libhibernate-validator-java-4.0.2.GA/0000755000175000017500000000000011402110405017257 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/0000755000175000017500000000000011402110404024444 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/license.txt0000644000175000017500000002613611144263744026662 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/readme.txt0000644000175000017500000000231011070443223026447 0ustar twernertwernerHibernate Validator ================================================== Version: 3.1.0.GA, 10.09.2008 Description ----------- Hibernate Validator aims at defining and checking a domain model level constraints. It supports custom constraints definitions as well as full internationalization. Annotations are used to define constraints on object level. The validation mechanism can be executed in different layers in your application without having to duplicate any of these rules (presentation layer, data access layer, Database schema). Hibernate Requires Hibernate Core 3.2 and above. This version runs well with Hibernate Annotations 3.3.x and Hibernate EntityManager 3.3.x Instructions ------------ Unzip to installation directory, read doc/reference Contact ------------ Latest Documentation: http://www.hibernate.org Bug Reports: Hibernate JIRA (preferred) hibernate-devel@lists.sourceforge.net Free Technical Support: http://forum.hibernate.org (http://forum.hibernate.org/viewforum.php?f=9) Notes ----------- If you want to contribute, go to http://www.hibernate.org/ This software and its documentation are distributed under the terms of the FSF Lesser Gnu Public License (see lgpl.txt).libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/0000755000175000017500000000000011402110375025242 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/0000755000175000017500000000000011402110374026220 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/0000755000175000017500000000000011402110375030233 5ustar twernertwerner././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages_da.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages0000644000175000017500000000031111173623006033573 0ustar twernertwerner#overriding of default keys #specific to my project long=is too damn long floor.name=Floor out.of.range=lower that {min} and greater than {max} floor.out.of.range={floor.name} cannot be {out.of.range}././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/hibernate.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/hibernate.propert0000644000175000017500000003077011173623006033625 0ustar twernertwerner###################### ### Query Language ### ###################### ## define query language constants / function names hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N' ## select the classic query parser #hibernate.query.factory_class org.hibernate.hql.classic.ClassicQueryTranslatorFactory hibernate.format_sql true ################# ### Platforms ### ################# ## JNDI Datasource #hibernate.connection.datasource jdbc/test #hibernate.connection.username db2 #hibernate.connection.password db2 ## HypersonicSQL hibernate.dialect org.hibernate.dialect.HSQLDialect hibernate.connection.driver_class org.hsqldb.jdbcDriver hibernate.connection.username sa hibernate.connection.password hibernate.connection.url jdbc:hsqldb:hsql://localhost hibernate.connection.url jdbc:hsqldb:test hibernate.connection.url jdbc:hsqldb:. ## MySQL #hibernate.dialect org.hibernate.dialect.MySQLDialect #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect #hibernate.connection.driver_class com.mysql.jdbc.Driver #hibernate.connection.url jdbc:mysql:///test #hibernate.connection.username emmanuel #hibernate.connection.password ## Oracle #hibernate.dialect org.hibernate.dialect.OracleDialect #hibernate.dialect org.hibernate.dialect.Oracle9Dialect #hibernate.connection.driver_class oracle.jdbc.driver.OracleDriver #hibernate.connection.username ora #hibernate.connection.password ora #hibernate.connection.url jdbc:oracle:thin:@localhost:1521:test ## PostgreSQL #hibernate.dialect org.hibernate.dialect.PostgreSQLDialect #hibernate.connection.driver_class org.postgresql.Driver #hibernate.connection.url jdbc:postgresql:annotations #hibernate.connection.username postgres #hibernate.connection.password hibernate #hibernate.query.substitutions yes 'Y', no 'N' ## DB2 #hibernate.dialect org.hibernate.dialect.DB2Dialect #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver #hibernate.connection.url jdbc:db2:test #hibernate.connection.username db2 #hibernate.connection.password db2 ## TimesTen (not supported yet) #hibernate.dialect org.hibernate.dialect.TimesTenDialect #hibernate.connection.driver_class com.timesten.jdbc.TimesTenDriver #hibernate.connection.url jdbc:timesten:direct:test #hibernate.connection.username #hibernate.connection.password ## DB2/400 #hibernate.dialect org.hibernate.dialect.DB2400Dialect #hibernate.connection.username user #hibernate.connection.password password ## Native driver #hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver #hibernate.connection.url jdbc:db2://systemname ## Toolbox driver #hibernate.connection.driver_class com.ibm.as400.access.AS400JDBCDriver #hibernate.connection.url jdbc:as400://systemname ## Derby (Not supported!) #hibernate.dialect org.hibernate.dialect.DerbyDialect #hibernate.connection.driver_class org.apache.derby.jdbc.EmbeddedDriver #hibernate.connection.username #hibernate.connection.password #hibernate.connection.url jdbc:derby:/test;create=true ## Sybase #hibernate.dialect org.hibernate.dialect.SybaseDialect #hibernate.connection.driver_class com.sybase.jdbc2.jdbc.SybDriver #hibernate.connection.username sa #hibernate.connection.password sasasa #hibernate.connection.url jdbc:sybase:Tds:co3061835-a:5000/tempdb ## Mckoi SQL #hibernate.dialect org.hibernate.dialect.MckoiDialect #hibernate.connection.driver_class com.mckoi.JDBCDriver #hibernate.connection.url jdbc:mckoi:/// #hibernate.connection.url jdbc:mckoi:local://C:/mckoi1.00/db.conf #hibernate.connection.username admin #hibernate.connection.password nimda ## SAP DB #hibernate.dialect org.hibernate.dialect.SAPDBDialect #hibernate.connection.driver_class com.sap.dbtech.jdbc.DriverSapDB #hibernate.connection.url jdbc:sapdb://localhost/TST #hibernate.connection.username TEST #hibernate.connection.password TEST #hibernate.query.substitutions yes 'Y', no 'N' ## MS SQL Server #hibernate.dialect org.hibernate.dialect.SQLServerDialect #hibernate.connection.username sa #hibernate.connection.password sa ## JSQL Driver #hibernate.connection.driver_class com.jnetdirect.jsql.JSQLDriver #hibernate.connection.url jdbc:JSQLConnect://1E1/test ## JTURBO Driver #hibernate.connection.driver_class com.newatlanta.jturbo.driver.Driver #hibernate.connection.url jdbc:JTurbo://1E1:1433/test ## WebLogic Driver #hibernate.connection.driver_class weblogic.jdbc.mssqlserver4.Driver #hibernate.connection.url jdbc:weblogic:mssqlserver4:1E1:1433 ## Microsoft Driver (not recommended!) #hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver #hibernate.connection.url jdbc:microsoft:sqlserver://1E1;DatabaseName=test;SelectMethod=cursor ## jTDS (since version 0.9) #hibernate.connection.driver_class net.sourceforge.jtds.jdbc.Driver #hibernate.connection.url jdbc:jtds:sqlserver://1E1/test ## Interbase #hibernate.dialect org.hibernate.dialect.InterbaseDialect #hibernate.connection.username sysdba #hibernate.connection.password masterkey ## DO NOT specify hibernate.connection.sqlDialect ## InterClient #hibernate.connection.driver_class interbase.interclient.Driver #hibernate.connection.url jdbc:interbase://localhost:3060/C:/firebird/test.gdb ## Pure Java #hibernate.connection.driver_class org.firebirdsql.jdbc.FBDriver #hibernate.connection.url jdbc:firebirdsql:localhost/3050:/firebird/test.gdb ## Pointbase #hibernate.dialect org.hibernate.dialect.PointbaseDialect #hibernate.connection.driver_class com.pointbase.jdbc.jdbcUniversalDriver #hibernate.connection.url jdbc:pointbase:embedded:sample #hibernate.connection.username PBPUBLIC #hibernate.connection.password PBPUBLIC ################################# ### Hibernate Connection Pool ### ################################# hibernate.connection.pool_size 1 ########################### ### C3P0 Connection Pool### ########################### #hibernate.c3p0.max_size 2 #hibernate.c3p0.min_size 2 #hibernate.c3p0.timeout 5000 #hibernate.c3p0.max_statements 100 #hibernate.c3p0.idle_test_period 3000 #hibernate.c3p0.acquire_increment 2 #hibernate.c3p0.validate false ############################## ### Proxool Connection Pool### ############################## ## Properties for external configuration of Proxool hibernate.proxool.pool_alias pool1 ## Only need one of the following #hibernate.proxool.existing_pool true #hibernate.proxool.xml proxool.xml #hibernate.proxool.properties proxool.properties ################################# ### Plugin ConnectionProvider ### ################################# ## use a custom ConnectionProvider (if not set, Hibernate will choose a built-in ConnectionProvider using hueristics) #hibernate.connection.provider_class org.hibernate.connection.DriverManagerConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.DatasourceConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.C3P0ConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.DBCPConnectionProvider #hibernate.connection.provider_class org.hibernate.connection.ProxoolConnectionProvider ####################### ### Transaction API ### ####################### ## Enable automatic flush during the JTA beforeCompletion() callback ## (This setting is relevant with or without the Transaction API) #hibernate.transaction.flush_before_completion ## Enable automatic session close at the end of transaction ## (This setting is relevant with or without the Transaction API) #hibernate.transaction.auto_close_session ## the Transaction API abstracts application code from the underlying JTA or JDBC transactions #hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory #hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory ## to use JTATransactionFactory, Hibernate must be able to locate the UserTransaction in JNDI ## default is java:comp/UserTransaction ## you do NOT need this setting if you specify hibernate.transaction.manager_lookup_class #jta.UserTransaction jta/usertransaction #jta.UserTransaction javax.transaction.UserTransaction #jta.UserTransaction UserTransaction ## to use the second-level cache with JTA, Hibernate must be able to obtain the JTA TransactionManager #hibernate.transaction.manager_lookup_class org.hibernate.transaction.JBossTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WeblogicTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.WebSphereTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.OrionTransactionManagerLookup #hibernate.transaction.manager_lookup_class org.hibernate.transaction.ResinTransactionManagerLookup ############################## ### Miscellaneous Settings ### ############################## ## print all generated SQL to the console #hibernate.show_sql true ## add comments to the generated SQL #hibernate.use_sql_comments true ## generate statistics #hibernate.generate_statistics true ## auto schema export #hibernate.hbm2ddl.auto create-drop #hibernate.hbm2ddl.auto create #hibernate.hbm2ddl.auto update ## specify a default schema and catalog for unqualified tablenames #hibernate.default_schema test #hibernate.default_catalog test ## enable ordering of SQL UPDATEs by primary key hibernate.order_updates true ## set the maximum depth of the outer join fetch tree hibernate.max_fetch_depth 1 ## set the default batch size for batch fetching hibernate.default_batch_fetch_size 100 ## rollback generated identifier values of deleted entities to default values #hibernate.use_identifer_rollback true ## enable CGLIB reflection optimizer (enabled by default) #hibernate.cglib.use_reflection_optimizer false ##################### ### JDBC Settings ### ##################### ## specify a JDBC isolation level #hibernate.connection.isolation 4 ## enable JDBC autocommit (not recommended!) #hibernate.connection.autocommit true ## set the JDBC fetch size #hibernate.jdbc.fetch_size 25 ## set the maximum JDBC 2 batch size (a nonzero value enables batching) #hibernate.jdbc.batch_size 0 ## enable batch updates even for versioned data hibernate.jdbc.batch_versioned_data true ## enable use of JDBC 2 scrollable ResultSets (specifying a Dialect will cause Hibernate to use a sensible default) #hibernate.jdbc.use_scrollable_resultset true ## use streams when writing binary types to / from JDBC hibernate.jdbc.use_streams_for_binary true ## use JDBC 3 PreparedStatement.getGeneratedKeys() to get the identifier of an inserted row #hibernate.jdbc.use_get_generated_keys false ## choose a custom JDBC batcher # hibernate.jdbc.factory_class ## enable JDBC result set column alias caching ## (minor performance enhancement for broken JDBC drivers) # hibernate.jdbc.wrap_result_sets ## choose a custom SQL exception converter #hibernate.jdbc.sql_exception_converter ########################## ### Second-level Cache ### ########################## ## optimize chache for minimal "puts" instead of minimal "gets" (good for clustered cache) #hibernate.cache.use_minimal_puts true ## set a prefix for cache region names hibernate.cache.region_prefix hibernate.test ## disable the second-level cache #hibernate.cache.use_second_level_cache false ## enable the query cache hibernate.cache.use_query_cache true ## store the second-level cache entries in a more human-friendly format #hibernate.cache.use_structured_entries true ## choose a cache implementation #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider ## choose a custom query cache implementation #hibernate.cache.query_cache_factory ############ ### JNDI ### ############ ## specify a JNDI name for the SessionFactory #hibernate.session_factory_name hibernate/session_factory ## Hibernate uses JNDI to bind a name to a SessionFactory and to look up the JTA UserTransaction; ## if hibernate.jndi.* are not specified, Hibernate will use the default InitialContext() which ## is the best approach in an application server #file system #hibernate.jndi.class com.sun.jndi.fscontext.RefFSContextFactory #hibernate.jndi.url file:/ #WebSphere #hibernate.jndi.class com.ibm.websphere.naming.WsnInitialContextFactory #hibernate.jndi.url iiop://localhost:900/ ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages_fr.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages0000644000175000017500000000033011173623006033574 0ustar twernertwerner#overriding of default keys #specific to my project long=est grave trop long floor.name=Etage out.of.range=plus petit que {min} ou plus grand que {max} floor.out.of.range={floor.name} ne peut pas être {out.of.range}././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/ValidatorMessages0000644000175000017500000000031111173623006033573 0ustar twernertwerner#overriding of default keys #specific to my project long=is too damn long floor.name=Floor out.of.range=lower that {min} and greater than {max} floor.out.of.range={floor.name} cannot be {out.of.range}libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/log4j.properties0000644000175000017500000000302011173623006033370 0ustar twernertwerner### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file hibernate.log ### #log4j.appender.file=org.apache.log4j.FileAppender #log4j.appender.file.File=hibernate.log #log4j.appender.file.layout=org.apache.log4j.PatternLayout #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=warn, stdout log4j.logger.org.hibernate=warn ### log just the SQL log4j.logger.org.hibernate.SQL=warn #log4j.logger.org.hibernate.engine.CascadingAction=debug ### log JDBC bind parameters ### #log4j.logger.org.hibernate.type=debug ### log schema export/update ### log4j.logger.org.hibernate.tool.hbm2ddl=warn ### log cache activity ### #log4j.logger.org.hibernate.cache=debug ### enable the following line if you want to track down connection ### ### leakages when using DriverManagerConnectionProvider ### #log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace ### annotation logs #log4j.logger.org.hibernate.annotation=info #log4j.logger.org.hibernate.cfg=info #log4j.logger.org.hibernate.cfg.SettingsFactory=info #log4j.logger.org.hibernate.cfg.AnnotationBinder=info #log4j.logger.org.hibernate.cfg.AnnotationConfiguration=info #log4j.logger.org.hibernate.cfg.Ejb3Column=info././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/messages_en.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/resources/messages_en.prope0000644000175000017500000000114011173623006033574 0ustar twernertwernerlong=is too damn long floor.name=Floor out.of.range=lower that {min} and greater than {max} floor.out.of.range={floor.name} cannot (escaping #{el}) be {out.of.range} validator.assertFalse=assertion failed validator.assertTrue=assertion failed validator.length=length must be between {min} and {max} validator.max=must less than or equal to {value} validator.min=must greater than or equal to {value} validator.notNull=may not be null validator.past=must be a past date validator.pattern=must match "{regex}" validator.range=must be between {min} and {max} validator.size=size must be between {min} and {max}libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/0000755000175000017500000000000011402110370027135 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/0000755000175000017500000000000011402110370027724 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/0000755000175000017500000000000011402110370031665 5ustar twernertwerner././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110370033411 5ustar twernertwerner././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110374033415 5ustar twernertwerner././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/ValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000002417511131662636033444 0ustar twernertwerner//$Id: ValidatorTest.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import java.io.Serializable; import java.io.ByteArrayOutputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ByteArrayInputStream; import java.io.ObjectInputStream; import java.math.BigInteger; import java.util.Date; import java.util.Locale; import java.util.ResourceBundle; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; import org.hibernate.validator.MessageInterpolator; import org.hibernate.validator.Validator; /** * @author Gavin King */ public class ValidatorTest extends TestCase { public static final String ESCAPING_EL = "(escaping #{el})"; public void testValidator() { Address a = new Address(); Address.blacklistedZipCode = null; a.setCountry( "Australia" ); a.setZip( "1221341234123" ); a.setState( "Vic" ); a.setLine1( "Karbarook Ave" ); a.setId( 3 ); ClassValidator
classValidator = new ClassValidator
( Address.class, ResourceBundle.getBundle( "messages", Locale.ENGLISH ) ); InvalidValue[] validationMessages = classValidator.getInvalidValues( a ); assertEquals( 2, validationMessages.length ); //static field is tested also Address.blacklistedZipCode = "323232"; a.setZip( null ); a.setState( "Victoria" ); validationMessages = classValidator.getInvalidValues( a ); assertEquals( 2, validationMessages.length ); validationMessages = classValidator.getInvalidValues( a, "zip" ); assertEquals( 1, validationMessages.length ); a.setZip( "3181" ); a.setState( "NSW" ); validationMessages = classValidator.getInvalidValues( a ); assertEquals( 0, validationMessages.length ); a.setCountry( null ); validationMessages = classValidator.getInvalidValues( a ); assertEquals( 1, validationMessages.length ); a.setInternalValid( false ); validationMessages = classValidator.getInvalidValues( a ); assertEquals( 2, validationMessages.length ); a.setInternalValid( true ); a.setCountry( "France" ); a.floor = 4000; validationMessages = classValidator.getInvalidValues( a ); assertEquals( 2, validationMessages.length ); assertEquals( "Floor cannot " + ESCAPING_EL + " be lower that -2 and greater than 50 " + ESCAPING_EL, validationMessages[0].getMessage() ); } public void testCircularity() throws Exception { Brother emmanuel = new Brother(); emmanuel.setName( "Emmanuel" ); Address.blacklistedZipCode = "666"; Address address = new Address(); address.setInternalValid( true ); address.setCountry( "France" ); address.setId( 3 ); address.setLine1( "Rue des rosiers" ); address.setState( "NYC" ); address.setZip( "33333" ); address.floor = 4; emmanuel.setAddress( address ); Brother christophe = new Brother(); christophe.setName( "Christophe" ); christophe.setAddress( address ); emmanuel.setYoungerBrother( christophe ); christophe.setElder( emmanuel ); ClassValidator classValidator = new ClassValidator( Brother.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( emmanuel ); assertEquals( 0, invalidValues.length ); christophe.setName( null ); invalidValues = classValidator.getInvalidValues( emmanuel ); assertEquals( 1, invalidValues.length ); assertEquals( emmanuel, invalidValues[0].getRootBean() ); assertEquals( "youngerBrother.name", invalidValues[0].getPropertyPath() ); christophe.setName( "Christophe" ); address = new Address(); address.setInternalValid( true ); address.setCountry( "France" ); address.setId( 4 ); address.setLine1( "Rue des plantes" ); address.setState( "NYC" ); address.setZip( "33333" ); address.floor = -100; christophe.setAddress( address ); invalidValues = classValidator.getInvalidValues( emmanuel ); assertEquals( 1, invalidValues.length ); } public void testAggregationAnnotations() throws Exception { Engine eng = new Engine(); eng.setHorsePower( 23 ); eng.setSerialNumber( "23-43###4" ); ClassValidator classValidator = new ClassValidator( Engine.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( eng ); assertEquals( 2, invalidValues.length ); eng.setSerialNumber( "1234-5678-9012"); invalidValues = classValidator.getInvalidValues( eng ); assertEquals( 0, invalidValues.length ); } public void testDefaultResourceBundle() throws Exception { Tv tv = new Tv(); tv.serial = "FS"; tv.name = "TooLong"; tv.expDate = new Date( new Date().getTime() + 1000 * 60 * 60 * 24 * 10 ); ClassValidator classValidator = new ClassValidator( Tv.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( tv ); assertEquals( 1, invalidValues.length ); Locale loc = Locale.getDefault(); if ( loc.toString().startsWith( "en" ) ) { assertEquals( "length must be between 0 and 2", invalidValues[0].getMessage() ); } else if ( loc.toString().startsWith( "fr" ) ) { String message = invalidValues[0].getMessage(); String message2 ="la longueur doit être entre 0 et 2"; assertEquals( message2, message ); } else if ( loc.toString().startsWith( "da" ) ) { assertEquals( "længden skal være mellem 0 og 2", invalidValues[0].getMessage() ); } else { // if default not found then it must be english assertEquals( "length must be between 0 and 2", invalidValues[0].getMessage() ); } } public void testSerialization() throws Exception { Tv tv = new Tv(); tv.serial = "FS"; tv.name = "TooLong"; tv.expDate = new Date( new Date().getTime() + 1000 * 60 * 60 * 24 * 10 ); ClassValidator classValidator = new ClassValidator( Tv.class ); ByteArrayOutputStream stream = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream( stream ); out.writeObject( classValidator ); out.close(); byte[] serialized = stream.toByteArray(); stream.close(); ByteArrayInputStream byteIn = new ByteArrayInputStream( serialized ); ObjectInputStream in = new ObjectInputStream( byteIn ); classValidator = (ClassValidator) in.readObject(); in.close(); byteIn.close(); InvalidValue[] invalidValues = classValidator.getInvalidValues( tv ); assertEquals( 1, invalidValues.length ); Locale loc = Locale.getDefault(); if ( loc.toString().startsWith( "en" ) ) { assertEquals( "length must be between 0 and 2", invalidValues[0].getMessage() ); } else if ( loc.toString().startsWith( "fr" ) ) { String message = invalidValues[0].getMessage(); String message2 ="la longueur doit être entre 0 et 2"; assertEquals( message2, message ); } else if ( loc.toString().startsWith( "da" ) ) { assertEquals( "længden skal være mellem 0 og 2", invalidValues[0].getMessage() ); } else { // if default not found then it must be english assertEquals( "length must be between 0 and 2", invalidValues[0].getMessage() ); } } public class PrefixMessageInterpolator implements MessageInterpolator, Serializable { private String prefix; public PrefixMessageInterpolator(String prefix) { this.prefix = prefix; } public String interpolate(String message, Validator validator, MessageInterpolator defaultInterpolator) { return prefix + defaultInterpolator.interpolate( message, validator, defaultInterpolator ); } } public void testMessageInterpolator() throws Exception { Tv tv = new Tv(); tv.serial = "FS"; tv.name = "TooLong"; tv.expDate = new Date( new Date().getTime() + 1000 * 60 * 60 * 24 * 10 ); String prefix = "Prefix"; ClassValidator classValidator = new ClassValidator( Tv.class, new PrefixMessageInterpolator( prefix ) ); InvalidValue[] invalidValues = classValidator.getInvalidValues( tv ); assertEquals( 1, invalidValues.length ); Locale loc = Locale.getDefault(); if ( loc.toString().startsWith( "en" ) ) { assertEquals( prefix + "length must be between 0 and 2", invalidValues[0].getMessage() ); } else if ( loc.toString().startsWith( "fr" ) ) { assertEquals( prefix + "la longueur doit être entre 0 et 2", invalidValues[0].getMessage() ); } else if ( loc.toString().startsWith( "da" ) ) { assertEquals( prefix + "længden skal være mellem 0 og 2", invalidValues[0].getMessage() ); } else { // if default not found then it must be english assertEquals( prefix + "length must be between 0 and 2", invalidValues[0].getMessage() ); } } public void testBigInteger() throws Exception { Tv tv = new Tv(); tv.lifetime = new BigInteger("9223372036854775808"); ClassValidator classValidator = new ClassValidator( Tv.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( tv ); assertEquals( 0, invalidValues.length ); } public void testBeanValidator() throws Exception { Vase v = new Vase(); ClassValidator classValidator = new ClassValidator( Vase.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( v ); assertEquals( 1, invalidValues.length ); assertNull( invalidValues[0].getPropertyName() ); } public void testPotentialInvalidValues() throws Exception { Address a = new Address(); Address.blacklistedZipCode = null; a.setCountry( "Australia" ); a.setZip( "1221341234123" ); a.setState( "Vic" ); a.setLine1( "Karbarook Ave" ); a.setId( 3 ); ClassValidator
classValidator = new ClassValidator
( Address.class ); InvalidValue[] validationMessages = classValidator.getPotentialInvalidValues( "blacklistedZipCode", Address.blacklistedZipCode ); assertEquals( 1, validationMessages.length ); } public void testRecursivity() throws Exception { Site site = new Site(); site.setSiteName( "Rocky mountains" ); Contact contact = new Contact(); contact.setName( null ); //1 error contact.setPhone( "01234455" ); site.setContact( contact ); Address a = new Address(); Address.blacklistedZipCode = "222"; a.setCountry( "Australia" ); a.setZip( "123" ); a.setState( "Vic" ); a.setLine1( null ); // 1 more error a.setId( 3 ); site.setAddress( a ); ClassValidator classValidator = new ClassValidator( Site.class ); InvalidValue[] validationMessages = classValidator.getInvalidValues( site ); assertEquals( 2, validationMessages.length ); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110372033413 5ustar twernertwerner././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/MartianPk.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000204111052766205033427 0ustar twernertwerner//$Id: MartianPk.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import java.io.Serializable; import javax.persistence.Embeddable; import org.hibernate.validator.Length; /** * @author Emmanuel Bernard */ @Embeddable public class MartianPk implements Serializable { private String name; private String colony; public String getName() { return name; } public void setName(String name) { this.name = name; } @Length(max = 4) public String getColony() { return colony; } public void setColony(String colony) { this.colony = colony; } public boolean equals(Object o) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; final MartianPk martianPk = (MartianPk) o; if ( !colony.equals( martianPk.colony ) ) return false; if ( !name.equals( martianPk.name ) ) return false; return true; } public int hashCode() { int result; result = name.hashCode(); result = 29 * result + colony.hashCode(); return result; } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Venusian.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000130211052766205033426 0ustar twernertwerner//$Id: Venusian.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.IdClass; import org.hibernate.validator.Length; /** * @author Emmanuel Bernard */ @Entity @IdClass(VenusianPk.class) public class Venusian implements Serializable { private String region; private String name; @Id @Length(min = 3) public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } @Id public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/PrefixMessageInterpolator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000106411052766205033433 0ustar twernertwerner//$Id: PrefixMessageInterpolator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import org.hibernate.validator.MessageInterpolator; import org.hibernate.validator.Validator; /** * @author Emmanuel Bernard */ public class PrefixMessageInterpolator implements MessageInterpolator { public String interpolate(String message, Validator validator, MessageInterpolator defaultInterpolator) { return "prefix_" + defaultInterpolator.interpolate( message, validator, defaultInterpolator ); } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Address.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000361111052766205033433 0ustar twernertwerner//$Id: Address.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Transient; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.Length; import org.hibernate.validator.Min; import org.hibernate.validator.NotNull; import org.hibernate.validator.Pattern; import org.hibernate.validator.Range; /** * @author Gavin King */ @Entity public class Address { @NotNull public static String blacklistedZipCode; private String line1; private String line2; private String zip; private String state; @Length(max = 20) @NotNull private String country; private long id; private boolean internalValid = true; @Range(min = -2, max = 50, message = "{floor.out.of.range} (escaping #{el})") public int floor; public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @NotNull public String getLine1() { return line1; } public void setLine1(String line1) { this.line1 = line1; } public String getLine2() { return line2; } public void setLine2(String line2) { this.line2 = line2; } @Length(max = 3) @NotNull public String getState() { return state; } public void setState(String state) { this.state = state; } @Length(max = 5, message = "{long}") @Pattern(regex = "[0-9]+") @NotNull public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } @AssertTrue @Transient public boolean isValid() { return true; } @AssertTrue @Transient private boolean isInternalValid() { return internalValid; } public void setInternalValid(boolean internalValid) { this.internalValid = internalValid; } @Id @Min(1) @Range(max = 2000) public long getId() { return id; } public void setId(long id) { this.id = id; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Rock.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000045711052766205033440 0ustar twernertwerner//$Id: Rock.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Entity; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ @Entity public class Rock extends Music { @NotNull public Integer bit; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/TvOwner.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000070111052766205033430 0ustar twernertwerner//$Id: TvOwner.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ @Entity public class TvOwner { @Id @GeneratedValue public Integer id; @ManyToOne @NotNull public Tv tv; } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Tv.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000116611052766205033436 0ustar twernertwerner//$Id: Tv.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import java.util.Date; import java.math.BigInteger; import javax.persistence.Entity; import javax.persistence.Id; import org.hibernate.validator.Future; import org.hibernate.validator.Length; import org.hibernate.validator.Min; /** * @author Emmanuel Bernard */ @Entity public class Tv { @Id @Length(max = 2) public String serial; public int size; @Length(max = 2) public String name; @Future public Date expDate; @Length(min = 0) public String description; @Min(1000) public BigInteger lifetime; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Martian.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000104111052766205033426 0ustar twernertwerner//$Id: Martian.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Entity; import javax.persistence.Id; /** * @author Emmanuel Bernard */ @Entity public class Martian { private MartianPk id; private MarsAddress address; @Id public MartianPk getId() { return id; } public void setId(MartianPk id) { this.id = id; } public MarsAddress getAddress() { return address; } public void setAddress(MarsAddress address) { this.address = address; } } ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/EmbeddedObjectTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000335311227341572033436 0ustar twernertwerner//$Id: EmbeddedObjectTest.java 17095 2009-07-15 11:54:34Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreUpdateEventListener; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.event.ValidatePreInsertEventListener; import org.hibernate.validator.event.ValidatePreUpdateEventListener; import org.hibernate.validator.test.HANTestCase; /** * @author Emmanuel Bernard */ @SuppressWarnings({ "deprecation" }) public class EmbeddedObjectTest extends HANTestCase { public void testNotNullEmbeddedObject() throws Exception { CreditCard cc = new CreditCard(); User username = new User(); username.setFirstname( "Emmanuel" ); username.setMiddlename( "P" ); username.setLastname( "Bernard" ); cc.setUsername( username ); ClassValidator ccValid = new ClassValidator( CreditCard.class ); assertEquals( 0, ccValid.getInvalidValues( cc ).length ); username.setMiddlename( null ); assertEquals( 0, ccValid.getInvalidValues( cc ).length ); Session s = openSession(); Transaction tx = s.beginTransaction(); s.persist( cc ); s.flush(); tx.rollback(); s.close(); } protected Class[] getMappings() { return new Class[]{ CreditCard.class }; } protected void configure(Configuration cfg) { cfg.getEventListeners() .setPreInsertEventListeners( new PreInsertEventListener[]{new ValidatePreInsertEventListener()} ); cfg.getEventListeners() .setPreUpdateEventListeners( new PreUpdateEventListener[]{new ValidatePreUpdateEventListener()} ); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/CreditCard.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000140511052766205033432 0ustar twernertwerner//$Id: CreditCard.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ @Entity public class CreditCard { @Id @GeneratedValue private Integer id; @Embedded @Valid @NotNull private User username; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public User getUsername() { return username; } public void setUsername(User username) { this.username = username; } } ././@LongLink0000000000000000000000000000024100000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/HibernateAnnotationIntegrationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000001332411222147453033432 0ustar twernertwerner//$Id: HibernateAnnotationIntegrationTest.java 16963 2009-06-29 14:26:51Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.validator.Environment; import org.hibernate.validator.InvalidStateException; import org.hibernate.validator.test.HANTestCase; /** * Test the validate framework integration with the Hibernate * metadata binding * * @author Emmanuel Bernard */ public class HibernateAnnotationIntegrationTest extends HANTestCase { public void testApply() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( Address.class.getName() ); //new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) ).apply( classMapping ); Column stateColumn = (Column) classMapping.getProperty( "state" ).getColumnIterator().next(); assertEquals( stateColumn.getLength(), 3 ); Column zipColumn = (Column) classMapping.getProperty( "zip" ).getColumnIterator().next(); assertEquals( zipColumn.getLength(), 5 ); assertFalse( zipColumn.isNullable() ); } public void testApplyOnIdColumn() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( Tv.class.getName() ); Column serialColumn = (Column) classMapping.getIdentifierProperty().getColumnIterator().next(); assertEquals( "Vaidator annotation not applied on ids", 2, serialColumn.getLength() ); } public void testApplyOnManyToOne() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( TvOwner.class.getName() ); Column serialColumn = (Column) classMapping.getProperty( "tv" ).getColumnIterator().next(); assertEquals( "Validator annotations not applied on associations", false, serialColumn.isNullable() ); } public void testSingleTableAvoidNotNull() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( Rock.class.getName() ); Column serialColumn = (Column) classMapping.getProperty( "bit" ).getColumnIterator().next(); assertTrue( "Notnull should not be applised on single tables", serialColumn.isNullable() ); } public void testEvents() throws Exception { Session s; Transaction tx; Address a = new Address(); Address.blacklistedZipCode = "3232"; a.setId( 12 ); a.setCountry( "Country" ); a.setLine1( "Line 1" ); a.setZip( "nonnumeric" ); a.setState( "NY" ); s = openSession(); tx = s.beginTransaction(); try { s.persist( a ); tx.commit(); fail( "bean should have been validated" ); } catch (InvalidStateException e) { //success assertEquals( 2, e.getInvalidValues().length ); assertTrue( "Environment.MESSAGE_INTERPOLATOR_CLASS does not work", e.getInvalidValues()[0].getMessage().startsWith( "prefix_") ); } finally { if ( tx != null ) tx.rollback(); s.close(); } a = new Address(); Address.blacklistedZipCode = "3232"; a.setId( 12 ); a.setCountry( "Country" ); a.setLine1( "Line 1" ); a.setZip( "12345" ); a.setState( "NY" ); s = openSession(); tx = s.beginTransaction(); s.persist( a ); tx.commit(); a.setState( "WAYTOOLONG" ); s = openSession(); tx = s.beginTransaction(); try { s.merge( a ); tx.commit(); fail( "bean should have been validated" ); } catch (InvalidStateException e) { //success assertEquals( 1, e.getInvalidValues().length ); assertTrue( "Environment.MESSAGE_INTERPOLATOR_CLASS does not work", e.getInvalidValues()[0].getMessage().startsWith( "prefix_") ); } finally { if ( tx != null ) tx.rollback(); s.close(); } s = openSession(); tx = s.beginTransaction(); a.setId( 13 ); a.setCountry( "Country" ); a.setLine1( "Line 1" ); a.setZip( "4343" ); a.setState( "NY" ); s.persist( a ); s.flush(); a.setState( "TOOLONG" ); try { s.flush(); fail( "update should have been checked" ); } catch (InvalidStateException e) { assertEquals( 1, e.getInvalidValues().length ); } finally { s.clear(); for (Object o : s.createCriteria( Address.class ).list() ) { s.delete( o ); } tx.commit(); s.close(); } } public void testComponents() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); Martian martian = new Martian(); MartianPk pk = new MartianPk(); pk.setColony( "Liberal" ); //one failure pk.setName( "Biboudie" ); MarsAddress address = new MarsAddress(); address.setContinent( "cont" ); //one failure address.setCanal( "Plus" ); //one failure martian.setId( pk ); martian.setAddress( address ); s.persist( martian ); try { s.flush(); fail( "Components are not validated" ); } catch (InvalidStateException e) { assertEquals( 2, e.getInvalidValues().length ); } finally { tx.rollback(); s.close(); } } public void testIdClass() throws Exception { Session s; Transaction tx; s = openSession(); tx = s.beginTransaction(); Venusian venus = new Venusian(); venus.setName( "bibi" ); venus.setRegion( "ts" ); s.persist( venus ); try { s.flush(); fail( "test on embedded properties should have been done" ); } catch (InvalidStateException e) { assertEquals( 1, e.getInvalidValues().length ); } finally { tx.rollback(); s.close(); } } protected void configure(Configuration cfg) { cfg.setProperty( Environment.MESSAGE_INTERPOLATOR_CLASS, PrefixMessageInterpolator.class.getName() ); } protected Class[] getMappings() { return new Class[]{ Address.class, Martian.class, Venusian.class, Tv.class, TvOwner.class, Music.class, Rock.class }; } public HibernateAnnotationIntegrationTest(String x) { super( x ); } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/User.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000146111052766205033434 0ustar twernertwerner//$Id: User.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Embeddable; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ @Embeddable public class User { @NotNull private String firstname; private String middlename; @NotNull private String lastname; public String getFirstname() { return firstname; } public void setFirstname(String firstname) { this.firstname = firstname; } public String getLastname() { return lastname; } public void setLastname(String lastname) { this.lastname = lastname; } public String getMiddlename() { return middlename; } public void setMiddlename(String middlename) { this.middlename = middlename; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/VenusianPk.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000165311052766205033437 0ustar twernertwerner//$Id: VenusianPk.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import java.io.Serializable; /** * @author Emmanuel Bernard */ public class VenusianPk implements Serializable { private String region; private String name; public String getRegion() { return region; } public void setRegion(String region) { this.region = region; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean equals(Object o) { if ( this == o ) return true; if ( o == null || getClass() != o.getClass() ) return false; final VenusianPk that = (VenusianPk) o; if ( !name.equals( that.name ) ) return false; if ( !region.equals( that.region ) ) return false; return true; } public int hashCode() { int result; result = region.hashCode(); result = 29 * result + name.hashCode(); return result; } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/Music.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000042211052766205033430 0ustar twernertwerner//$Id: Music.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Entity; import javax.persistence.Id; /** * @author Emmanuel Bernard */ @Entity public class Music { @Id public String name; } ././@LongLink0000000000000000000000000000024500000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/NonHibernateAnnotationsIntegrationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000346711052766205033444 0ustar twernertwerner//$Id: NonHibernateAnnotationsIntegrationTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Column; import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreUpdateEventListener; import org.hibernate.cfg.Configuration; import org.hibernate.validator.Environment; import org.hibernate.validator.test.HANTestCase; import org.hibernate.validator.event.ValidateEventListener; import org.hibernate.Session; /** * Test the ability to disable DDL update * * @author Emmanuel Bernard */ public class NonHibernateAnnotationsIntegrationTest extends HANTestCase { public void testNotApplyDll() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( Address.class.getName() ); Column stateColumn = (Column) classMapping.getProperty( "state" ).getColumnIterator().next(); assertFalse( stateColumn.getLength() == 3 ); Column zipColumn = (Column) classMapping.getProperty( "zip" ).getColumnIterator().next(); assertFalse( zipColumn.getLength() == 5 ); assertTrue( zipColumn.isNullable() ); } public void testNotApplyListener() throws Exception { Session s = openSession( ); Address a = new Address(); s.persist( a ); //shouldn't fail s.flush(); s.close(); } protected void configure(Configuration cfg) { cfg.setProperty( Environment.MESSAGE_INTERPOLATOR_CLASS, PrefixMessageInterpolator.class.getName() ); cfg.setProperty( Environment.APPLY_TO_DDL, "false" ); cfg.setProperty( Environment.AUTOREGISTER_LISTENERS, "false" ); } protected Class[] getMappings() { return new Class[]{ Address.class, }; } public NonHibernateAnnotationsIntegrationTest(String x) { super( x ); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/haintegration/MarsAddress.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000120511052766205033430 0ustar twernertwerner//$Id: MarsAddress.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.haintegration; import javax.persistence.Embeddable; import org.hibernate.validator.Length; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ @Embeddable public class MarsAddress { private String continent; private String canal; @NotNull public String getContinent() { return continent; } public void setContinent(String continent) { this.continent = continent; } @Length(min = 5) public String getCanal() { return canal; } public void setCanal(String canal) { this.canal = canal; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Brother.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000202511131662636033432 0ustar twernertwerner//$Id: Brother.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class Brother { private String name; private Brother elder; private Brother youngerBrother; @NotNull @Valid private Address address; @NotNull public String getName() { return name; } public void setName(String name) { this.name = name; } @Valid public Brother getElder() { return elder; } public void setElder(Brother elder) { this.elder = elder; } @Valid public Brother getYoungerBrother() { return youngerBrother; } public void setYoungerBrother(Brother youngerBrother) { this.youngerBrother = youngerBrother; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public boolean equals(Object o) { return true; //workaround dummy equals and hashcode? } public int hashCode() { return 5; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Contact.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000075211131662636033437 0ustar twernertwerner//$Id: Contact.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class Contact { @NotNull private String name; @NotNull private String phone; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } }././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110373033414 5ustar twernertwerner././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/Car.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000136211052766205033434 0ustar twernertwerner//$Id: Car.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.validators; import java.math.BigDecimal; import javax.persistence.Id; import javax.persistence.GeneratedValue; import javax.persistence.Entity; import org.hibernate.validator.NotEmpty; import org.hibernate.validator.Digits; /** * @author Emmanuel Bernard */ @Entity public class Car { @Id @GeneratedValue public Long id; @NotEmpty public String name; @NotEmpty public String[] insurances; @Digits(integerDigits = 1, fractionalDigits = 2) public BigDecimal length; @Digits(integerDigits = 2, fractionalDigits = 1) public Double gallons; @Digits(integerDigits = 2, fractionalDigits = 1) public String mpg; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/CreditCard.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000050711052766205033434 0ustar twernertwerner//$Id: CreditCard.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.validators; import org.hibernate.validator.EAN; /** * @author Emmanuel Bernard */ public class CreditCard { @org.hibernate.validator.CreditCardNumber public String number; @EAN public String ean; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/DigitsTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000375711052766205033446 0ustar twernertwerner//$Id: DigitsTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.validators; import java.math.BigDecimal; import org.hibernate.cfg.Configuration; import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreUpdateEventListener; import org.hibernate.mapping.Column; import org.hibernate.mapping.PersistentClass; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; import org.hibernate.validator.test.HANTestCase; import org.hibernate.validator.event.ValidateEventListener; /** * @author Emmanuel Bernard */ public class DigitsTest extends HANTestCase { public void testDigits() throws Exception { Car car = new Car(); car.name = "350Z"; car.insurances = new String[] { "random" }; car.length = new BigDecimal(10.2); car.gallons = 100.3; car.mpg = "EFG"; ClassValidator classValidator = new ClassValidator( Car.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( car ); assertEquals( 3, invalidValues.length ); car.length = new BigDecimal(1.223); //more than 2 car.gallons = 10.300; //1 digit really so not invalid invalidValues = classValidator.getInvalidValues( car ); assertEquals( 2, invalidValues.length ); } public void testApply() throws Exception { PersistentClass classMapping = getCfg().getClassMapping( Car.class.getName() ); Column stateColumn = (Column) classMapping.getProperty( "gallons" ).getColumnIterator().next(); assertEquals( stateColumn.getPrecision(), 3 ); assertEquals( stateColumn.getScale(), 1 ); } protected void configure(Configuration cfg) { cfg.getEventListeners() .setPreInsertEventListeners( new PreInsertEventListener[]{new ValidateEventListener()} ); cfg.getEventListeners() .setPreUpdateEventListeners( new PreUpdateEventListener[]{new ValidateEventListener()} ); } protected Class[] getMappings() { return new Class[] { Car.class }; } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/LuhnTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000215011052766205033430 0ustar twernertwerner//$Id: LuhnTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.validators; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Emmanuel Bernard */ public class LuhnTest extends TestCase { public void testCreditCard() { CreditCard card = new CreditCard(); card.number = "1234567890123456"; ClassValidator classValidator = new ClassValidator( CreditCard.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( card ); assertEquals( 1, invalidValues.length ); card.number = "541234567890125"; //right CC (luhn compliant) invalidValues = classValidator.getInvalidValues( card ); assertEquals( 0, invalidValues.length ); card.ean = "9782266156066"; //right EAN invalidValues = classValidator.getInvalidValues( card ); assertEquals( 0, invalidValues.length ); card.ean = "9782266156067"; //wrong EAN invalidValues = classValidator.getInvalidValues( card ); assertEquals( 1, invalidValues.length ); } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/validators/NotEmptyTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000215711052766205033437 0ustar twernertwerner//$Id: NotEmptyTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.validators; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Gavin King */ public class NotEmptyTest extends TestCase { public void testBigInteger() throws Exception { Car car = new Car(); ClassValidator classValidator = new ClassValidator( Car.class ); InvalidValue[] invalidValues = classValidator.getInvalidValues( car ); assertEquals( 2, invalidValues.length ); car.name = ""; invalidValues = classValidator.getInvalidValues( car ); assertEquals( 2, invalidValues.length ); car.name = "350Z"; invalidValues = classValidator.getInvalidValues( car ); assertEquals( 1, invalidValues.length ); car.insurances = new String[0]; invalidValues = classValidator.getInvalidValues( car ); assertEquals( 1, invalidValues.length ); car.insurances = new String[1]; invalidValues = classValidator.getInvalidValues( car ); assertEquals( 0, invalidValues.length ); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/BooleanHolder.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000130511052766205033431 0ustar twernertwerner//$Id: BooleanHolder.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.AssertFalse; import org.hibernate.validator.AssertTrue; /** * @author Hardy Ferentschik */ public class BooleanHolder { @AssertTrue private Boolean mustBeTrue; @AssertFalse private Boolean mustBeFalse; public Boolean getMustBeTrue() { return mustBeTrue; } public void setMustBeTrue(Boolean mustBeTrue) { this.mustBeTrue = mustBeTrue; } public Boolean getMustBeFalse() { return mustBeFalse; } public void setMustBeFalse(Boolean mustBeFalse) { this.mustBeFalse = mustBeFalse; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/EmailTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000233211131662636033433 0ustar twernertwerner//$Id: EmailTest.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; /** * @author Emmanuel Bernard */ public class EmailTest extends TestCase { private ClassValidator userValidator; public void testEmail() throws Exception { userValidator = new ClassValidator(User.class); isRightEmail("emmanuel@hibernate.org"); isRightEmail(""); isRightEmail(null); isRightEmail("emmanuel@hibernate"); isRightEmail("emma-n_uel@hibernate"); isRightEmail("emma+nuel@hibernate.org"); isRightEmail("emma=nuel@hibernate.org"); isRightEmail("emmanuel@[123.12.2.11]"); isWrongEmail("emmanuel.hibernate.org"); isWrongEmail("emma nuel@hibernate.org"); isWrongEmail("emma(nuel@hibernate.org"); isWrongEmail("emmanuel@"); isWrongEmail("emma\nnuel@hibernate.org"); isWrongEmail("emma@nuel@hibernate.org"); } private void isRightEmail(String email) { assertEquals("Wrong email", 0, userValidator.getPotentialInvalidValues("email", email).length); } private void isWrongEmail(String email) { assertEquals("Right email", 1, userValidator.getPotentialInvalidValues("email", email).length); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Engine.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000142211052766205033431 0ustar twernertwerner//$Id: Engine.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.Patterns; import org.hibernate.validator.Pattern; /** * @author Emmanuel Bernard */ public class Engine { @Patterns( { @Pattern(regex = "^[A-Z0-9-]+$", message = "must contain alphabetical characters only"), @Pattern(regex = "^....-....-....$", message="must match ....-....-....") } ) private String serialNumber; private long horsePower; public String getSerialNumber() { return serialNumber; } public void setSerialNumber(String serialNumber) { this.serialNumber = serialNumber; } public long getHorsePower() { return horsePower; } public void setHorsePower(long horsePower) { this.horsePower = horsePower; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Address.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000344511131662636033441 0ustar twernertwerner//$Id: Address.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.AssertTrue; import org.hibernate.validator.Length; import org.hibernate.validator.Min; import org.hibernate.validator.NotNull; import org.hibernate.validator.Pattern; import org.hibernate.validator.Range; import org.hibernate.validator.Max; /** * @author Gavin King */ public class Address { @NotNull public static String blacklistedZipCode; private String line1; private String line2; private String zip; private String state; @Length(max = 20) @NotNull private String country; private long id; private boolean internalValid = true; @Range(min = -2, max = 50, message = "{floor.out.of.range} (escaping #{el})") @Max(70) public int floor; public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } @NotNull public String getLine1() { return line1; } public void setLine1(String line1) { this.line1 = line1; } public String getLine2() { return line2; } public void setLine2(String line2) { this.line2 = line2; } @Length(max = 3) @NotNull public String getState() { return state; } public void setState(String state) { this.state = state; } @Length(max = 5, message = "{long}") @Pattern(regex = "[0-9]+") @NotNull public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } @AssertTrue public boolean isValid() { return true; } @AssertTrue private boolean isInternalValid() { return internalValid; } public void setInternalValid(boolean internalValid) { this.internalValid = internalValid; } @Min(1) @Range(max = 2000) public long getId() { return id; } public void setId(long id) { this.id = id; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110374033415 5ustar twernertwerner././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/JPATestCase.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000503411227341572033434 0ustar twernertwerner//$Id: JPATestCase.java 17095 2009-07-15 11:54:34Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import java.util.Map; import java.util.HashMap; import java.util.Properties; import java.util.ArrayList; import java.io.InputStream; import java.io.IOException; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.hibernate.cfg.Environment; import org.hibernate.ejb.HibernatePersistence; /** * @author Emmanuel Bernard */ @SuppressWarnings({ "deprecation" }) public abstract class JPATestCase extends junit.framework.TestCase { protected EntityManagerFactory factory; public JPATestCase() { super(); } public JPATestCase(String name) { super( name ); } public void setUp() { factory = new HibernatePersistence().createEntityManagerFactory( getConfig() ); } public void tearDown() { factory.close(); } public abstract Class[] getAnnotatedClasses(); public String[] getEjb3DD() { return new String[]{}; } public Map getCachedClasses() { return new HashMap(); } public Map getCachedCollections() { return new HashMap(); } public static Properties loadProperties() { Properties props = new Properties(); InputStream stream = Persistence.class.getResourceAsStream( "/hibernate.properties" ); if ( stream != null ) { try { props.load( stream ); } catch (Exception e) { throw new RuntimeException( "could not load hibernate.properties" ); } finally { try { stream.close(); } catch (IOException ioe) { } } } props.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); return props; } public Map getConfig() { Map config = loadProperties(); ArrayList classes = new ArrayList(); for ( Class clazz : getAnnotatedClasses() ) { classes.add( clazz ); } config.put( HibernatePersistence.LOADED_CLASSES, classes ); for ( Map.Entry entry : getCachedClasses().entrySet() ) { config.put( HibernatePersistence.CLASS_CACHE_PREFIX + "." + entry.getKey().getName(), entry.getValue() ); } for ( Map.Entry entry : getCachedCollections().entrySet() ) { config.put( HibernatePersistence.COLLECTION_CACHE_PREFIX + "." + entry.getKey(), entry.getValue() ); } if ( getEjb3DD().length > 0 ) { ArrayList dds = new ArrayList(); for ( String dd : getEjb3DD() ) { dds.add( dd ); } config.put( HibernatePersistence.XML_FILE_NAMES, dds ); } return config; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/Commander.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000072711052766205033440 0ustar twernertwerner//$Id: Commander.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import javax.persistence.Embeddable; import javax.persistence.Column; import org.hibernate.validator.NotEmpty; /** * @author Emmanuel Bernard */ @Embeddable public class Commander { @NotEmpty @Column(name="commander_name") private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/Cat.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000150111052766205033427 0ustar twernertwerner//$Id: Cat.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.validator.Length; import org.hibernate.validator.Min; /** * @author Emmanuel Bernard */ @Entity public class Cat implements Serializable { private Integer id; private String name; private long length; @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Length(min = 4) public String getName() { return name; } public void setName(String name) { this.name = name; } @Min(0) public long getLength() { return length; } public void setLength(long length) { this.length = length; } }././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/HEMAutoWireringTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000260311052766205033433 0ustar twernertwerner//$Id: HEMAutoWireringTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import java.util.Date; import java.util.Map; import javax.persistence.EntityManager; import org.hibernate.ejb.HibernatePersistence; import org.hibernate.engine.SessionImplementor; import org.hibernate.validator.InvalidStateException; /** * @author Emmanuel Bernard */ public class HEMAutoWireringTest extends JPATestCase { public void testPropertyValidation() throws Exception { EntityManager em = factory.createEntityManager(); Cat cat = new Cat(); cat.setName( "iti" ); em.getTransaction().begin(); try { em.persist( cat ); em.flush(); fail( "No validation" ); } catch (InvalidStateException e) { //success } finally { em.getTransaction().rollback(); em.close(); } } public void testEventPerProperties() throws Exception { EntityManager em = factory.createEntityManager(); assertEquals( "Only validator and explicit NoOp should be present", 2, ( (SessionImplementor) em.getDelegate() ).getListeners().getPreInsertEventListeners().length ); em.close(); } public Class[] getAnnotatedClasses() { return new Class[] { Cat.class }; } public Map getConfig() { Map config = super.getConfig(); config.put( HibernatePersistence.EVENT_LISTENER_PREFIX + ".pre-insert", NoOpListener.class.getName() ); return config; } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/JPAValidateListenerTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000405611052766205033437 0ustar twernertwerner//$Id: JPAValidateListenerTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import java.util.Map; import javax.persistence.EntityManager; import org.hibernate.ejb.HibernatePersistence; import org.hibernate.validator.Environment; import org.hibernate.validator.InvalidStateException; /** * @author Emmanuel Bernard */ public class JPAValidateListenerTest extends JPATestCase { public void testEventTrigger() { EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Commander beetles = new Commander(); beetles.setName( "" ); Submarine yellowSubmarine = new Submarine(); yellowSubmarine.setCommander( beetles ); yellowSubmarine.setName( "" ); yellowSubmarine.setSize( 3 ); try { em.persist( yellowSubmarine ); em.flush(); fail("Event not wired"); } catch(InvalidStateException e) { assertEquals( 3, e.getInvalidValues().length ); } finally { em.getTransaction().rollback(); em.close(); } //update trigger em = factory.createEntityManager(); em.getTransaction().begin(); beetles = new Commander(); beetles.setName( "Beetles" ); yellowSubmarine = new Submarine(); yellowSubmarine.setCommander( beetles ); yellowSubmarine.setName( "Yellow" ); yellowSubmarine.setSize( 13 ); em.persist( yellowSubmarine ); em.flush(); em.clear(); yellowSubmarine = em.find( Submarine.class, yellowSubmarine.getId() ); yellowSubmarine.setSize( 3 ); try { em.flush(); fail("Event not wired"); } catch(InvalidStateException e) { assertEquals( 1, e.getInvalidValues().length ); } finally { em.getTransaction().rollback(); em.close(); } } public Class[] getAnnotatedClasses() { return new Class[]{ Commander.class, Submarine.class }; } public Map getConfig() { Map map = super.getConfig(); //Remove regular Validator wiring map.put( HibernatePersistence.EVENT_LISTENER_PREFIX + "." + "pre-insert", "" ); map.put( HibernatePersistence.EVENT_LISTENER_PREFIX + "." + "pre-update", "" ); return map; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/NoOpListener.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000057511052766205033441 0ustar twernertwerner//$Id: NoOpListener.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreInsertEvent; /** * @author Emmanuel Bernard */ public class NoOpListener implements PreInsertEventListener { public boolean onPreInsert(PreInsertEvent event) { return false; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/jpa/Submarine.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000216011052766205033431 0ustar twernertwerner//$Id: Submarine.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.jpa; import javax.persistence.Entity; import javax.persistence.EntityListeners; import javax.persistence.GeneratedValue; import javax.persistence.Id; import org.hibernate.validator.Min; import org.hibernate.validator.NotEmpty; import org.hibernate.validator.Valid; import org.hibernate.validator.event.JPAValidateListener; /** * @author Emmanuel Bernard */ @Entity @EntityListeners( JPAValidateListener.class ) public class Submarine { @Id @GeneratedValue private Long id; @NotEmpty private String name; @Valid private Commander commander; @Min( 10 ) private long size; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public Commander getCommander() { return commander; } public void setCommander(Commander commander) { this.commander = commander; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/AssertTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000427511052516561033440 0ustar twernertwerner// $Id: AssertTest.java 15111 2008-08-19 10:16:17Z hardy.ferentschik $ package org.hibernate.validator.test; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; import org.hibernate.validator.AssertTrueValidator; import org.hibernate.validator.AssertFalseValidator; import java.util.Locale; import java.util.ResourceBundle; /** * Test cases for AssertFalse and AssertTrue. * * @author Hardy Ferentschik * @see HV-53 */ public class AssertTest extends TestCase { ClassValidator classValidator; public void setUp() throws Exception { classValidator = new ClassValidator( BooleanHolder.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) ); } public void testSuccessfulValidation() throws Exception { BooleanHolder bholder = new BooleanHolder(); bholder.setMustBeTrue(true); bholder.setMustBeFalse(false); InvalidValue[] invalidValues = classValidator.getInvalidValues(bholder); assertTrue("should be empty", invalidValues.length == 0); } public void testUnSuccessfulValidation() throws Exception { BooleanHolder bholder = new BooleanHolder(); bholder.setMustBeTrue(false); bholder.setMustBeFalse(true); InvalidValue[] invalidValues = classValidator.getInvalidValues(bholder); assertTrue("should be empty", invalidValues.length == 2); } public void testNullValidation() throws Exception { BooleanHolder bholder = new BooleanHolder(); bholder.setMustBeTrue(null); bholder.setMustBeFalse(null); InvalidValue[] invalidValues = classValidator.getInvalidValues(bholder); assertTrue("should be empty", invalidValues.length == 0); } public void testNonBooleanValidation() throws Exception { AssertTrueValidator trueValidator = new AssertTrueValidator(); assertFalse(trueValidator.isValid("foo")); AssertFalseValidator falseValidator = new AssertFalseValidator(); assertFalse(falseValidator.isValid("foo")); } }././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Serializability.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000112011131662636033425 0ustar twernertwernerpackage org.hibernate.validator.test; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import org.hibernate.validator.ValidatorClass; /** * Dummy sample of a bean-level validation annotation * * @author Emmanuel Bernard */ @ValidatorClass(SerializabilityValidator.class) @Target(TYPE) @Retention(RUNTIME) @Documented public @interface Serializability { String message() default "Bean not Serializable"; } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/HANTestCase.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000761511227341464033443 0ustar twernertwerner//$Id: HANTestCase.java 17094 2009-07-15 11:53:24Z hardy.ferentschik $ package org.hibernate.validator.test; import java.io.InputStream; import org.hibernate.SessionFactory; import org.hibernate.Session; import org.hibernate.HibernateException; import org.hibernate.Interceptor; import org.hibernate.dialect.Dialect; import org.hibernate.cfg.AnnotationConfiguration; import org.hibernate.cfg.Environment; import org.hibernate.cfg.Configuration; /** * Copy from HAN * * @author Emmanuel Bernard */ public abstract class HANTestCase extends junit.framework.TestCase { private static SessionFactory sessions; private static AnnotationConfiguration cfg; private static Dialect dialect; private static Class lastTestClass; private Session session; public HANTestCase() { super(); } public HANTestCase(String x) { super( x ); } protected void buildSessionFactory(Class[] classes, String[] packages, String[] xmlFiles) throws Exception { if ( getSessions() != null ) getSessions().close(); try { setCfg( new AnnotationConfiguration() ); configure( cfg ); if ( recreateSchema() ) { cfg.setProperty( Environment.HBM2DDL_AUTO, "create-drop" ); } for ( int i = 0; i < packages.length; i++ ) { getCfg().addPackage( packages[i] ); } for ( int i = 0; i < classes.length; i++ ) { getCfg().addAnnotatedClass( classes[i] ); } for ( int i = 0; i < xmlFiles.length; i++ ) { InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream( xmlFiles[i] ); getCfg().addInputStream( is ); } setDialect( Dialect.getDialect() ); setSessions( getCfg().buildSessionFactory( /*new TestInterceptor()*/ ) ); } catch (Exception e) { e.printStackTrace(); throw e; } } protected void setUp() throws Exception { if ( getSessions() == null || lastTestClass != getClass() ) { buildSessionFactory( getMappings(), getAnnotatedPackages(), getXmlFiles() ); lastTestClass = getClass(); } } @SuppressWarnings({ "deprecation" }) protected void runTest() throws Throwable { try { super.runTest(); if ( session != null && session.isOpen() ) { if ( session.isConnected() ) session.connection().rollback(); session.close(); session = null; fail( "unclosed session" ); } else { session = null; } } catch (Throwable e) { try { if ( session != null && session.isOpen() ) { if ( session.isConnected() ) session.connection().rollback(); session.close(); } } catch (Exception ignore) { } try { if ( sessions != null ) { sessions.close(); sessions = null; } } catch (Exception ignore) { } throw e; } } public Session openSession() throws HibernateException { session = getSessions().openSession(); return session; } public Session openSession(Interceptor interceptor) throws HibernateException { session = getSessions().openSession( interceptor ); return session; } protected abstract Class[] getMappings(); protected String[] getAnnotatedPackages() { return new String[]{}; } protected String[] getXmlFiles() { return new String[]{}; } private void setSessions(SessionFactory sessions) { HANTestCase.sessions = sessions; } protected SessionFactory getSessions() { return sessions; } private void setDialect(Dialect dialect) { HANTestCase.dialect = dialect; } protected Dialect getDialect() { return dialect; } protected static void setCfg(AnnotationConfiguration cfg) { HANTestCase.cfg = cfg; } protected static AnnotationConfiguration getCfg() { return cfg; } protected void configure(Configuration cfg) { //cfg.setNamingStrategy( AlternativeNamingStrategy.INSTANCE ); //cfg.getSessionEventListenerConfig().setFlushEventListener( new EJB3FlushEventListener() ); //cfg.getSessionEventListenerConfig().setAutoFlushEventListener( new EJB3AutoFlushEventListener() ); } protected boolean recreateSchema() { return true; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/TvOwner.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000045411131662636033436 0ustar twernertwerner//$Id: TvOwner.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class TvOwner { public Integer id; @NotNull @Valid public Tv tv; } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110374033415 5ustar twernertwerner././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/Show.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000040111052766205033425 0ustar twernertwerner//$Id: Show.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.collections; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class Show { @NotNull public String name; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/Presenter.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000041311052766205033430 0ustar twernertwerner//$Id: Presenter.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.collections; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class Presenter { @NotNull public String name; } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/Tv.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000111311052766205033426 0ustar twernertwerner//$Id: Tv.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.collections; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class Tv { @NotNull public String name; @Valid public List presenters = new ArrayList(); @Valid public Map shows = new HashMap(); public @Valid Movie[] movies; } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/ValidationCollectionTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000364411052766205033441 0ustar twernertwerner//$Id: ValidationCollectionTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.collections; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Emmanuel Bernard */ public class ValidationCollectionTest extends TestCase { public void testCollection() throws Exception { Tv tv = new Tv(); tv.name = "France 2"; Presenter presNok = new Presenter(); presNok.name = null; Presenter presOk = new Presenter(); presOk.name = "Thierry Ardisson"; tv.presenters.add( presOk ); tv.presenters.add( presNok ); ClassValidator validator = new ClassValidator( Tv.class ); InvalidValue[] values = validator.getInvalidValues( tv ); assertEquals( 1, values.length ); assertEquals( "presenters[1].name", values[0].getPropertyPath() ); } public void testMap() throws Exception { Tv tv = new Tv(); tv.name = "France 2"; Show showOk = new Show(); showOk.name = "Tout le monde en parle"; Show showNok = new Show(); showNok.name = null; tv.shows.put( "Midnight", showOk ); tv.shows.put( "Primetime", showNok ); ClassValidator validator = new ClassValidator( Tv.class ); InvalidValue[] values = validator.getInvalidValues( tv ); assertEquals( 1, values.length ); assertEquals( "shows['Primetime'].name", values[0].getPropertyPath() ); } public void testArray() throws Exception { Tv tv = new Tv(); tv.name = "France 2"; Movie movieOk = new Movie(); movieOk.name = "Kill Bill"; Movie movieNok = new Movie(); movieNok.name = null; tv.movies = new Movie[]{ movieOk, null, movieNok }; ClassValidator validator = new ClassValidator( Tv.class ); InvalidValue[] values = validator.getInvalidValues( tv ); assertEquals( 1, values.length ); assertEquals( "movies[2].name", values[0].getPropertyPath() ); } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/collections/Movie.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000040311052766205033427 0ustar twernertwerner//$Id: Movie.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.collections; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class Movie { @NotNull public String name; } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Tv.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000103511131662636033432 0ustar twernertwerner//$Id: Tv.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import java.math.BigInteger; import java.util.Date; import org.hibernate.validator.Future; import org.hibernate.validator.Length; import org.hibernate.validator.Min; /** * @author Emmanuel Bernard */ public class Tv { @Length(max = 2) public String serial; public int size; @Length(max = 2) public String name; @Future public Date expDate; @Length(min = 0) public String description; @Min(1000) public BigInteger lifetime; } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Vase.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000035111131662636033432 0ustar twernertwerner//$Id: Vase.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; /** * A vase has to be Serializable to fit in luggages * * @author Emmanuel Bernard */ @Serializability public class Vase { } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/InterpolationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000226411052766205033436 0ustar twernertwerner//$Id: InterpolationTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test; import java.util.MissingResourceException; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Emmanuel Bernard */ public class InterpolationTest extends TestCase { public void testMissingKey() { Building b = new Building(); b.setAddress( "2323 Younge St"); ClassValidator validator = new ClassValidator(Building.class); try { validator.getInvalidValues( b ); } catch (MissingResourceException e) { fail("message should be interpolated lazily in DefaultMessageInterpolator"); } b = new Building(); b.setAddress(""); boolean failure = false; InvalidValue[] invalidValues = validator.getInvalidValues( b ); assertNotSame( "Should have a failure here", 0, invalidValues.length ); assertEquals( "Missing key should be left unchanged", "{notpresent.Key} and #{key.notPresent} and {key.notPresent2} 1", invalidValues[0].getMessage() ); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/SerializabilityValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000077311131662636033442 0ustar twernertwerner//$Id: SerializabilityValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import java.io.Serializable; import org.hibernate.validator.Validator; /** * Sample of a bean-level validator * * @author Emmanuel Bernard */ public class SerializabilityValidator implements Validator, Serializable { public boolean isValid(Object value) { return value instanceof Serializable; } public void initialize(Serializability parameters) { } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Building.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000107111052766205033431 0ustar twernertwerner//$Id: Building.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.Length; /** * @author Emmanuel Bernard */ public class Building { private Long id; @Length( min = 1, message = "{notpresent.Key} and #{key.notPresent} and {key.notPresent2} {min}" ) private String address; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/Site.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000132711131662636033436 0ustar twernertwerner//$Id: Site.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.NotNull; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class Site { @NotNull private String siteName; @Valid private Address address; @Valid private Contact contact; public String getSiteName() { return siteName; } public void setSiteName(String siteName) { this.siteName = siteName; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } public Contact getContact() { return contact; } public void setContact(Contact contact) { this.contact = contact; } }././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/User.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000045511131662636033437 0ustar twernertwerner//$Id: User.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test; import org.hibernate.validator.Email; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class User { @NotNull public String name; @Email public String email; } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110371033412 5ustar twernertwerner././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/BoneEater.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000050411131662636033432 0ustar twernertwerner//$Id: BoneEater.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public interface BoneEater extends Eater { @NotNull String getFavoriteBone(); void setFavoriteBone(String favoriteBone); } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/InheritanceTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000135511131662636033437 0ustar twernertwerner//$Id: InheritanceTest.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Emmanuel Bernard */ public class InheritanceTest extends TestCase { public void testInheritance() throws Exception { ClassValidator classValidator = new ClassValidator( Dog.class ); Dog dog = new Dog(); InvalidValue[] invalidValues = classValidator.getInvalidValues( dog ); assertEquals( 3, invalidValues.length ); dog.setFavoriteBone( "DE" ); //failure invalidValues = classValidator.getInvalidValues( dog ); assertEquals( 3, invalidValues.length ); } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/Eater.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000043211131662636033432 0ustar twernertwerner//$Id: Eater.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import org.hibernate.validator.Min; /** * @author Emmanuel Bernard */ public interface Eater { @Min(2) int getFrequency(); void setFrequency(int frequency); } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/Animal.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000055511131662636033440 0ustar twernertwerner//$Id: Animal.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import java.io.Serializable; /** * @author Emmanuel Bernard */ public class Animal implements Serializable, Name { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/Dog.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000120711131662636033433 0ustar twernertwerner//$Id: Dog.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import java.io.Serializable; import org.hibernate.validator.Length; /** * @author Emmanuel Bernard */ public class Dog extends Animal implements Serializable, BoneEater { private String favoriteBone; private int frequency; @Length(min = 3) public String getFavoriteBone() { return favoriteBone; } public void setFavoriteBone(String favoriteBone) { this.favoriteBone = favoriteBone; } public int getFrequency() { return frequency; } public void setFrequency(int frequency) { this.frequency = frequency; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/inheritance/Name.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000042411131662636033433 0ustar twernertwerner//$Id: Name.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.test.inheritance; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public interface Name { @NotNull String getName(); void setName(String name); } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/valid/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000755000175000017500000000000011402110373033414 5ustar twernertwerner././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/valid/Form.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000056011052766205033433 0ustar twernertwerner//$Id: Form.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.valid; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class Form { private Member member; @Valid public Member getMember() { return member; } public void setMember(Member m) { this.member = m; } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/valid/Member.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000061211052766205033431 0ustar twernertwerner//$Id: Member.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.valid; import org.hibernate.validator.Valid; /** * @author Emmanuel Bernard */ public class Member { private Address address; @Valid public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/valid/Address.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000046711052766205033441 0ustar twernertwerner//$Id: Address.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.valid; import org.hibernate.validator.NotNull; /** * @author Emmanuel Bernard */ public class Address { private String city; @NotNull public String getCity() { return city; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validator/test/valid/ValidTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/test/java/org/hibernate/validato0000644000175000017500000000125711052766205033437 0ustar twernertwerner//$Id: ValidTest.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.test.valid; import junit.framework.TestCase; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.InvalidValue; /** * @author Emmanuel Bernard */ public class ValidTest extends TestCase { public void testDeepValid() throws Exception { ClassValidator
formValidator = new ClassValidator(Form.class); Address a = new Address(); Member m = new Member(); m.setAddress( a ); Form f = new Form(); f.setMember(m); InvalidValue[] values = formValidator.getInvalidValues( f ); assertEquals( 1, values.length ); } } libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/0000755000175000017500000000000011402110402026155 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/0000755000175000017500000000000011402110402030167 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/0000755000175000017500000000000011402110402030756 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/0000755000175000017500000000000011402110402032717 5ustar twernertwerner././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000755000175000017500000000000011402110402033422 5ustar twernertwerner././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000755000175000017500000000000011402110403033423 5ustar twernertwerner././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_sv.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000140611173623006033443 0ustar twernertwernervalidator.assertFalse=Felaktigt påstående validator.assertTrue=Felaktigt påstående validator.future=måste vara ett datum fram i tiden validator.length=måste vara mellan {min} och {max} tecken validator.max=får vara max {value} validator.min=måste vara minst {value} validator.notNull=får inte vara tomt validator.past=måste vara ett datum bakåt i tiden validator.pattern=måste matcha "{regex}" validator.range=måste vara mellan {min} och {max} validator.size=storlek måste vara mellan {min} och {max} validator.email=ogiltig e-mail adress validator.notEmpty=får inte vara tomt validator.digits=numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.ean=invalid EAN validator.creditCard=invalid credit card number././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_es.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000150111173623006033437 0ustar twernertwernervalidator.assertFalse=aserción fallida validator.assertTrue=aserción fallida validator.future=debe ser una fecha futura validator.length=la longitud debe ser entre {min} y {max} validator.max=debe ser menor o igual a {value} validator.min=debe ser mayor o igual a {value} validator.notNull=no puede ser nula validator.past=debe ser una fecha pasada validator.pattern=debe corresponder a "{regex}" validator.range=debe ser entre {min} y {max} validator.size=el tamaño debe ser entre {min} y {max} validator.email=no es una dirección de correo electrónico bien formada validator.notEmpty=no debe ser nulo o vacío validator.digits=valor numŽrico fuera de los l’mites (se esperaba <{integerDigits} d’gitos>.<{fractionalDigits} d’gitos>) validator.ean=EAN inv‡lido validator.creditCard=nœmero de tarjeta de crŽdito inv‡lido././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_it.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000145711173623006033451 0ustar twernertwernervalidator.assertFalse=asserzione fallita validator.assertTrue=asserzione fallita validator.future=deve essere una data futura validator.length=la lunghezza deve essere tra {min} e {max} validator.max=deve essere minore o uguale a {value} validator.min=deve essere maggiore o uguale a {value} validator.notNull=non può essere nullo validator.past=deve essere una data nel passato validator.pattern=deve corrispondere a "{regex}" validator.range=deve essere tra {min} e {max} validator.size=le dimensioni devono essere tra {min} e {max} validator.email=not a well-formed email address validator.notEmpty=non può essere nullo o vuoto validator.digits=Valore numerico fuori dai limiti (atteso <{integerDigits} cifre>.<{fractionalDigits} cifre>) validator.ean=EAN invalido validator.creditCard=invalid credit card number././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_fr.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000144711173623006033450 0ustar twernertwernervalidator.assertFalse=l'assertion a échoué validator.assertTrue=l'assertion a échoué validator.future=doit être dans le futur validator.length=la longueur doit être entre {min} et {max} validator.max=doit être inférieur ou égal à {value} validator.min=doit être supérieur ou égal à {value} validator.notNull=ne peut pas être nul validator.past=doit être dans le passé validator.pattern=doit suivre "{regex}" validator.range=doit être entre {min} et {max} validator.size=le nombre d'éléments doit être entre {min} et {max} validator.email=Address email mal formée validator.notEmpty=ne peut pas être nul ou vide validator.digits=Valeur numérique hors limite (<{integerDigits} chiffres>.<{fractionalDigits} chiffres> attendus) validator.ean=EAN invalide validator.creditCard=Numéro de carte de crédit invalide././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_de.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000144311173623006033444 0ustar twernertwernervalidator.assertFalse=nicht garantiert validator.assertTrue=garantiert validator.future=muss in der Zukunft liegen validator.length=muss zwischen {min} und {max} lang sein validator.max=muss weniger oder gleich {value} sein validator.min=muss mehr oder gleich {value} sein validator.notNull=kann nicht leer sein validator.past=muss in der Vergangenheit liegen validator.pattern=muss Ausdruck "{regex}" entsprechen validator.range=muss zwischen {min} und {max} sein validator.size=muss zwischen {min} und {max} gross sein validator.email=not a well-formed email address validator.notEmpty=kann nicht null oder leer sein validator.digits=numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.ean=invalid EAN validator.creditCard=Ungültige Kreditkartennummer././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_ja.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000336411173623006033450 0ustar twernertwernervalidator.assertFalse=\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u306b\u5931\u6557\u3057\u307e\u3057\u305f validator.assertTrue=\u30a2\u30b5\u30fc\u30b7\u30e7\u30f3\u306b\u5931\u6557\u3057\u307e\u3057\u305f validator.future=\u672a\u6765\u306e\u65e5\u4ed8\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.length={min}\u6587\u5b57\u304b\u3089{max}\u6587\u5b57\u307e\u3067\u306e\u9577\u3055\u3067\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.max={value}\u4ee5\u4e0b\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.min={value}\u4ee5\u4e0a\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.notNull=null\u306e\u72b6\u614b\u306f\u8a31\u3055\u308c\u307e\u305b\u3093 validator.past=\u904e\u53bb\u306e\u65e5\u4ed8\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.pattern="{regex}"\u306b\u30de\u30c3\u30c1\u3055\u305b\u3066\u304f\u3060\u3055\u3044 validator.range={min}\u4ee5\u4e0a\u3001{max}\u4ee5\u4e0b\u3092\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.size={min}\u304b\u3089{max}\u307e\u3067\u306e\u30b5\u30a4\u30ba\u3067\u6307\u5b9a\u3057\u3066\u304f\u3060\u3055\u3044 validator.email=\u96fb\u5b50\u30e1\u30fc\u30eb\u306e\u30a2\u30c9\u30ec\u30b9\u306e\u5f62\u5f0f\u3068\u3057\u3066\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093 validator.notEmpty=null\u3084\u7a7a\u306e\u72b6\u614b\u306f\u8a31\u3055\u308c\u307e\u305b\u3093 validator.digits=\u7bc4\u56f2\u5916\u306e\u6570\u5024\u3067\u3059(<{integerDigits}\u6841>.<{fractionalDigits}\u6841>\u307e\u3067\u306e\u6841\u6570\u304c\u8a31\u5bb9\u3055\u308c\u3066\u3044\u307e\u3059) validator.creditCard=\u7121\u52b9\u306a\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u3059 validator.ean=\u7121\u52b9\u306aJAN\u30b3\u30fc\u30c9\u3067\u3059 ././@LongLink0000000000000000000000000000023700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_zh_CN.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000164211173623006033445 0ustar twernertwernervalidator.assertFalse=\u9a8c\u8bc1\u5931\u8d25 validator.assertTrue=\u9a8c\u8bc1\u5931\u8d25 validator.future=\u5fc5\u987b\u8fdf\u4e8e\u4eca\u65e5 validator.length=\u957f\u5ea6\u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 validator.max=\u5fc5\u987b\u5c0f\u4e8e\u7b49\u4e8e {value} validator.min=\u5fc5\u987b\u5927\u4e8e\u7b49\u4e8e {value} validator.notNull=\u4e0d\u80fd\u4e3a\u7a7a validator.past=\u5fc5\u987b\u65e9\u4e8e\u4eca\u65e5 validator.pattern=\u5fc5\u987b\u7b26\u5408 "{regex}" validator.range=\u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 validator.size=\u5927\u5c0f\u5fc5\u987b\u4ecb\u4e8e {min} \u4e0e {max} \u4e4b\u95f4 validator.email=not a well-formed email address validator.notEmpty=may not be null or empty validator.digits=numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.ean=invalid EAN validator.creditCard=invalid credit card number././@LongLink0000000000000000000000000000023700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_pt_BR.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000146311173623006033446 0ustar twernertwernervalidator.assertFalse=asserção falhou validator.assertTrue=asserção falhou validator.future=deve ser uma data no futuro validator.length=tamanho deve estar entre {min} e {max} validator.max=deve ser menor ou igual a {value} validator.min=deve ser maior ou igual a {value} validator.notNull=não pode ser nulo validator.past=deve ser uma data no passado validator.pattern=deve ser válida de acordo com a expressão "{regex}" validator.range=deve estar entre {min} e {max} validator.size=tamanho deve estar entre {min} e {max} validator.email=não é um email válido validator.notEmpty=não pode ser nulo ou vazio validator.digits=Valor numérico fora do padrão (esperado <{integerDigits}> dígitos,<{fractionalDigits} dígitos) validator.ean=EAN inválido validator.creditCard=Número inválido de cartão de crédito././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_en.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000137111173623006033444 0ustar twernertwernervalidator.assertFalse=assertion failed validator.assertTrue=assertion failed validator.future=must be a future date validator.length=length must be between {min} and {max} validator.max=must be less than or equal to {value} validator.min=must be greater than or equal to {value} validator.notNull=may not be null validator.past=must be a past date validator.pattern=must match "{regex}" validator.range=must be between {min} and {max} validator.size=size must be between {min} and {max} validator.email=not a well-formed email address validator.notEmpty=may not be null or empty validator.digits=Numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.creditCard=Invalid credit card number validator.ean=Invalid EAN././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_da.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000144011173623006033441 0ustar twernertwernervalidator.assertFalse=assertion fejlet validator.assertTrue=assertion fejlet validator.future=skal være en fremtidig dato validator.length=længden skal være mellem {min} og {max} validator.max=skal være mindre end eller lig med {value} validator.min=skal være større end eller lig med {value} validator.notNull=må ikke være null validator.past=skal være en passeret dato validator.pattern=skal matche "{regex}" validator.range=skal være mellem {min} og {max} validator.size=antallet skal være mellem {min} og {max} validator.email=not a well-formed email address validator.notEmpty=må ikke være null eller tom validator.digits=Værdien er ikke inden for det forventede (<{integerDigits} heltal>.<{fractionalDigits} decimaler>) validator.ean=Ukorrekt EAN validator.creditCard=Ukorrekt kreditkort nummer././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_nl.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000146211173623006033445 0ustar twernertwernervalidator.assertFalse=is niet geldig validator.assertTrue=is niet geldig validator.future=moet een datum in de toekomst zijn validator.length=moet tussen {min} en {max} lang zijn validator.max=moet kleiner of gelijk aan {value} zijn validator.min=moet groter of gelijk aan {value} zijn validator.notNull=mag niet leeg zijn validator.past=moet een datum in het verleden zijn validator.pattern=moet overeenkomen met "{regex}" validator.range=moet tussen {min} en {max} zijn validator.size=moet tussen {min} en {max} groot zijn validator.email=moet een geldig e-mail adres zijn validator.notEmpty=mag niet null of leeg zijn validator.digits=numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.ean=invalid EAN validator.creditCard=invalid credit card number././@LongLink0000000000000000000000000000023400000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_cs.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000205211173623006033441 0ustar twernertwernervalidator.assertFalse=p\u0159edpoklad neplat\u00ed validator.assertTrue=p\u0159edpoklad neplat\u00ed validator.future=mus\u00ed b\u00fdt datum v budoucnosti validator.length=d\u00e9lka mus\u00ed b\u00fdt mezi {min} a {max} validator.max=mus\u00ed b\u00fdt men\u0161\u00ed nebo rovno {value} validator.min=mus\u00e1 b\u00fdt men\u0161\u00ed nebo rovno {value} validator.notNull=nesm\u00ed b\u00fdt pr\u00e1zdn\u00e9 validator.past=mus\u00ed b\u00fdt datum v minulosti validator.pattern=mus\u00ed odpov\u00eddat "{regex}" validator.range=mus\u00ed b\u00fdt v rozmez\u00ed od {min} do {max} validator.size=d\u00e9lka mus\u00ed b\u00fdt mezi {min} a {max} validator.email=nen\u00ed spr\u00e1vn\u011b zapsan\u00e1 emailov\u00e1 adresa validator.notEmpty=nesm\u00ed b\u00fdt pr\u00e1zdn\u00e9 validator.digits=\u010c\u00edseln\u00e1 hodnota je mimo rozsah (o\u010dek\u00e1v\u00e1no <{integerDigits} \u010d\u00edsel>,<{fractionalDigits} \u010d\u00edsel>) validator.creditCard=Nen\u00ed platn\u00e9 \u010d\u00edslo kreditn\u00ed karty validator.ean=Nen\u00ed platn\u00e9 EAN././@LongLink0000000000000000000000000000023100000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000137111173623006033444 0ustar twernertwernervalidator.assertFalse=assertion failed validator.assertTrue=assertion failed validator.future=must be a future date validator.length=length must be between {min} and {max} validator.max=must be less than or equal to {value} validator.min=must be greater than or equal to {value} validator.notNull=may not be null validator.past=must be a past date validator.pattern=must match "{regex}" validator.range=must be between {min} and {max} validator.size=size must be between {min} and {max} validator.email=not a well-formed email address validator.notEmpty=may not be null or empty validator.digits=Numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.creditCard=Invalid credit card number validator.ean=Invalid EAN././@LongLink0000000000000000000000000000023700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/validator/resources/DefaultValidatorMessages_zh_TW.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/resources/org/hibernate/val0000644000175000017500000000165111173623006033445 0ustar twernertwernervalidator.assertFalse=\u9a57\u8b49\u5931\u6557 validator.assertTrue=\u9a57\u8b49\u5931\u6557 validator.future=\u5fc5\u9808\u9072\u4e8e\u4eca\u65e5 validator.length=\u9577\u5ea6\u5fc5\u9808\u4ecb\u65bc {min} \u8207 {max} \u4e4b\u9593 validator.max=\u5fc5\u9808\u5c0f\u4e8e\u6216\u7b49\u65bc{value} validator.min=\u5fc5\u9808\u5927\u4e8e\u6216\u7b49\u65bc{value} validator.notNull=\u5fc5\u9808\u586b\u5beb validator.past=\u5fc5\u9808\u65e9\u4e8e\u4eca\u65e5 validator.pattern=\u5fc5\u9808\u7b26\u5408"{regex}" validator.range=\u5fc5\u9808\u4ecb\u65bc{min} \u8207 {max} \u4e4b\u9593 validator.size=\u5927\u5c0f\u5fc5\u9808\u4ecb\u65bc{min} \u8207 {max} \u4e4b\u9593 validator.email=not a well-formed email address validator.digits=numeric value out of bounds (<{integerDigits} digits>.<{fractionalDigits} digits> expected) validator.notEmpty=may not be null or empty validator.ean=invalid EAN validator.creditCard=invalid credit card numberlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/javadoc/0000755000175000017500000000000011402110402027564 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/javadoc/stylesheet.css0000644000175000017500000000460411073343621032512 0ustar twernertwerner/* Javadoc style sheet */ /* Define colors, fonts and other style attributes here to override the defaults */ /* Page background color */ body { font-family: Arial; background-color: white; font-size: 10pt; } td { font-family: Arial; font-size: 10pt; } /* Table colors */ .TableHeadingColor { background: #F4F4F4 } .TableSubHeadingColor { background: #F4F4F4 } .TableRowColor { background: #FFFFFF } /* Font used in left-hand frame lists */ .FrameTitleFont { font-size: normal; font-family: Arial } .FrameHeadingFont { font-size: normal; font-family: Arial } .FrameItemFont { font-size: normal; font-family: Arial } /* Example of smaller, sans-serif font in frames */ /* .FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */ /* Navigation bar fonts and colors */ .NavBarCell1 { background-color:#F4F4F4;} .NavBarCell1Rev { background-color:silver;} .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;} .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;} .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;} .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;} A { color: #003399; } A:active { color: #003399; } A:visited { color: #888888; } P, OL, UL, LI, DL, DT, DD, BLOCKQUOTE { color: #000000; } TD, TH, SPAN { color: #000000; } BLOCKQUOTE { margin-right: 0px; } /*H1, H2, H3, H4, H5, H6 { color: #000000; font-weight:500; margin-top:10px; padding-top:15px; } H1 { font-size: 150%; } H2 { font-size: 140%; } H3 { font-size: 110%; font-weight: bold; } H4 { font-size: 110%; font-weight: bold;} H5 { font-size: 100%; font-style: italic; } H6 { font-size: 100%; font-style: italic; }*/ TT { font-size: 90%; font-family: "Courier New", Courier, monospace; color: #000000; } PRE { font-size: 90%; padding: 5px; border-style: solid; border-width: 1px; border-color: #CCCCCC; background-color: #F4F4F4; } UL, OL, LI { list-style: disc; } HR { width: 100%; height: 1px; background-color: #CCCCCC; border-width: 0px; padding: 0px; color: #CCCCCC; } .variablelist { padding-top: 10; padding-bottom:10; margin:0; } .itemizedlist, UL { padding-top: 0; padding-bottom:0; margin:0; } .term { font-weight:bold; } libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/0000755000175000017500000000000011402110376027110 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/0000755000175000017500000000000011402110376027677 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/0000755000175000017500000000000011402110376031640 5ustar twernertwerner././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000755000175000017500000000000011402110401033351 5ustar twernertwerner././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Future.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000124011131662636033375 0ustar twernertwerner//$Id: Future.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Check that a Date, a Calendar, or a string representation apply in the future * * @author Gavin King */ @Documented @ValidatorClass(FutureValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Future { String message() default "{validator.future}"; } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/NotNullValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000211411131662636033376 0ustar twernertwerner//$Id: NotNullValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.util.Iterator; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; import org.hibernate.mapping.SingleTableSubclass; /** * Check a not null restriction on an object * and apply the equivalent constraint on hibernate metadata. * * @author Gavin King */ public class NotNullValidator implements Validator, PropertyConstraint, Serializable { public boolean isValid(Object value) { return value != null; } public void initialize(NotNull parameters) { } @SuppressWarnings("unchecked") public void apply(Property property) { if ( ! ( property.getPersistentClass() instanceof SingleTableSubclass ) ) { //single table should not be forced to null if ( !property.isComposite() ) { //composite should not add not-null on all columns Iterator iter = (Iterator) property.getColumnIterator(); while ( iter.hasNext() ) { iter.next().setNullable( false ); } } } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Past.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000122611131662636033401 0ustar twernertwerner//$Id: Past.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Check that a Date, a Calendar, or a string representation apply in the past * * @author Gavin King */ @Documented @ValidatorClass(PastValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Past { String message() default "{validator.past}"; } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/DigitsValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000410511213511275033371 0ustar twernertwerner//$Id: DigitsValidator.java 16729 2009-06-09 16:50:05Z hardy.ferentschik $ package org.hibernate.validator; import java.math.BigDecimal; import java.math.BigInteger; import org.hibernate.mapping.Property; import org.hibernate.mapping.Column; /** * Validate a Digit to check if it matches the according pattern * * @author Norman Richards * @author Emmanuel Bernard */ public class DigitsValidator implements Validator, PropertyConstraint { int integerDigits; int fractionalDigits; public void initialize(Digits configuration) { integerDigits = configuration.integerDigits(); fractionalDigits = configuration.fractionalDigits(); } public boolean isValid(Object value) { if ( value == null ) { return true; } String stringValue; if ( value instanceof String ) { try { stringValue = stringValue( new BigDecimal( (String) value ) ); } catch (NumberFormatException nfe) { return false; } } else if ( value instanceof BigDecimal ) { stringValue = stringValue( (BigDecimal) value ); } else if ( value instanceof BigInteger ) { stringValue = stringValue( (BigInteger) value ); } else if ( value instanceof Number ) { //yukky stringValue = stringValue( new BigDecimal( ( (Number) value ).toString() ) ); } else { return false; } int pos = stringValue.indexOf( "." ); int left = ( pos == -1 ) ? stringValue.length() : pos; int right = ( pos == -1 ) ? 0 : stringValue.length() - pos - 1; if ( left == 1 && stringValue.charAt( 0 ) == '0' ) { left--; } return !( left > integerDigits || right > fractionalDigits ); } private String stringValue(BigDecimal number) { return number.abs().stripTrailingZeros().toPlainString(); } private String stringValue(BigInteger number) { return number.abs().toString(); } public void apply(Property property) { Column col = (Column) property.getColumnIterator().next(); col.setPrecision( integerDigits + fractionalDigits ); col.setScale( fractionalDigits ); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Pattern.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000137511131662636033406 0ustar twernertwerner//$Id: Pattern.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * The annotated element must follow the regexp pattern * * @author Gavin King */ @Documented @ValidatorClass(PatternValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Pattern { /** regular expression */ String regex(); /** regular expression processing flags */ int flags() default 0; String message() default "{validator.pattern}"; } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/ClassValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000006171311131662636033410 0ustar twernertwerner//$Id: ClassValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.beans.Introspector; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import java.util.StringTokenizer; import org.hibernate.AssertionFailure; import org.hibernate.Hibernate; import org.hibernate.MappingException; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.mapping.Component; import org.hibernate.annotations.common.reflection.Filter; import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.XClass; import org.hibernate.annotations.common.reflection.XMember; import org.hibernate.annotations.common.reflection.XMethod; import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.annotations.common.reflection.java.JavaReflectionManager; import org.hibernate.util.IdentitySet; import org.hibernate.validator.interpolator.DefaultMessageInterpolatorAggregator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Engine that take a bean and check every expressed annotation restrictions * * @author Gavin King * @author Emmanuel Bernard */ public class ClassValidator implements Serializable { //TODO Define magic number private static final Logger log = LoggerFactory.getLogger( ClassValidator.class ); private static final InvalidValue[] EMPTY_INVALID_VALUE_ARRAY = new InvalidValue[]{}; private static final String DEFAULT_VALIDATOR_MESSAGE = "org.hibernate.validator.resources.DefaultValidatorMessages"; private static final String VALIDATOR_MESSAGE = "ValidatorMessages"; private static final Set INDEXABLE_CLASS = new HashSet(); static { INDEXABLE_CLASS.add( Integer.class ); INDEXABLE_CLASS.add( Long.class ); INDEXABLE_CLASS.add( String.class ); } static { Version.touch(); //touch version } private final Class beanClass; private transient ResourceBundle messageBundle; private transient ResourceBundle defaultMessageBundle; private transient boolean isUserProvidedResourceBundle; private transient ReflectionManager reflectionManager; private final transient Map childClassValidators; private transient List beanValidators; private transient List memberValidators; private transient List memberGetters; private transient List childGetters; private transient DefaultMessageInterpolatorAggregator defaultInterpolator; private transient MessageInterpolator userInterpolator; private static final Filter GET_ALL_FILTER = new Filter() { public boolean returnStatic() { return true; } public boolean returnTransient() { return true; } }; /** * create the validator engine for this bean type */ public ClassValidator(Class beanClass) { this( beanClass, (ResourceBundle) null ); } /** * create the validator engine for a particular bean class, using a resource bundle * for message rendering on violation */ public ClassValidator(Class beanClass, ResourceBundle resourceBundle) { this( beanClass, resourceBundle, null, new HashMap(), null ); } /** * create the validator engine for a particular bean class, using a custom message interpolator * for message rendering on violation */ public ClassValidator(Class beanClass, MessageInterpolator interpolator) { this( beanClass, null, interpolator, new HashMap(), null ); } /** * Not a public API */ public ClassValidator( Class beanClass, ResourceBundle resourceBundle, MessageInterpolator interpolator, Map childClassValidators, ReflectionManager reflectionManager ) { this.reflectionManager = reflectionManager != null ? reflectionManager : new JavaReflectionManager(); XClass beanXClass = this.reflectionManager.toXClass( beanClass ); this.beanClass = beanClass; this.messageBundle = resourceBundle == null ? getDefaultResourceBundle() : resourceBundle; this.defaultMessageBundle = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE ); this.userInterpolator = interpolator; this.childClassValidators = childClassValidators != null ? childClassValidators : new HashMap(); initValidator( beanXClass, this.childClassValidators ); } @SuppressWarnings("unchecked") protected ClassValidator( XClass beanXClass, ResourceBundle resourceBundle, MessageInterpolator userInterpolator, Map childClassValidators, ReflectionManager reflectionManager ) { this.reflectionManager = reflectionManager; this.beanClass = reflectionManager.toClass( beanXClass ); this.messageBundle = resourceBundle == null ? getDefaultResourceBundle() : resourceBundle; this.defaultMessageBundle = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE ); this.userInterpolator = userInterpolator; this.childClassValidators = childClassValidators; initValidator( beanXClass, childClassValidators ); } private ResourceBundle getDefaultResourceBundle() { ResourceBundle rb; try { //use context class loader as a first citizen ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if ( contextClassLoader == null ) { throw new MissingResourceException( "No context classloader", null, VALIDATOR_MESSAGE ); } rb = ResourceBundle.getBundle( VALIDATOR_MESSAGE, Locale.getDefault(), contextClassLoader ); } catch (MissingResourceException e) { log.trace( "ResourceBundle {} not found in thread context classloader", VALIDATOR_MESSAGE ); //then use the Validator Framework classloader try { rb = ResourceBundle.getBundle( VALIDATOR_MESSAGE, Locale.getDefault(), this.getClass().getClassLoader() ); } catch (MissingResourceException ee) { log.debug( "ResourceBundle ValidatorMessages not found in Validator classloader. Delegate to {}", DEFAULT_VALIDATOR_MESSAGE ); //the user did not override the default ValidatorMessages rb = null; } } isUserProvidedResourceBundle = true; return rb; } private void initValidator( XClass xClass, Map childClassValidators ) { beanValidators = new ArrayList(); memberValidators = new ArrayList(); memberGetters = new ArrayList(); childGetters = new ArrayList(); defaultInterpolator = new DefaultMessageInterpolatorAggregator(); defaultInterpolator.initialize( messageBundle, defaultMessageBundle ); //build the class hierarchy to look for members in childClassValidators.put( xClass, this ); Collection classes = new HashSet(); addSuperClassesAndInterfaces( xClass, classes ); for ( XClass currentClass : classes ) { Annotation[] classAnnotations = currentClass.getAnnotations(); for ( int i = 0; i < classAnnotations.length ; i++ ) { Annotation classAnnotation = classAnnotations[i]; Validator beanValidator = createValidator( classAnnotation ); if ( beanValidator != null ) beanValidators.add( beanValidator ); handleAggregateAnnotations(classAnnotation, null); } } //Check on all selected classes for ( XClass currClass : classes ) { List methods = currClass.getDeclaredMethods(); for ( XMethod method : methods ) { createMemberValidator( method ); createChildValidator( method ); } List fields = currClass.getDeclaredProperties( "field", GET_ALL_FILTER ); for ( XProperty field : fields ) { createMemberValidator( field ); createChildValidator( field ); } } } private void addSuperClassesAndInterfaces(XClass clazz, Collection classes) { for ( XClass currClass = clazz; currClass != null ; currClass = currClass.getSuperclass() ) { if ( ! classes.add( currClass ) ) return; XClass[] interfaces = currClass.getInterfaces(); for ( XClass interf : interfaces ) { addSuperClassesAndInterfaces( interf, classes ); } } } private boolean handleAggregateAnnotations(Annotation annotation, XMember member) { Object[] values; try { Method valueMethod = annotation.getClass().getMethod( "value" ); if ( valueMethod.getReturnType().isArray() ) { values = (Object[]) valueMethod.invoke( annotation ); } else { return false; } } catch (NoSuchMethodException e) { return false; } catch (Exception e) { throw new IllegalStateException( e ); } boolean validatorPresent = false; for ( Object value : values ) { if ( value instanceof Annotation ) { annotation = (Annotation) value; Validator validator = createValidator( annotation ); if ( validator != null ) { if ( member != null ) { //member memberValidators.add( validator ); setAccessible( member ); memberGetters.add( member ); } else { //bean beanValidators.add( validator ); } validatorPresent = true; } } } return validatorPresent; } @SuppressWarnings("unchecked") private void createChildValidator( XMember member) { if ( member.isAnnotationPresent( Valid.class ) ) { setAccessible( member ); childGetters.add( member ); XClass clazz; if ( member.isCollection() || member.isArray() ) { clazz = member.getElementClass(); } else { clazz = member.getType(); } if ( !childClassValidators.containsKey( clazz ) ) { //ClassValidator added by side effect (added to childClassValidators during CV construction) new ClassValidator( clazz, messageBundle, userInterpolator, childClassValidators, reflectionManager ); } } } private void createMemberValidator(XMember member) { boolean validatorPresent = false; Annotation[] memberAnnotations = member.getAnnotations(); for ( Annotation methodAnnotation : memberAnnotations ) { Validator propertyValidator = createValidator( methodAnnotation ); if ( propertyValidator != null ) { memberValidators.add( propertyValidator ); setAccessible( member ); memberGetters.add( member ); validatorPresent = true; } boolean agrValidPresent = handleAggregateAnnotations( methodAnnotation, member ); validatorPresent = validatorPresent || agrValidPresent; } if ( validatorPresent && !member.isTypeResolved() ) { log.warn( "Original type of property {} is unbound and has been approximated.", member ); } } private static void setAccessible(XMember member) { if ( !Modifier.isPublic( member.getModifiers() ) ) { member.setAccessible( true ); } } @SuppressWarnings("unchecked") private Validator createValidator(Annotation annotation) { try { ValidatorClass validatorClass = annotation.annotationType().getAnnotation( ValidatorClass.class ); if ( validatorClass == null ) { return null; } Validator beanValidator = validatorClass.value().newInstance(); beanValidator.initialize( annotation ); defaultInterpolator.addInterpolator( annotation, beanValidator ); return beanValidator; } catch (Exception e) { throw new IllegalArgumentException( "could not instantiate ClassValidator", e ); } } public boolean hasValidationRules() { return beanValidators.size() != 0 || memberValidators.size() != 0; } /** * apply constraints on a bean instance and return all the failures. * if bean is null, an empty array is returned */ public InvalidValue[] getInvalidValues(T bean) { return this.getInvalidValues( bean, new IdentitySet() ); } /** * apply constraints on a bean instance and return all the failures. * if bean is null, an empty array is returned */ @SuppressWarnings("unchecked") protected InvalidValue[] getInvalidValues(T bean, Set circularityState) { if ( bean == null || circularityState.contains( bean ) ) { return EMPTY_INVALID_VALUE_ARRAY; //Avoid circularity } else { circularityState.add( bean ); } if ( !beanClass.isInstance( bean ) ) { throw new IllegalArgumentException( "not an instance of: " + bean.getClass() ); } List results = new ArrayList(); for ( int i = 0; i < beanValidators.size() ; i++ ) { Validator validator = beanValidators.get( i ); if ( !validator.isValid( bean ) ) { results.add( new InvalidValue( interpolate(validator), beanClass, null, bean, bean ) ); } } for ( int i = 0; i < memberValidators.size() ; i++ ) { XMember getter = memberGetters.get( i ); if ( Hibernate.isPropertyInitialized( bean, getPropertyName( getter ) ) ) { Object value = getMemberValue( bean, getter ); Validator validator = memberValidators.get( i ); if ( !validator.isValid( value ) ) { String propertyName = getPropertyName( getter ); results.add( new InvalidValue( interpolate(validator), beanClass, propertyName, value, bean ) ); } } } for ( int i = 0; i < childGetters.size() ; i++ ) { XMember getter = childGetters.get( i ); if ( Hibernate.isPropertyInitialized( bean, getPropertyName( getter ) ) ) { Object value = getMemberValue( bean, getter ); if ( value != null && Hibernate.isInitialized( value ) ) { String propertyName = getPropertyName( getter ); if ( getter.isCollection() ) { int index = 0; boolean isIterable = value instanceof Iterable; Map map = ! isIterable ? (Map) value : null; Iterable elements = isIterable ? (Iterable) value : map.keySet(); for ( Object element : elements ) { Object actualElement = isIterable ? element : map.get( element ); if ( actualElement == null ) { index++; continue; } InvalidValue[] invalidValues = getClassValidator( actualElement ) .getInvalidValues( actualElement, circularityState ); String indexedPropName = MessageFormat.format( "{0}[{1}]", propertyName, INDEXABLE_CLASS.contains( element.getClass() ) ? ( "'" + element + "'" ) : index ); index++; for ( InvalidValue invalidValue : invalidValues ) { invalidValue.addParentBean( bean, indexedPropName ); results.add( invalidValue ); } } } if ( getter.isArray() ) { int index = 0; for ( Object element : (Object[]) value ) { if ( element == null ) { index++; continue; } InvalidValue[] invalidValues = getClassValidator( element ) .getInvalidValues( element, circularityState ); String indexedPropName = MessageFormat.format( "{0}[{1}]", propertyName, index ); index++; for ( InvalidValue invalidValue : invalidValues ) { invalidValue.addParentBean( bean, indexedPropName ); results.add( invalidValue ); } } } else { InvalidValue[] invalidValues = getClassValidator( value ) .getInvalidValues( value, circularityState ); for ( InvalidValue invalidValue : invalidValues ) { invalidValue.addParentBean( bean, propertyName ); results.add( invalidValue ); } } } } } return results.toArray( new InvalidValue[results.size()] ); } private String interpolate(Validator validator) { String message = defaultInterpolator.getAnnotationMessage( validator ); if (userInterpolator != null) { return userInterpolator.interpolate( message, validator, defaultInterpolator ); } else { return defaultInterpolator.interpolate( message, validator, null); } } @SuppressWarnings("unchecked") private ClassValidator getClassValidator(Object value) { Class clazz = value.getClass(); ClassValidator validator = childClassValidators.get( reflectionManager.toXClass( clazz ) ); if ( validator == null ) { //handles polymorphism //TODO cache this thing. in a second queue (reflectionManager being sealed)? beware of concurrency validator = new ClassValidator( clazz ); } return validator; } /** * Apply constraints of a particular property on a bean instance and return all the failures. * Note this is not recursive. */ //TODO should it be recursive? public InvalidValue[] getInvalidValues(T bean, String propertyName) { List results = new ArrayList(); for ( int i = 0; i < memberValidators.size() ; i++ ) { XMember getter = memberGetters.get( i ); if ( getPropertyName( getter ).equals( propertyName ) ) { Object value = getMemberValue( bean, getter ); Validator validator = memberValidators.get( i ); if ( !validator.isValid( value ) ) { results.add( new InvalidValue( interpolate(validator), beanClass, propertyName, value, bean ) ); } } } return results.toArray( new InvalidValue[results.size()] ); } /** * Apply constraints of a particular property value of a bean type and return all the failures. * The InvalidValue objects returns return null for InvalidValue#getBean() and InvalidValue#getRootBean() * Note this is not recursive. */ //TODO should it be recursive? public InvalidValue[] getPotentialInvalidValues(String propertyName, Object value) { List results = new ArrayList(); for ( int i = 0; i < memberValidators.size() ; i++ ) { XMember getter = memberGetters.get( i ); if ( getPropertyName( getter ).equals( propertyName ) ) { Validator validator = memberValidators.get( i ); if ( !validator.isValid( value ) ) { results.add( new InvalidValue( interpolate(validator), beanClass, propertyName, value, null ) ); } } } return results.toArray( new InvalidValue[results.size()] ); } private Object getMemberValue(T bean, XMember getter) { Object value; try { value = getter.invoke( bean ); } catch (Exception e) { throw new IllegalStateException( "Could not get property value", e ); } return value; } private String getPropertyName(XMember member) { //Do no try to cache the result in a map, it's actually much slower (2.x time) String propertyName; if ( XProperty.class.isAssignableFrom( member.getClass() ) ) { propertyName = member.getName(); } else if ( XMethod.class.isAssignableFrom( member.getClass() ) ) { propertyName = member.getName(); if ( propertyName.startsWith( "is" ) ) { propertyName = Introspector.decapitalize( propertyName.substring( 2 ) ); } else if ( propertyName.startsWith( "get" ) ) { propertyName = Introspector.decapitalize( propertyName.substring( 3 ) ); } //do nothing for non getter method, in case someone want to validate a PO Method } else { throw new AssertionFailure( "Unexpected member: " + member.getClass().getName() ); } return propertyName; } /** @deprecated */ private String replace(String message, Annotation parameters) { StringTokenizer tokens = new StringTokenizer( message, "#{}", true ); StringBuilder buf = new StringBuilder( 30 ); boolean escaped = false; boolean el = false; while ( tokens.hasMoreTokens() ) { String token = tokens.nextToken(); if ( !escaped && "#".equals( token ) ) { el = true; } if ( !el && "{".equals( token ) ) { escaped = true; } else if ( escaped && "}".equals( token ) ) { escaped = false; } else if ( !escaped ) { if ( "{".equals( token ) ) el = false; buf.append( token ); } else { Method member; try { member = parameters.getClass().getMethod( token, (Class[]) null ); } catch (NoSuchMethodException nsfme) { member = null; } if ( member != null ) { try { buf.append( member.invoke( parameters ) ); } catch (Exception e) { throw new IllegalArgumentException( "could not render message", e ); } } else { String string = null; try { string = messageBundle != null ? messageBundle.getString( token ) : null; } catch( MissingResourceException e ) { //give a second chance with the default resource bundle } if (string == null) { try { string = defaultMessageBundle.getString( token ); } catch( MissingResourceException e) { throw new MissingResourceException( "Can't find resource in validator bundles, key " + token, defaultMessageBundle.getClass().getName(), token ); } } if ( string != null ) buf.append( replace( string, parameters ) ); } } } return buf.toString(); } /** * apply the registred constraints rules on the hibernate metadata (to be applied on DB schema...) * * @param persistentClass hibernate metadata */ public void apply(PersistentClass persistentClass) { for ( Validator validator : beanValidators ) { if ( validator instanceof PersistentClassConstraint ) { ( (PersistentClassConstraint) validator ).apply( persistentClass ); } } Iterator validators = memberValidators.iterator(); Iterator getters = memberGetters.iterator(); while ( validators.hasNext() ) { Validator validator = validators.next(); String propertyName = getPropertyName( getters.next() ); if ( validator instanceof PropertyConstraint ) { try { Property property = findPropertyByName(persistentClass, propertyName); if (property != null) { ( (PropertyConstraint) validator ).apply( property ); } } catch (MappingException pnfe) { //do nothing } } } } public void assertValid(T bean) { InvalidValue[] values = getInvalidValues( bean ); if ( values.length > 0 ) { throw new InvalidStateException( values ); } } private void writeObject(ObjectOutputStream oos) throws IOException { ResourceBundle rb = messageBundle; MessageInterpolator interpolator = this.userInterpolator; if ( rb != null && ! ( rb instanceof Serializable ) ) { messageBundle = null; if ( ! isUserProvidedResourceBundle ) { log.warn( "Serializing a ClassValidator with a non serializable ResourceBundle: ResourceBundle ignored" ); } } if (interpolator != null && ! (interpolator instanceof Serializable) ) { userInterpolator = null; log.warn( "Serializing a non serializable MessageInterpolator" ); } oos.defaultWriteObject(); oos.writeObject( messageBundle ); oos.writeObject( userInterpolator ); messageBundle = rb; userInterpolator = interpolator; } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); ResourceBundle rb = (ResourceBundle) ois.readObject(); if ( rb == null ) rb = getDefaultResourceBundle(); this.messageBundle = rb; this.userInterpolator = (MessageInterpolator) ois.readObject(); this.defaultMessageBundle = ResourceBundle.getBundle( DEFAULT_VALIDATOR_MESSAGE ); reflectionManager = new JavaReflectionManager(); initValidator( reflectionManager.toXClass( beanClass ), new HashMap() ); } /** * Retrieve the property by path in a recursive way, including IndetifierProperty in the loop * If propertyName is null or empty, the IdentifierProperty is returned */ public static Property findPropertyByName(PersistentClass associatedClass, String propertyName) { Property property = null; Property idProperty = associatedClass.getIdentifierProperty(); String idName = idProperty != null ? idProperty.getName() : null; try { if ( propertyName == null || propertyName.length() == 0 || propertyName.equals( idName ) ) { //default to id property = idProperty; } else { if ( propertyName.indexOf( idName + "." ) == 0 ) { property = idProperty; propertyName = propertyName.substring( idName.length() + 1 ); } StringTokenizer st = new StringTokenizer( propertyName, ".", false ); while ( st.hasMoreElements() ) { String element = (String) st.nextElement(); if ( property == null ) { property = associatedClass.getProperty( element ); } else { if ( ! property.isComposite() ) return null; property = ( (Component) property.getValue() ).getProperty( element ); } } } } catch (MappingException e) { try { //if we do not find it try to check the identifier mapper if ( associatedClass.getIdentifierMapper() == null ) return null; StringTokenizer st = new StringTokenizer( propertyName, ".", false ); while ( st.hasMoreElements() ) { String element = (String) st.nextElement(); if ( property == null ) { property = associatedClass.getIdentifierMapper().getProperty( element ); } else { if ( ! property.isComposite() ) return null; property = ( (Component) property.getValue() ).getProperty( element ); } } } catch (MappingException ee) { return null; } } return property; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Environment.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000173511052766205033405 0ustar twernertwerner//$Id: Environment.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; /** * Hibernate Validator Event properties * The properties are retrieved from Hibernate * (hibernate.properties, hibernate.cfg.xml, persistence.xml or Configuration API) * * @author Emmanuel Bernard */ public class Environment { /** * Message interpolator class used. The same instance is shared across all ClassValidators */ public static final String MESSAGE_INTERPOLATOR_CLASS = "hibernate.validator.message_interpolator_class"; /** * Apply DDL changes on Hibernate metamodel when using validator with Hibernate Annotations. Default to true. */ public static final String APPLY_TO_DDL = "hibernate.validator.apply_to_ddl"; /** * Enable listeners auto registration in Hibernate Annotations and EntityManager. Default to true. */ public static final String AUTOREGISTER_LISTENERS = "hibernate.validator.autoregister_listeners"; } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/NotNull.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000115211131662636033377 0ustar twernertwerner//$Id: NotNull.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * not null constraint * * @author Gavin King */ @Documented @ValidatorClass(NotNullValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface NotNull { String message() default "{validator.notNull}"; } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/NotEmptyValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000302311052766205033375 0ustar twernertwerner//$Id: NotEmptyValidator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.lang.reflect.Array; import java.util.Collection; import java.util.Map; import java.util.Iterator; import org.hibernate.mapping.Property; import org.hibernate.mapping.SingleTableSubclass; import org.hibernate.mapping.Column; /** * Check the non emptyness of the element * * @author Gavin King */ public class NotEmptyValidator implements Validator, PropertyConstraint, Serializable { public void initialize(NotEmpty parameters) { } public boolean isValid(Object value) { if ( value == null ) return false; if ( value.getClass().isArray() ) { return Array.getLength( value ) > 0; } else if ( value instanceof Collection ) { return ( (Collection) value ).size() > 0; } else if ( value instanceof Map ) { return ( (Map) value ).size() > 0; } else { return ( (String) value ).length() > 0; } } @SuppressWarnings("unchecked") public void apply(Property property) { if ( ! ( property.getPersistentClass() instanceof SingleTableSubclass ) && ! ( property.getValue() instanceof Collection ) ) { //single table should not be forced to null if ( !property.isComposite() ) { //composite should not add not-null on all columns Iterator iter = (Iterator) property.getColumnIterator(); while ( iter.hasNext() ) { iter.next().setNullable( false ); } } } } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Size.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000126311131662636033402 0ustar twernertwerner//$Id: Size.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Size range for Arrays, Collections or Maps * * @author Gavin King */ @Documented @ValidatorClass(SizeValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Size { int max() default Integer.MAX_VALUE; int min() default 0; String message() default "{validator.size}"; } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Version.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000072711061723465033406 0ustar twernertwerner//$Id: Version.java 15169 2008-09-10 10:53:41Z hardy.ferentschik $ package org.hibernate.validator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Hibernate Vaildator version * * @author Emmanuel Bernard */ public class Version { public static final String VERSION = "3.1.0.GA"; private static Logger log = LoggerFactory.getLogger( Version.class ); static { log.info( "Hibernate Validator {}", VERSION ); } public static void touch() { } }././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/EmailValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000236311131662636033404 0ustar twernertwerner//$Id: EmailValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.util.regex.Matcher; /** * Check that a given string is a well-formed email address * * @author Emmanuel Bernard */ public class EmailValidator implements Validator, Serializable { //TODO: Implement this http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html regex in java private static String ATOM = "[^\\x00-\\x1F^\\(^\\)^\\<^\\>^\\@^\\,^\\;^\\:^\\\\^\\\"^\\.^\\[^\\]^\\s]"; private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*"; private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]"; private java.util.regex.Pattern pattern; public boolean isValid(Object value) { if ( value == null ) return true; if ( !( value instanceof String ) ) return false; String string = (String) value; if ( string.length() == 0 ) return true; Matcher m = pattern.matcher( string ); return m.matches(); } public void initialize(Email parameters) { pattern = java.util.regex.Pattern.compile( "^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$", java.util.regex.Pattern.CASE_INSENSITIVE ); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Max.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000120511131662636033376 0ustar twernertwerner//$Id: Max.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * max restriction on a numeric annotated element * * @author Gavin King */ @Documented @ValidatorClass(MaxValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Max { long value(); String message() default "{validator.max}"; } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/AssertTrueValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000112011131662636033372 0ustar twernertwerner//$Id: AssertTrueValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; /** * Check whether an element is true or not. * * @author Gavin King * @author Hardy Ferentschik */ public class AssertTrueValidator implements Validator, Serializable { public boolean isValid(Object value) { if (value == null) return true; if (value instanceof Boolean) { return (Boolean) value; } return false; } public void initialize(AssertTrue parameters) { } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Min.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000126011131662636033377 0ustar twernertwerner//$Id: Min.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * min restriction on a numeric annotated elemnt (or the string representation of a numeric) * * @author Gavin King */ @Documented @ValidatorClass(MinValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Min { long value(); String message() default "{validator.min}"; } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Length.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000133711131662636033404 0ustar twernertwerner//$Id: Length.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Apply some length restrictions to the annotated element. It has to be a string * * @author Gavin King */ @Documented @ValidatorClass(LengthValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Length { int max() default Integer.MAX_VALUE; int min() default 0; String message() default "{validator.length}"; } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/ValidatorClass.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000111611131662636033377 0ustar twernertwerner//$Id: ValidatorClass.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Link between an constraint annotation and it's validator implementation * * @author Gavin King */ @Documented @Target({ANNOTATION_TYPE}) @Retention(RUNTIME) public @interface ValidatorClass { Class value(); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/NotEmpty.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000132211052766205033375 0ustar twernertwerner//$Id: NotEmpty.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import java.lang.annotation.Target; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; /** * Check that a String is not empty (not null and length > 0) * or that a Collection (or array) is not empty (not null and length > 0) * * @author Emmanuel Bernard */ @Documented @ValidatorClass(NotEmptyValidator.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention( RetentionPolicy.RUNTIME ) public @interface NotEmpty { String message() default "{validator.notEmpty}"; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/AssertTrue.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000120711131662636033400 0ustar twernertwerner//$Id: AssertTrue.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * The annotated element has to be true * * @author Gavin King */ @Documented @ValidatorClass(AssertTrueValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface AssertTrue { String message() default "{validator.assertTrue}"; } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/MaxValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000313511131662636033402 0ustar twernertwerner//$Id: MaxValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; /** * Do check a max restriction on a numeric (whether and actual number or its string representation, * and apply expected contraints on hibernate metadata. * * @author Gavin King */ public class MaxValidator implements Validator, PropertyConstraint, Serializable { private long max; public void initialize(Max parameters) { max = parameters.value(); } public boolean isValid(Object value) { if ( value == null ) return true; if ( value instanceof String ) { try { return new BigDecimal( (String) value ).compareTo( BigDecimal.valueOf( max ) ) <= 0; } catch (NumberFormatException nfe) { return false; } } else if ( ( value instanceof Double ) || ( value instanceof Float ) ) { double dv = ( (Number) value ).doubleValue(); return dv <= max; } else if ( value instanceof BigInteger ) { return ( (BigInteger) value ).compareTo( BigInteger.valueOf( max ) ) <= 0; } else if ( value instanceof BigDecimal ) { return ( (BigDecimal) value ).compareTo( BigDecimal.valueOf( max ) ) <= 0; } else if ( value instanceof Number ) { long lv = ( (Number) value ).longValue(); return lv <= max; } else { return false; } } public void apply(Property property) { Column col = (Column) property.getColumnIterator().next(); col.setCheckConstraint( col.getName() + "<=" + max ); } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/EAN.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000127511052766205033404 0ustar twernertwerner//$Id: EAN.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import java.lang.annotation.Target; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * The annotated element has to represent an EAN-13 or UPC-A * * which aims to check for user mistake, not actual number validity! * * @author Emmanuel Bernard */ @Documented @ValidatorClass( EANValidator.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention( RetentionPolicy.RUNTIME ) public @interface EAN { String message() default "{validator.ean}"; } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Valid.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000755000175000017500000000105611131662636033405 0ustar twernertwerner//$Id: Valid.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * Enables recursive validation of an associated object * * @author Gavin King */ @Documented @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Valid { } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Range.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000143311131662636033401 0ustar twernertwerner//$Id: Range.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * The annotated elemnt has to be in the appropriate range. Apply on numeric values or string * representation of the numeric value. * * @author Gavin King */ @Documented @ValidatorClass(RangeValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Range { long max() default Long.MAX_VALUE; long min() default Long.MIN_VALUE; String message() default "{validator.range}"; } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Validator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000075211131662636033404 0ustar twernertwerner//$Id: Validator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Annotation; /** * A constraint validator for a particular annotation * * @author Gavin King */ public interface Validator { /** * does the object/element pass the constraints */ public boolean isValid(Object value); /** * Take the annotations values * * @param parameters */ public void initialize(A parameters); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Patterns.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000112711052766205033400 0ustar twernertwerner//$Id: Patterns.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import java.lang.annotation.Target; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.FIELD; /** * The annotated element must follow the list of regexp patterns * * @author Emmanuel Bernard */ @Documented @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Patterns { Pattern[] value(); } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/interpolator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000755000175000017500000000000011402110377033365 5ustar twernertwerner././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/interpolator/DefaultMessageInterpolator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000001127411052766205033404 0ustar twernertwerner//$Id: DefaultMessageInterpolator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.interpolator; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.HashMap; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.StringTokenizer; import org.hibernate.util.StringHelper; import org.hibernate.validator.MessageInterpolator; import org.hibernate.validator.Validator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Resource bundle based interpolator * Also interpolate annotation parameters inside the message * * @author Emmanuel Bernard */ public class DefaultMessageInterpolator implements MessageInterpolator, Serializable { private static final Logger log = LoggerFactory.getLogger( DefaultMessageInterpolator.class ); private Map annotationParameters = new HashMap(); private transient ResourceBundle messageBundle; private transient ResourceBundle defaultMessageBundle; private String annotationMessage; private String interpolateMessage; //not an interface method public void initialize(ResourceBundle messageBundle, ResourceBundle defaultMessageBundle) { this.messageBundle = messageBundle; this.defaultMessageBundle = defaultMessageBundle; } public void initialize(Annotation annotation, MessageInterpolator defaultInterpolator) { Class clazz = annotation.getClass(); for ( Method method : clazz.getMethods() ) { try { //FIXME remove non serilalization elements on writeObject? if ( method.getReturnType() != void.class && method.getParameterTypes().length == 0 && ! Modifier.isStatic( method.getModifiers() ) ) { //cannot use an exclude list because the parameter name could match a method name annotationParameters.put( method.getName(), method.invoke( annotation ) ); } } catch (IllegalAccessException e) { //really should not happen, but we degrade nicely log.warn( "Unable to access {}", StringHelper.qualify( clazz.toString(), method.getName() ) ); } catch (InvocationTargetException e) { //really should not happen, but we degrade nicely log.warn( "Unable to access {}", StringHelper.qualify( clazz.toString(), method.getName() ) ); } } annotationMessage = (String) annotationParameters.get( "message" ); if (annotationMessage == null) { throw new IllegalArgumentException( "Annotation " + clazz + " does not have an (accessible) message attribute"); } //do not resolve the property eagerly to allow validator.apply to work wo interpolator } private String replace(String message) { StringTokenizer tokens = new StringTokenizer( message, "#{}", true ); StringBuilder buf = new StringBuilder( 30 ); boolean escaped = false; boolean el = false; while ( tokens.hasMoreTokens() ) { String token = tokens.nextToken(); if ( !escaped && "#".equals( token ) ) { el = true; } if ( !el && "{".equals( token ) ) { escaped = true; } else if ( escaped && "}".equals( token ) ) { escaped = false; } else if ( !escaped ) { if ( "{".equals( token ) ) el = false; buf.append( token ); } else { Object variable = annotationParameters.get( token ); if ( variable != null ) { buf.append( variable ); } else { String string = null; try { string = messageBundle != null ? messageBundle.getString( token ) : null; } catch( MissingResourceException e ) { //give a second chance with the default resource bundle } if (string == null) { try { string = defaultMessageBundle.getString( token ); } catch( MissingResourceException e) { //return the unchanged string buf.append('{').append(token).append('}'); } } if ( string != null ) buf.append( replace( string ) ); } } } return buf.toString(); } public String interpolate(String message, Validator validator, MessageInterpolator defaultInterpolator) { if ( annotationMessage.equals( message ) ) { //short cut if (interpolateMessage == null) { interpolateMessage = replace( annotationMessage ); } return interpolateMessage; } else { //TODO keep them in a weak hash map, but this might not even be useful return replace( message ); } } public String getAnnotationMessage() { return annotationMessage; } } ././@LongLink0000000000000000000000000000023500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/interpolator/DefaultMessageInterpolatorAggregator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000470611052766205033406 0ustar twernertwerner//$Id: DefaultMessageInterpolatorAggregator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.interpolator; import java.lang.annotation.Annotation; import java.util.Map; import java.util.HashMap; import java.util.ResourceBundle; import java.io.Serializable; import org.hibernate.validator.MessageInterpolator; import org.hibernate.validator.Validator; import org.hibernate.AssertionFailure; /** * @author Emmanuel Bernard */ public class DefaultMessageInterpolatorAggregator implements MessageInterpolator, Serializable { private transient Map interpolators = new HashMap(); //transient but repopulated by the object owing a reference to the interpolator private transient ResourceBundle messageBundle; //transient but repopulated by the object owing a reference to the interpolator private transient ResourceBundle defaultMessageBundle; //not an interface method public void initialize(ResourceBundle messageBundle, ResourceBundle defaultMessageBundle) { this.messageBundle = messageBundle; this.defaultMessageBundle = defaultMessageBundle; //useful when we deserialize for ( DefaultMessageInterpolator interpolator : interpolators.values() ) { interpolator.initialize( messageBundle, defaultMessageBundle ); } } public void addInterpolator(Annotation annotation, Validator validator) { DefaultMessageInterpolator interpolator = new DefaultMessageInterpolator(); interpolator.initialize(messageBundle, defaultMessageBundle ); interpolator.initialize( annotation, null ); interpolators.put( validator, interpolator ); } public String interpolate(String message, Validator validator, MessageInterpolator defaultInterpolator) { DefaultMessageInterpolator defaultMessageInterpolator = interpolators.get( validator ); if (defaultMessageInterpolator == null) { return message; } else { return defaultMessageInterpolator.interpolate( message, validator, defaultInterpolator ); } } public String getAnnotationMessage(Validator validator) { DefaultMessageInterpolator defaultMessageInterpolator = interpolators.get( validator ); String message = defaultMessageInterpolator != null ? defaultMessageInterpolator.getAnnotationMessage() : null; if (message == null) throw new AssertionFailure("Validator not registred to the messageInterceptorAggregator"); return message; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/event/libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000755000175000017500000000000011402110377033365 5ustar twernertwerner././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/event/ValidateEventListener.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000001747111227341464033411 0ustar twernertwerner//$Id: ValidateEventListener.java 17094 2009-07-15 11:53:24Z hardy.ferentschik $ package org.hibernate.validator.event; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.hibernate.AssertionFailure; import org.hibernate.EntityMode; import org.hibernate.HibernateException; import org.hibernate.cfg.Configuration; import org.hibernate.event.Initializable; import org.hibernate.event.PreInsertEvent; import org.hibernate.event.PreInsertEventListener; import org.hibernate.event.PreUpdateEvent; import org.hibernate.event.PreUpdateEventListener; import org.hibernate.mapping.Component; import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.Property; import org.hibernate.property.Getter; import org.hibernate.property.PropertyAccessor; import org.hibernate.property.PropertyAccessorFactory; import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.java.JavaReflectionManager; import org.hibernate.util.ReflectHelper; import org.hibernate.util.StringHelper; import org.hibernate.validator.ClassValidator; import org.hibernate.validator.Environment; import org.hibernate.validator.InvalidStateException; import org.hibernate.validator.InvalidValue; import org.hibernate.validator.MessageInterpolator; /** * Before insert and update, executes the validator framework * * @author Emmanuel Bernard */ public class ValidateEventListener implements PreInsertEventListener, PreUpdateEventListener, Initializable { private boolean isInitialized; private Map validators = new HashMap(); /** * initialize the validators, any non significant validators are not kept */ @SuppressWarnings( "unchecked" ) public synchronized void initialize(final Configuration cfg) { if ( !isInitialized ) { String interpolatorString = cfg.getProperty( Environment.MESSAGE_INTERPOLATOR_CLASS ); MessageInterpolator interpolator = null; if ( StringHelper.isNotEmpty( interpolatorString ) ) { try { Class interpolatorClass = ReflectHelper.classForName( interpolatorString ); interpolator = (MessageInterpolator) interpolatorClass.newInstance(); } catch (ClassNotFoundException e) { throw new HibernateException( "Unable to find message interpolator: " + interpolatorString, e ); } catch (IllegalAccessException e) { throw new HibernateException( "Unable to instanciate message interpolator: " + interpolatorString, e ); } catch (InstantiationException e) { throw new HibernateException( "Unable to instanciate message interpolator: " + interpolatorString, e ); } catch (ClassCastException e) { throw new HibernateException( "Class does not implement " + MessageInterpolator.class.getName() + ": " + interpolatorString, e ); } } Iterator classes = (Iterator) cfg.getClassMappings(); ReflectionManager reflectionManager; try { //TODO introduce q ReflectionManagerHolder interface to avoid reflection //I want to avoid hard link between HAN and Validator for usch a simple need //reuse the existing reflectionManager one when possible reflectionManager = (ReflectionManager) cfg.getClass().getMethod( "getReflectionManager" ).invoke( cfg ); } catch (Exception e) { reflectionManager = new JavaReflectionManager(); } while ( classes.hasNext() ) { PersistentClass clazz = classes.next(); final Class mappedClass = clazz.getMappedClass(); ClassValidator validator = new ClassValidator( mappedClass, null, interpolator, null, reflectionManager ); ValidatableElement element = new ValidatableElement( mappedClass, validator ); addSubElement( clazz.getIdentifierProperty(), element ); Iterator properties = clazz.getPropertyIterator(); while ( properties.hasNext() ) { addSubElement( (Property) properties.next(), element ); } if ( element.subElements.size() != 0 || element.validator.hasValidationRules() ) { validators.put( mappedClass, element ); } } isInitialized = true; } } @SuppressWarnings( "unchecked" ) private void addSubElement(Property property, ValidatableElement element) { if ( property != null && property.isComposite() && !property.isBackRef() ) { Component component = (Component) property.getValue(); if ( component.isEmbedded() ) return; PropertyAccessor accessor = PropertyAccessorFactory.getPropertyAccessor( property, EntityMode.POJO ); Getter getter = accessor.getGetter( element.clazz, property.getName() ); ClassValidator validator = new ClassValidator( getter.getReturnType() ); ValidatableElement subElement = new ValidatableElement( getter.getReturnType(), validator, getter ); Iterator properties = component.getPropertyIterator(); while ( properties.hasNext() ) { addSubElement( (Property) properties.next(), subElement ); } if ( subElement.getSubElements().size() != 0 || subElement.validator.hasValidationRules() ) { element.addSubElement( subElement ); } } } @SuppressWarnings( "unchecked" ) protected void validate(Object entity, EntityMode mode) { if ( entity == null || !EntityMode.POJO.equals( mode ) ) return; ValidatableElement element; if ( isInitialized ) { element = validators.get( entity.getClass() ); } else { throw new AssertionFailure( "Validator event not initialized" ); } if ( element == null ) return; //no validation to do List consolidatedInvalidValues = new ArrayList(); validateSubElements( element, entity, consolidatedInvalidValues ); InvalidValue[] invalidValues = element.validator == null ? null : element.validator.getInvalidValues( entity ); if ( invalidValues != null ) { for ( InvalidValue invalidValue : invalidValues ) { consolidatedInvalidValues.add( invalidValue ); } } if ( consolidatedInvalidValues.size() > 0 ) { throw new InvalidStateException( consolidatedInvalidValues.toArray( new InvalidValue[consolidatedInvalidValues.size()] ), entity.getClass().getName() ); } } @SuppressWarnings( "unchecked" ) private void validateSubElements( ValidatableElement element, Object entity, List consolidatedInvalidValues ) { if ( element != null ) { for ( ValidatableElement subElement : element.subElements ) { Object component = subElement.getter.get( entity ); InvalidValue[] invalidValues = subElement.validator.getInvalidValues( component ); for ( InvalidValue invalidValue : invalidValues ) { consolidatedInvalidValues.add( invalidValue ); } validateSubElements( subElement, component, consolidatedInvalidValues ); } } } @SuppressWarnings({ "deprecation" }) public boolean onPreInsert(PreInsertEvent event) { validate( event.getEntity(), event.getSource().getEntityMode() ); return false; } @SuppressWarnings({ "deprecation" }) public boolean onPreUpdate(PreUpdateEvent event) { validate( event.getEntity(), event.getSource().getEntityMode() ); return false; } private static class ValidatableElement implements Serializable { private Class clazz; private ClassValidator validator; private Getter getter; private Collection subElements = new ArrayList(); public ValidatableElement(Class clazz, ClassValidator validator) { this.clazz = clazz; this.validator = validator; } public ValidatableElement(Class clazz, ClassValidator validator, Getter getter) { this( clazz, validator ); this.getter = getter; } public void addSubElement(ValidatableElement subValidatableElement) { subElements.add( subValidatableElement ); } public Collection getSubElements() { return this.subElements; } } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/event/ValidatePreUpdateEventListener.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000052011131662636033375 0ustar twernertwerner//$Id: ValidatePreUpdateEventListener.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.event; /** * Before update, execute the validator framework * * @deprecated use ValidateEventListener * * @author Gavin King */ public class ValidatePreUpdateEventListener extends ValidateEventListener { } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/event/ValidatePreInsertEventListener.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000052111131662636033376 0ustar twernertwerner//$Id: ValidatePreInsertEventListener.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator.event; /** * Before insert, execute the validator framework * * @deprecated use ValidateEventListener * * @author Gavin King */ public class ValidatePreInsertEventListener extends ValidateEventListener { } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/event/JPAValidateListener.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000411411052766205033377 0ustar twernertwerner//$Id: JPAValidateListener.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator.event; import java.lang.ref.WeakReference; import java.util.Map; import java.util.WeakHashMap; import java.util.Set; import java.util.HashSet; import javax.persistence.PrePersist; import javax.persistence.PreUpdate; import org.hibernate.validator.ClassValidator; /** * Java Persistence Entity Listener that validates entities on inserts or updates * This listener needs ot be placed on each validatable entities * * * @Entity * @EntityListeners(JPAValidateListener.class) * public class Submarine { * @NotEmpty private String name; * ... * } * * * @author Emmanuel Bernard */ public class JPAValidateListener { //No need for weakReference if the event listener is loaded by the same CL than //the entities, but in a shared env this is not the case //TODO check that this can be hot redeployable private static final Map> validators; private static final ClassValidator NO_VALIDATOR; static { validators = new WeakHashMap>(); NO_VALIDATOR = new ClassValidator( JPAValidateListener.class); } //keep hardref at the instance level private final Set currentValidators = new HashSet(); @PrePersist @PreUpdate @SuppressWarnings( "unchecked" ) public void onChange(Object object) { if (object == null) return; Class entity = object.getClass(); WeakReference weakValidator = validators.get(entity); ClassValidator validator = weakValidator != null ? weakValidator.get() : null; if ( validator == null ) { //initialize //TODO reuse the same reflection manager? validator = new ClassValidator(entity); if ( ! validator.hasValidationRules() ) { validator = NO_VALIDATOR; } validators.put( entity, new WeakReference(validator) ); currentValidators.add( validator ); } if ( validator != NO_VALIDATOR ) { validator.assertValid( object ); } } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Digits.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000147611052766205033407 0ustar twernertwerner//$Id: Digits.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.ElementType; import java.lang.annotation.Target; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Check that a given number has integerDigits integer digits * and fractionalDigits fractional digits * The constraints are defined at the database level too * * @author Norman Richards */ @ValidatorClass(DigitsValidator.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention( RetentionPolicy.RUNTIME) @Documented public @interface Digits { int integerDigits(); int fractionalDigits() default 0; String message() default "{validator.digits}"; }././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/RangeValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000314111131662636033377 0ustar twernertwerner//$Id: RangeValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.math.BigDecimal; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; /** * The value has to be in a defined range, the constraint is also applied on DB * * @author Gavin King */ public class RangeValidator implements Validator, PropertyConstraint, Serializable { private long max; private long min; public void initialize(Range parameters) { max = parameters.max(); min = parameters.min(); } public boolean isValid(Object value) { if ( value == null ) return true; if ( value instanceof String ) { try { BigDecimal dv = new BigDecimal( (String) value ); return dv.compareTo( BigDecimal.valueOf( min ) ) >= 0 && dv.compareTo( BigDecimal.valueOf( max ) ) <= 0; } catch (NumberFormatException nfe) { return false; } } else if ( ( value instanceof Double ) || ( value instanceof Float ) ) { double dv = ( (Number) value ).doubleValue(); return dv >= min && dv <= max; } else if ( value instanceof Number ) { long lv = ( (Number) value ).longValue(); return lv >= min && lv <= max; } else { return false; } } public void apply(Property property) { Column col = (Column) property.getColumnIterator().next(); String check = ""; if ( min != Long.MIN_VALUE ) check += col.getName() + ">=" + min; if ( max != Long.MAX_VALUE && min != Long.MIN_VALUE ) check += " and "; if ( max != Long.MAX_VALUE ) check += col.getName() + "<=" + max; col.setCheckConstraint( check ); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/CreditCardNumberValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000075011052766205033401 0ustar twernertwerner//$Id: CreditCardNumberValidator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; /** * Check a credit card number through the Luhn algorithm * * @author Emmanuel Bernard */ public class CreditCardNumberValidator extends AbstractLuhnValidator implements Validator, Serializable { public void initialize(CreditCardNumber parameters) { } int multiplicator() { return 2; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/AssertFalse.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000121611131662636033400 0ustar twernertwerner//$Id: AssertFalse.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * The annotated property has to be false. * * @author Gavin King */ @Documented @ValidatorClass(AssertFalseValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface AssertFalse { String message() default "{validator.assertFalse}"; } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/InvalidStateException.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000137711131662636033410 0ustar twernertwerner//$Id: InvalidStateException.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; /** * Thrown when the bean has violated one or several of its constraints * You can get the violation details in getInvalidValues() * * @author Gavin King */ public class InvalidStateException extends RuntimeException { private final InvalidValue[] invalidValues; public InvalidStateException(InvalidValue[] invalidValues) { this( invalidValues, invalidValues[0].getBeanClass().getName() ); } public InvalidStateException(InvalidValue[] invalidValues, String className) { super( "validation failed for: " + className ); this.invalidValues = invalidValues; } public InvalidValue[] getInvalidValues() { return invalidValues; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/PastValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000245211131662636033403 0ustar twernertwerner//$Id: PastValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.util.Calendar; import java.util.Date; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; /** * Check that a given date is in the past, and apply the same restriction * at the DB level * * @author Gavin King */ public class PastValidator implements Validator, PropertyConstraint, Serializable { public void initialize(Past parameters) { } public boolean isValid(Object value) { if ( value == null ) return true; if ( value instanceof Date ) { Date date = (Date) value; return date.before( new Date() ); } else if ( value instanceof Calendar ) { Calendar cal = (Calendar) value; return cal.before( Calendar.getInstance() ); } else { return false; } } // ANSI SQL does not allow the use of current_date on check constraints :( // public void apply(Property property) { // Column col = (Column) property.getColumnIterator().next(); // col.setCheckConstraint( col.getName() + " < current_date" ); // } //TODO Keep it here for ABI compatibility. Should be removed whe moving to Bean Validation public void apply(Property property) { } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/PropertyConstraint.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000057711131662636033411 0ustar twernertwerner//$Id: PropertyConstraint.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import org.hibernate.mapping.Property; /** * Interface implemented by the validator * when a constraint may be represented in a * hibernate metadata property * * @author Gavin King */ public interface PropertyConstraint { public void apply(Property property); } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/MessageInterpolator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000117611052766205033404 0ustar twernertwerner//$Id: MessageInterpolator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; /** * Responsible for validator message interpolation (variable replacement etc) * this extension point is useful if the call has some contextual informations to * interpolate in validator messages * * @author Emmanuel Bernard */ public interface MessageInterpolator { /** * Interpolate a given validator message. * The implementation is free to delegate to the default interpolator or not. */ String interpolate(String message, Validator validator, MessageInterpolator defaultInterpolator); } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/MinValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000313311131662636033400 0ustar twernertwerner//$Id: MinValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; /** * Do check a min restriction on a numeric (whether and actual number or its string representation, * and apply expected contraints on hibernate metadata. * * @author Gavin King */ public class MinValidator implements Validator, PropertyConstraint, Serializable { private long min; public void initialize(Min parameters) { min = parameters.value(); } public boolean isValid(Object value) { if ( value == null ) return true; if ( value instanceof String ) { try { return new BigDecimal( (String) value ).compareTo( BigDecimal.valueOf(min) ) >= 0; } catch (NumberFormatException nfe) { return false; } } else if ( ( value instanceof Double ) || ( value instanceof Float ) ) { double dv = ( (Number) value ).doubleValue(); return dv >= min; } else if ( value instanceof BigInteger ) { return ( (BigInteger) value ).compareTo( BigInteger.valueOf( min ) ) >= 0; } else if ( value instanceof BigDecimal ) { return ( (BigDecimal) value ).compareTo( BigDecimal.valueOf( min ) ) >= 0; } else if ( value instanceof Number ) { long lv = ( (Number) value ).longValue(); return lv >= min; } else { return false; } } public void apply(Property property) { Column col = (Column) property.getColumnIterator().next(); col.setCheckConstraint( col.getName() + ">=" + min ); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/EANValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000171111052766205033377 0ustar twernertwerner//$Id: EANValidator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.util.List; import java.util.ArrayList; /** * Validate EAN13 and UPC-A * * @author Emmanuel Bernard */ public class EANValidator implements Validator { public void initialize(EAN parameters) { } public boolean isValid(Object value) { if (value == null) return true; if ( ! ( value instanceof String) ) return false; String creditCard = (String) value; char[] chars = creditCard.toCharArray(); List ints = new ArrayList(); for (char c : chars) { if ( Character.isDigit( c ) ) ints.add( c - '0' ); } int length = ints.size(); int sum = 0; boolean even = false; for ( int index = length - 1 ; index >= 0 ; index-- ) { int digit = ints.get(index); if (even) { digit *= 3; } sum+= digit; even = !even; } return sum % 10 == 0; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/FutureValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000152311131662636033401 0ustar twernertwerner//$Id: FutureValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.text.DateFormat; import java.text.ParseException; import java.util.Calendar; import java.util.Date; /** * Check that a given date is in the future, and apply the same restriction * at the DB level * * @author Emmanuel Bernard */ public class FutureValidator implements Validator, Serializable { public void initialize(Future parameters) { } public boolean isValid(Object value) { if ( value == null ) return true; if ( value instanceof Date ) { Date date = (Date) value; return date.after( new Date() ); } else if ( value instanceof Calendar ) { Calendar cal = (Calendar) value; return cal.after( Calendar.getInstance() ); } else { return false; } } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/AbstractLuhnValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000205011052766205033374 0ustar twernertwerner//$Id: AbstractLuhnValidator.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.util.List; import java.util.ArrayList; /** * Implement the Luhn algorithm (with Luhn key on the last digit) * @author Emmanuel Bernard */ public abstract class AbstractLuhnValidator { abstract int multiplicator(); public boolean isValid(Object value) { if (value == null) return true; if ( ! ( value instanceof String) ) return false; String creditCard = (String) value; char[] chars = creditCard.toCharArray(); List ints = new ArrayList(); for (char c : chars) { if ( Character.isDigit( c ) ) ints.add( c - '0' ); } int length = ints.size(); int sum = 0; boolean even = false; for ( int index = length - 1 ; index >= 0 ; index-- ) { int digit = ints.get(index); if (even) { digit *= multiplicator(); } if (digit > 9) { digit = digit / 10 + digit % 10; } sum+= digit; even = !even; } return sum % 10 == 0; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/SizeValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000163311131662636033403 0ustar twernertwerner//$Id: SizeValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.lang.reflect.Array; import java.util.Collection; import java.util.Map; /** * Check the size range according to the element * * @author Gavin King */ public class SizeValidator implements Validator, Serializable { private int max; private int min; public void initialize(Size parameters) { max = parameters.max(); min = parameters.min(); } public boolean isValid(Object value) { if ( value == null ) return true; int length; if ( value.getClass().isArray() ) { length = Array.getLength( value ); } else if ( value instanceof Collection ) { length = ( (Collection) value ).size(); } else if ( value instanceof Map ) { length = ( (Map) value ).size(); } else { return false; } return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/CreditCardNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000143411052766205033401 0ustar twernertwerner//$Id: CreditCardNumber.java 15133 2008-08-20 10:05:57Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import java.lang.annotation.Target; import java.lang.annotation.Retention; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; /** * The annotated element has to represent a valid * credit card number. This is the Luhn algorithm implementation * which aims to check for user mistake, not credit card validity! * * @author Emmanuel Bernard */ @Documented @ValidatorClass( CreditCardNumberValidator.class) @Target({ElementType.METHOD, ElementType.FIELD}) @Retention( RetentionPolicy.RUNTIME ) public @interface CreditCardNumber { String message() default "{validator.creditCard}"; } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/InvalidValue.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000261511131662636033404 0ustar twernertwerner//$Id: InvalidValue.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; /** * A single violation of a class level or method level constraint. * * @author Gavin King */ public class InvalidValue implements Serializable { private final String message; private final Object value; private final String propertyName; private final Class beanClass; private final Object bean; private Object rootBean; public Object getRootBean() { return rootBean; } public String getPropertyPath() { return propertyPath; } private String propertyPath; public InvalidValue(String message, Class beanClass, String propertyName, Object value, Object bean) { this.message = message; this.value = value; this.beanClass = beanClass; this.propertyName = propertyName; this.bean = bean; this.rootBean = bean; this.propertyPath = propertyName; } public void addParentBean(Object parentBean, String propertyName) { this.rootBean = parentBean; this.propertyPath = propertyName + "." + this.propertyPath; } public Class getBeanClass() { return beanClass; } public String getMessage() { return message; } public String getPropertyName() { return propertyName; } public Object getValue() { return value; } public Object getBean() { return bean; } public String toString() { return propertyName + ' ' + message; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/AssertFalseValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000112411131662636033376 0ustar twernertwerner//$Id: AssertFalseValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; /** * Check if a given object is false or not * * @author Gavin King * @author Hardy Ferentschik */ public class AssertFalseValidator implements Validator, Serializable { public boolean isValid(Object value) { if (value == null) return true; if (value instanceof Boolean) { return !(Boolean) value; } return false; } public void initialize(AssertFalse parameters) { } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/PersistentClassConstraint.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000076611131662636033411 0ustar twernertwerner//$Id: PersistentClassConstraint.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import org.hibernate.mapping.PersistentClass; /** * Interface implemented by the validator * when a constraint may be represented in the * hibernate metadata * * @author Gavin King */ public interface PersistentClassConstraint { /** * Apply the constraint in the hibernate metadata * * @param persistentClass */ public void apply(PersistentClass persistentClass); } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/PatternValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000137011131662636033401 0ustar twernertwerner//$Id: PatternValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import java.util.regex.Matcher; /** * check if a given element match the regular expression * * @author Gavin King */ public class PatternValidator implements Validator, Serializable { private java.util.regex.Pattern pattern; public void initialize(Pattern parameters) { pattern = java.util.regex.Pattern.compile( parameters.regex(), parameters.flags() ); } public boolean isValid(Object value) { if ( value == null ) return true; if ( !( value instanceof String ) ) return false; String string = (String) value; Matcher m = pattern.matcher( string ); return m.matches(); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/LengthValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000172511131662636033405 0ustar twernertwerner//$Id: LengthValidator.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.io.Serializable; import org.hibernate.mapping.Column; import org.hibernate.mapping.Property; /** * Do check a length restriction on a string, and apply expected contraints on hibernate metadata. * * @author Gavin King */ public class LengthValidator implements Validator, PropertyConstraint, Serializable { private int max; private int min; public void initialize(Length parameters) { max = parameters.max(); min = parameters.min(); } public boolean isValid(Object value) { if ( value == null ) return true; if ( !( value instanceof String ) ) return false; String string = (String) value; int length = string.length(); return length >= min && length <= max; } public void apply(Property property) { Column col = (Column) property.getColumnIterator().next(); if ( max < Integer.MAX_VALUE ) col.setLength( max ); } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validator/Email.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/java/org/hibernate/validato0000644000175000017500000000120511131662636033376 0ustar twernertwerner//$Id: Email.java 15765 2009-01-09 14:56:30Z hardy.ferentschik $ package org.hibernate.validator; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; /** * The string has to be a well-formed email address * * @author Emmanuel Bernard */ @Documented @ValidatorClass(EmailValidator.class) @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Email { String message() default "{validator.email}"; } libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/assembly/0000755000175000017500000000000011402110375030005 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/assembly/dist.xml0000644000175000017500000000437011173623006031503 0ustar twernertwerner dist tar.gz tar.bz2 zip false /dist/lib/runtime runtime false /dist/lib/test test target /dist *.jar target/site/apidocs /dist/docs/api target/docbook/publish/en-US /dist/docs/manual . true **/target/** libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/0000755000175000017500000000000011402110375027606 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/0000755000175000017500000000000011402110376030536 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/images/0000755000175000017500000000000011402110375032002 5ustar twernertwerner././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/images/hibernate_logo_a.pnglibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/images/hibern0000644000175000017500000007616611073343621033222 0ustar twernertwerner‰PNG  IHDR ‚÷VZðbKGDÿÿÿ œ§“ pHYs."."ªâݒ IDATxœìÝl•÷/ø' PlC&یðã@LàîpQ 6€Kš ³;¡“J{/™F³RÒÍýcºôjïœê4«ÉHý¡;#ÝöÎtV{«€ÒÝMK»Š#]Ù"Ꭱ0–:ªÍØÿ@ǍbÎ9Ô&Éþá;„€}Îó}Îy^¯?ªü€ó}'Á.çyŸÏç{ÇG}@ Ü:ÄD7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH Ýi¡ -tc€…n €ŽÐº1ÒB7@ZèÆH‹%¡ÝÿМtfxé¿äƒgÖmØœŒº6t/;~);>^¢ߺyS‰^è3¿oôôž‹-Ì< uu õ«£(ª©®n^wošZº¢\Ÿð×/¿ºÿá{ªîš …²tYÕtajëΧC¡ôôÅúè§¡®®¡nuœ'V€’6ŸTyÏæ†/æòù؎KÿÀ¡ÏþWšËç³c—>óųãã£cñýòŸ]Û¶lžýƒæŠ_ÿ7ݺeS€B+¥\Ÿ00<:EŠ”Ñ/æë¿6>Þc}ò[ÍÀðð•\|ßóK䟊u5ÕÕ õ«kª«gË3¿§ŠÁÕüd!7:ÅK–V­Œgmèå$æÿˆµõb;+å&Ç.„:: _†Sï\›)„NA‚üzö ,N+ïi\²tyèe鎏>ú(tkimkk?Œúî;ÿàášÐY˜ïŸÿwÏù7‹÷‡ÿêóžýû?ðÔþ8O¬H³ßœc;nۖÍß|ác;.ßûÁßt÷öÅvœ)±¢ŠºyݺÙ'×Íëîm𝫰N4”žŸsßýþC§H‘¿ýO:­òk#úÇά¹éÞæu÷67­Ó–ׅ³ƒç;C§˜o÷ÿÆ‘[óÄǞúnlg¥ÙÔû#§þk°ïÿK—Uíùÿ÷P§Ç£ëø'²ý¡S‡U ·ï~6æCý‹“§Ç fn,í²ã—fŸœ^ºüavªŠae.t"æè?ÛþÐ*êa+”¯+¹|wo_Ô;ç/nÛ²yö™õÖ-›kª«E*Ö»CÃQ]ÿŒÂlIïÛNeëíjÿ9&$J6Óðô™éÂÈàéµë ˜€RӍ¥]Ëk¯_ÿ㎓ïýÑï®þèÃé€y˜çòdÆoÈ Éº{û®?³^S_·uËŠæuëvíØî5P ³%ýõo;÷5­ÛºeÓÖ-›ÊhU&Ÿi"Ûïm )—<6ÀD¶ß× @eӍ¥ZOß¹·Ît]ÿÓékÑ;#nǜ‰žþ³í Û썀䛜JíøË¯Œ¯iݮ۷nÙdï"P:ï ¿;4<» äó;¶77­Ûµc»œ‹ÀÛ@Ò,›é™™|SÑhŠ{óÌSŸ*˜n,ÕZ^k›÷W:ߞlÞWWt5Hnhfº0tŸsÃO„܆ÙÖQ­©¯Ûµcû®ەd@IœuŠë­3]_{ýó;¶oݲÙkYó64›KÄ5E™ÁSM÷ï €Rэ¥×¡Ž7fŸ×Ìs¬;÷…mwş‡›<ßÙØŒÓmÌPŽFÇÆÛÚ·µŸ¯iÝÞGv{Z ”ÚlIÖÒúú®Û·nÞŽkÇöЉXˆÁó ÛVÞ³6tˆÕµ™«a/».›é֍T°;C Œ\Ÿpšãð ÿօLŸðÁʘóð™z»ZCGåÝ¡á—_=ø_zå'-ÃCÇ*ܕ\þÍ£Çÿã~üÿüȱ¡ã°ýgÛCG€že3ÝÁ*κ<™¹šŸ €Rэ¥Ô¡ŽÃWrùOý»?ýEœažÙþɱ ¡S‹5ûŽú[ßù‹ïýàozú΅ŽTŸÑ±ñ—_=øü¿þw-­m¹|"ž8s‹&²ý#ƒ§C§€XMd±PqVfàT蔊n,²ã—fïjþ4S…F~it,qŒŽ@%éîíûî÷øœüMvüRè,@廒˷µþƋ/iÈÊKÿÙök3n'-®æ'G“±PqV¢ÂP\º±4zåՖÏü1ož¹ãÎe1„áÖrCï (ŠîÞŸŸõÒ+?iѐ1žÞêx#tnÉÌtaè|gè“€uQ…Ü„>•J7–:=}çº{û>ó‡M_‹ÞŸà³i‰3tŸÓg òŒyôø ßz©¥µ-t ®äò_{ýÅïþ¥»ËÂàùNOçI‰lº±(yuÅ¢K[›õÿËÍD+J†Û53]p3Tª¶öÃU±ywhø[ßù +˂·€ÁÕüäåÉLèó%°® (tcéÒÒÚ6:6~ë?þÓÙ҅aa2§ŠÞ (‰ëªCÒbvÅâÉ3]¡ƒp3—'3ìSñ2§BGž™éÂÈàéÐ)(>ÝXŠäò…#ǎßÖO¹ôÁ/et,q|f*›2 NWrùÿø£kå΂}*^b·NdûCG øtc)ÒÒúú•\þvVÇ[ï•" ‹1‘íÏfzB§JèÝ¡áïýà‡=}çBÒ¢­ýð_ýèÇö+&–ûT¶©÷G ¹‰Ð)nl4Ó­™š<º±ŽŸøæÑÛ›5Uøhh|yÑó°HÞ@Å»’Ë÷û?Œ³ªˆaXŒBnâÂَÐ)€’{ùՃ±™ZÕÊ'–OIR©²I]š8+áñXÝX*œ<ÓÕÝÛ·àŸ>}-:s.WÄ<EfðÔÕüdè@ɵµ~å'-¡Siq%—ùՃê±dº<™zçhèPdÙLÏÌt¢º^žÌxPatc•/—/,þ³Æ?¿›Ž~£(y(–™éÂàùÎÐ)€8Œyôžz ˆÓ˯Ž\1™†ÎwzFO…™ëá³e¬Uš(º±ÊwšãðèØøâ_çÍÓ¿Xü‹P\ÖÍ@zšÇ€˜¹{,™fŠ ý=6+R9®Í\-‹ÚiÔZE€Ê¢«pÙñKGŽ/ÊK\ú ;US”—¢ˆŒŽ@zŒyôž-g@l®äòê±dÍtû”$£\®ò*ä&ŠÞ €¢ÑUžC‡¯äòÅzµ¿ûÙèw}®X¯FQLdûGO‡NÄÄ%@@œfë±ìø¥ÐA˜¯·«5t(Ž2šÇÊ –Á|·H7VÉzúΜyŽ8Cc³Š Ï|PÄ€(ú϶_›¹:“–Ö×=§bs%—ÿ«ý8t æ+ä&.œíëj~r"[—Í*—7n…n¬’µŒÖVô×ì|{òƒhyÑ_–Ř™. Ù¬©á95³w‡†[Z‹ÿî’EÊ žºšŸ ¥Œ†Æ¢(š™.d3=¡SPº±Šu䨉w‡†KñÊ'{‹¶€‘b<ßéM€‡çÔ@ÌÚÚŸ<Ó:sÌLú{ÚC§€E)»I¬² À§ÑUŠ\ŸÐÒúz‰^Œw(Wø`e‰^œóŠR¥­ýpOß¹Ð)€yå'-º&ÍhŠ{rìBè°@Sï\žÌ„Nq{F3Ýnµš º±Êtšãð•\ §»:NŸWºgaŒ)€ŽyåՖЀ¹’Ëû¶“@œ]­žÔSŠÊt«Lc0n¬eÇ/µµ.é—.˜ª)é,@ÿY£c"£cã‡:ޝH‘îÞ>›“А›pÿ4eªŒ.».3x*tŠ`Iè_Ëk¥ÚŠøq'ßû£ß]ýчÓ1œÅ-º<™zçhÓý{B€8Ü׎®Šºú¶~Jwo_‰Â„ršãðÞGv×TW…€EKkÛ®ÛC§`ŽÁóÍ;—W׆·arìB!7:ÅB\žÌ\ÍOúŠ(wº±JÓÓwî­X>Ç7}-ú‡á·üV Gq†Îw6®ß¹déòÐAà6¬©¯ÛûÈîæŠ{?ù·¶nÞTІ/æòù(ŠzzÏEQ40tq`xž€+©KäJ.šãð§ö‡b¶toš_ýñ꜡®®¡~õ'póºuóšé\Ÿ00<üñ¿’»”Ÿýち‹ÙññѱñÏìÄê“O|1tæèíjÝŸûÙÐ)à6”éÐØ¬ÌÀ© >:‹¢«4qî?Ñ3ùÀoÕßÙlž 3Ӆ¡ó~‹@yiš«‹ù1kóº_÷p󺷞Ÿs=œçÊ«*;rìøÞGv7ÔÝàÁ=p»|yÿb*ùšêªù?}ó ~XvüRv|Œ§÷\vl|`øbÙµe&Vh"۟Íô44n nUYßÚ5šéöà ÜéÆ*Ê¡Ž7b~[u¬;÷…mwÅy"ŸÉ> X°­›7]®=0|ñ䙮“gºþØúJ.äØq£c·åé/é†sŠ†ºÕ u«¯·Éå =œ}³Ý|¿áÌ2±šLýgÛW5lŽD„²ÍôÌLB§XžBnbêý‘•÷¬ dáÖ4n»ûžÆÐ)hfАˆõÖ·ÆæK—–ë'BªjV…ŽPrw×6n|p_èÁ¬,Û¯åàtc•#—/ê8ó¡2ù]¿œ¶ê®©˜ÏåæìӀÅk^woóº{<µ¶$;rìxb'Étc·«¹éޭ넚©®Úµcûì%^åÒÊ9vüÉ'7:–(…Ü„%"”‹²›•<µùwþ tŠ…[»þ¡ÐnrìBÌÝØšÆmµõâ<‘Û²di•ÿ@,À¡P4‡:y^sè§¿ˆÿPnn"Û?9v!t š³ Ù÷¿ýÒWŸyzM}]è87p%—?rìDè@üã7œ?û“çŸ}lÏîÐq>Օ\þd,]s[Ïw^ÍO†NŸáÚÌÕ²ŸllVÔ{)§«ÙñKmíqÍš*|44niCâôvµ†Ž¥Šºjï#ÿÛöÕgž^QS:Î|=œ}¡#ÅŽkÇöçŸràßy)± ّcÇCGàŒ$ù*£Uš™.d3=¡S°pº± ñÊ«-O?úöØw. €O*ä&.œí*ÐÞGþþ·_Ú¿ïñÐAæxëLWvüRè@‘5Ô­žmÈ>¿c{è,óœ;4<0|1t æ›Èö žn&3ë6ŒÒ©Œ’ µtc•à䙮žŸ:w5`n(3xêڌÿ.P|5ÕUžÚÿ§ßøZ¢Èì7ƒJÕP·úëÏ?û'Ï?›šï9‘ѱ€ê?Ûî ‰u5?yy2:EqŒfº}­”/ÝX%him !úù…ÜLŽ"t 昙.ôŸm*ÖÖ͛Ÿÿí sôôž (¡];¶'ê{NE'Ïtåò…Ð)˜ofº0tŸ3t ž± žiì㌎”/ÝXÙkim"Š¢èÓÙИ/3pjêý‘Ð) bÕTW}ýùgrPwoŸ‡ÔPÙf¿ç<ýå/…òkWry«É4xŸÓ;A’)3P! gUÌ~H€ҍ•·\Ÿœ-#—>øå¯ŒŽ%ŽÑ1(µçŸr !õXOÐ=Û@<ž|â‹_}æé„ìWóNšz€›¢˜.Of®æ'C§`!tcå­¥õõ+¹|èÿ€ã­÷îŒës¡S0ÇD¶?›é *Üs_9„EgÃCGâ°÷‘‡¿þü³¡SD‘m® 6‘í<:ÌQ‘+l =tce¬§ïܛG“246kªðÑùÌ¡S0Ÿ«˜ Ï=óô}MëÂfðÒcëæM_}æéÐ)¢Ñ±q­|by'HÒTØec³*ò tceìPû¡#ÜÀß÷L~xgUèÌQÈMžŠJ­Šºê¹g„Ýröîåf"{y8 wiåkfºà ɑÍôijPqÛÎ?Œá”ë ¹ ×û”#ÝX¹:rìDw"Ÿ9— ‚ù2ƒ§¬À€Rk^wïÞG_<ÖÓç!5€È“O|qۖÍa3 hålð|§§ö$ÄÄX §Ü]Ûxwmc }\fÐZE€ò£+K¹|áPÇáÐ)>ÕÏ/䊣ߝ‚9fŠ ƒ>0¥wà©ýkêëÈ%é2Z _þÙ°«*ù„ë{»5tˆ¢ž.¿qyumUͪκ®"ïQšxº±²tšãðèØxè7óæé_„ŽÀ|™S“cB§€Êwà©ýOwñ€MMuՁ§BnVŒ’˫ǒìòdf蝣¡Sv#ƒ§gŠ 1ŽòžÆ(ŠV5lŒá¬ëfŠ ÙLOœ'°xº±ò“¿täØñÐ)>ÃÈ¥²S5¡S0_ÿÙöРòíÚ±=àèX.on Rgï#›Xå&†Îw^›¹:©6‘c¡bE³ cž‹ŒŽ”!ÝXùiyíõ+åðÆ£ãä{wܹ,t æž<™<:TŸ'Ÿx<ÔÑÙ±K¡Ž2±ÊMÌL|P’€®Í\¥:ªªYµŒº6Š¢Uõ±ÎEQ4šéÖ@”ÝX™éé;÷֙®Ð)nÉôµè‘C§`Ÿþ³í~»¥¶kÇöPGw÷ö…:h׎íÛ¶luº‰Õä³cŸ€2ƒ§â9èú*ŕ÷¬]º¬*žC¯3:P^tceŠåµ¶ÐnCçۓDËC§`Ž™éÂÐùÎÐ) ÂÕTW}>\=€SÀVÞÄjY0:F(±•F_¥8{ñXœb«( ÝX99rìÄ»CáSܞ“œ>?˜8ƒç;¯æ'C§€ ·5ܐN»±á2{£šN—'3Cï ‚Ô¹šŸŒ<™‰ç¬¯RŒ;önìòdÆÃ€2¢+¹|¡¥õõÐ)n[ïP®ðÁÊÐ)˜¯¿Ç Ž¶nÙ:.5ÕUíÙäè+¹|._rt¹ˆœÛ ïŽcŸ˜ebšŠZº¬jå=k¯ÿéõýŠqŠçZ5ŠB7V6uŸ’+Ë¬Ž“ï…ŽÀ|£™n»æ €êV¯©¯ rŽ'ԐZ[7k华Ý\ãú¡#DQÍLúºZC§ ]b«‹>>4EQmý†xÎýžØŠ@O7V²ã—ÚÚ‡N±@—.8òK£c‰Óë”Xóº{ƒœë 5€–m®‰d„å†|P’8Mœ?RÈMÄsÖ'¿ÊÖ4n‹çèë ¹‰©÷Gb>€…э•‡W^m aQÞ<=rǝËB§`ŽBn®y(©†@sc@jÕTWÝ׎.t n¬±9£c‘J£lŒ;?ٍ­¬ûʱ(ÞdC7VzúÎu÷ö…N±(Ó×¢þ0t æ³kJªŠº:t uB]v80t1ȹedý†Žðk…Üą³¡S ™Á˜v VÕ¬Z^];ï/ÎÛ²Øþ‘X$ÝX(÷¡±Y'z&?ˆ–‡NÁ3Ӆ¡ó¡S@Åjn ³SH³†ºP7–åõØqZ^]›œÑ±Ìà©«ùÉÐ)špÙLÏÌtLw Þp}âÊ{Ö.]VO€ëfŠ ÙLȮ°º±€;ÔñÆèØxèÅq¬;:ó žïôŽ*Ló:Õ œêW‡ŽÀ§JÎèØÌt¡¿§=t *ÜÄXlg­ŒçÆëb¿r,Š÷€Ӎ%Z._8Ôq8tŠ¢¹ÉÿòW+B§`>»æ DBMoÔTÇýi 9ŽãÉTÈMD ÍtOŽ]‚Šumæjf Ÿí‚ŸŒllÖݟҙ•Tfà” ,’O7–h‡:_ÉUÔbŠŽ·Þ ù&²ýæý êLoqӎ'Ól7}Êæ·P|P’ÒÉfºc;kUÃÆ%Ko|‹Ç§uf¥ç?> £K®á‹mí•346kªðÑО[ǧÿ¬eP!VÔT‡Žv_“ѱ䪭ßêaý'rÎv„NAešÈÆ·Wð&_SË«kï® 0:6ªH<ÝXrµŒÖ:BI}{ìŽ;—…NÁÞ@ŰN š©Бçòµò€€’sëXä jJãj~2Îrèæã˜«êŽÑÙ~_Y §Kš“gºº{ûB§(‰ékÑ©sÖ.'NfÐ:l(²ìø¥øµN "H!WŠ5:Ù¬H ÄYŒUÕ¬Z^]{“Ðh‘©Ñ1€„Ӎ%TKkeÍúù…ÜLŽ"t 昙.جŕÿІúºøà¶$jtÌÔ]œ·m}æ~+ïY[U³*ž0—8ÿ¡Ü:ÝXµŽ¶,"Öþ IDATŽx’§7NgCG`ŸÌÀ©É± ¡S‹ÒŒîÞИofŠðñ?MÚèXÿÙv{D(–«ùÉ˓™ØŽ»•±° _n…ÜÄÔû#ñŸ À-ҍ%NvüґcÇC§(¹‘Kd§jB§`ŸÁó¡#@åÈåÜŸÓÜäŸ1H;»Uš›˜÷W5:VÈM y3H‘Ä9/µtYÕÊ{Ö~æ råXïü·K7–8‡:_ ñ%~÷³Ñ;ïú\èÌ1‘í<:Tˆá‹1Ÿž¢Šº¡nu̇I“Ë>û›ûÆnWÒFÇÏw^ÍO†NA%ˆóž­[ŒK¬¡qëÒe>4ŽV ¹tcÉÒÓwîÍ£•?46kªðÑùÌ¡S0ßàùNË4 (²±oÉn^gh £¹ÉB×ۖšÑ±(Šz»ZCG ìMœ?òÉ)ÉÒ¹õ° £c3Ó—ù$–n,Yµ¿:B¬þŸgòÃ;­ûHË4 XâÝØºeSÌ'°`I›Èö{ŽÏ"Å<)ÕОõd𝵉±þ çð™tc r䨉îÞŸÐ)b5}-:s.:óeOYŠ‹”Ëâÿ­n ˆ¢(;÷Ðjdnu¡’6:Ö÷v«=",Fœ7l­¹µ…гnqûbÑeNùšH&ÝXRäò…C‡C§àçrÓÑo„NÁ3ӅþžöÐ) ŒõÄ^Œ­©¯k^g§ÆŸÐ5Š¢šjA"i£c3Ó{DX°lŠgf:Ÿ¡ùÛúÚY²tùmuiEg_À­Ó%Å¡ŽÃAÞÀ$Á91:ófº'Ç.„Ne¬§ï\Ì'îÚ±=恟ÿ¡Û¶lŽÿÐòrmæS ƒ€Ž žïœzߛt"Îh鲪µëº­Ÿª‡Ս$’n,²ã—ÚÚÓ846ëÒå³S5¡S0_ÿY£c°p=œqwc*Qe %ÒåȨ́ý­€ŽEÞ ² ×f®ÆY-`GâÚõ-]à›ÕD¶ßœ €K„–×^!°Ž“ïÝqç²Ð)˜ãòdfdðtèP–zúÎÅŒ`M}ÝÖͺ1 ÌÜXC}]ü‡V’€ŽMdûœävÅŒ9pUýBåP·ŽH ÝXx=}çÞ:Ó:E`Ó×¢wF> ‚ùú϶»3àdì¿»ÛûÈî˜O’i`(D7V§[”dŽŽy3Èm‰³þYº¬ª¡që~âµÅË œ r.7¡ ¯åµ¶Ð¡óíÉ¢å¡S0‡{˜`²ã—ލn,˜ Ÿ)NŸ©ÂG#¿4:–8FÇàVôô{ëLẆ>¹ï‹1Ÿ$ÓÉØ¿ÿÌ27VDM<ä2€›:ßymæjè$ZÌÛ¿qM µŠcñ]ÉÀgҍóÊ«-¡#$ԛ§GîžsYèÌQÈMøŽ Ü\._ø«ý8æC?¿cûÖ͞JQâ²ÃÈec·ãV.r^²tyš…oŸffºÐ¶=t -ÎËÆªjV­Œgí"_$ÔÝ~™Sšf€äЍ…ÑÓw®;Ä%ÉeaúZôÆNÁ|>-7÷W?úqüë²|ùK1Ÿ$ÓÉ3]ï Çî®Ûã?ŽLr·òÃ8:–8eÍ>ŸfrìÂ-þÚ.Š¢Œ|-¯®œ»¶qñ¯³1ÏØpº±0 Ý܉žÉ™hEèÌ13]:ß:$TKk[üŸ|Ú¿ïqãÀ¬–Ö¶ çî}dws+ؒ¥Ë7>ž/tŠùŒŽñi⋊7òj@3æ]܄n,€CoŒŽ‡N‘toœÎ†ŽÀ|ƒç;§Þ çȱñß#»ŠŸîÉ'ùP ™Ž;ä=æ¶-›5ô¥°výCU5«B§˜ãòdƚ}n(ÎAš»k—W×å¥iÙÂLdûoeœ*1ЍÅ-—/êˆûÑI9¹ôÁ/et,q|Zæ9rìÄ˯ŒÿÜçž9PS¬¥[@¹|¡¥õõ G[šX: ³fŸO<=3]ˆíž"{-YºŒ(ëÀè@BèÆâÖÒúzüQ”©Ž·Þ ù&²ýÙLOè¡Š±ýûߺySüç ôÊ«CœÇԍ•NCãÖU C§˜cfºÐ×Õ:É2‘íóžâ{…úså@BèÆb50|ñÍ£ÇC§(S…†Æ—‡NÁ|FÇ`VKk[b쟊u¶)³uŒñ֙® G?¶g·éՒZÿÀ£¡#Ì7šéž»:Iqmæjœ#Pk·-YZÌgDk×?ŽtY€ob—'3®«HÝX¬Z^ s=rù:úöØw. ‚9 ¹‰ g;B§€rùÂ÷~ð7ñß1EъšjہYÃnìWҗZmý†P;ßn¢×èÿ(æù§RÜêÖ1£cI ‹ÏÉ3]Ýœ}¡S”™ékÑ©sš'Nfð”ËcH­žŸs/~÷/BýŸîÀS_j^wo£DÉå ßûÁCmS|lÏÕAŽN•[wë˜ÏJr]fðTlg-]VÕОµè/ëÊ1€4ӍÅ$—/ŽŽ[ˆŸ_ÈMG¿:sÌLÏw†NqËå õ£÷û?`ÿŸÇ÷>òp£D [ŒE†Æâ²Œº6›}V’(Š®æ'/Ofb;®D^µõªjV•â•o®›p•;@pº±˜ê8êJxóô/BG`ŸÌÀ)‹æH•Co|ãŗBÝëEÑc{vxjšÓä˜-ÆÞàó;¶‹Mӏyv3Ӆþ·P§]̓Oëw–è•CŽMŒõ9€ëtcqȎ_:rìxèeläÒÙ©šÐ)˜Ïè)q䨉oŒøç_{=àˆÆ}Më<õ¥P§ÉŒ‹¢hïžÝO/_م< _²tùÆ·Yq4Óí³’)—ˆo¡bUͪ•÷¬-ы76—ªu»¹lŠûڌ;DBҍÅáPÇá€OR*Ãßýlôλ>:sLdûGO‡N¥’¿ÔÒÚöÿüåW†]p_ÓºoŸðµšêª€€$Ÿø_ [Œ=¶g÷Ö͛H¡†Æ­«6†N1_oWkè3õþH!7Ûq%íZ^]{wmcé^ÿÓÌL²njI蕯§ïܛG -ÖTá£ó™6þfèÌ5xŸ³¡qے¥ËC€b:yŠë䙮€ë?N1Ì:rìDKkÈÖ(ŠVÔT›a bãƒûNe:Å…Üą³|"tˆ¹Ô)õhWCã¶8ïN»n"Û¿výCñŸ À,ÝXÉj#t„ ñ÷=“Í¿YWdä_A¡èÆJëȱÝœ}¡STˆékÑÉÞüÃ[,Mo‡ø€“gº†.†NQö²ã!žAJäò…áážÞsCø{¶Çöì>ðԗ<††”;yŠ«¥µ-ìf×YÛ¶lÞµc{èéÕôÀ£™ÁS3ӅÐAæèíjÝŸûÙÐ)ˆU6ÓçBÅÆõ%¿lÉÒåk·ÅYø]7šénºOüçéÆJ*—/ŽŽŸ:EEéÊm`mÕ]S¡ƒ0GOû֝O‡NA‚ŒŽ'áñ À' _Ìåó=œçrùüÀÐŰwöÜÜc{v?÷•¡ST¬“gºzzυNŸ†ººœ<:·m`øbËkm iîWÔT?÷ŒoJ!-YºŒéGƒL·ÜÄD¶?›éihÜ:ñ™ëóž†R^6vݪ†Aº±¬n ŠavÍo豲ī(tc%tšãpròTŒŽ“ïýÁÃ5¡S0ÇhŠ»qlgmý†ÐA(WÙññ#ÇN4Ô¯þäßj^·îV§²ã—æM[ ]ÌåóQåòùìØ¥ìx9Õö_}æiMFI¥í>àm[6ûU^²ã—uNÔ/ÔO}©¡îߥ‰SÓý{²™î #ÝDÿÙöU ÝB×f®ÆyÙØšž.8_»þ¡þ³íñÏe^žÌLœ?²òžµ1Ÿ А›HÚÚáRӍ…n¬T²ã—ÚÚ‡NQ.]þ0;UÓ°2:sôŸmè :åjtlüåW†N‘+jª¿ùÂך×Ý:FOß¹#G'áj±{lÏnõjBl|pßÏ~úJèsž…:U²™î8 €x†Æ®Ÿ•8Ûq×e3ݺ1€ tc¥ÒòšmŠ¥Òqòœ?úÝÕ}8:ÿäòdfdðôÚõ…elۖÍ_þYŒA eÇ/<ÓuòLWwœÞ׮Ί×äš­ßÐØŒ3Èü›p uzLdã[šžtYUœë:×êÆF3ݪe€ tc%ÑÓw.iô«$Ó×¢þpËo…ÎÁ\ýgÛâZwfEMõ“O<þä_ ˆUvüRO﹓gºr©Ø'­š©þúóφNÁÜóìέèíjÝŸ;Ì/••÷497…®Í\óR®8‡Æ¢(ª­ßPU³ª›ˆóÐ(Š ¹ —ö¡+‰–×ÚBGšp'z&ø­ú»¢«¡ƒðOfŠ 6iÀlÛ²ù¹gžÈRb¶îé=—ü{¿þü³Ÿ;%͒¥Ë›xŽ¿§=t9&²ý¡žï/]fÞ:&™ÁXǪ×ïŒóž(ŠÖ4n reÑÄX¿n ~º±â;ÔñF÷`Tžcݹ/l»+t æ°In˚úºOíßµc{è À¯ ]Œ¢hëæME{Áዹ|~`è×ÿ;0<|%—/֋—ÚWŸyºˆÿ*(¢Šû÷d3ݗ'3¡ƒÌÑ÷v몆V‰T°lŒCcU5«â¿…«±ygn,›éÞøà>_;1ӍY._8Ôq8tŠTžÉïúíµUwM…Â7i@YQSœ÷‘ÝžÚ:0ÇÁOÜ}_ÓºšêêþàæŠ{¯ÿqvl<—ÿ§w¹|ŸÜ?1ùÕgžÞûÈáSð©6>žïg?}%tŠ9¬©lWó“qÖ±kâ]š8kyuíݵñ·Î3ӅlŠÛ î1ӍÙ¡ŽÃeô1Àrwè§¿ø®‚9&²ý“cjë7„ 5ۊ=ùÄã5Õv@AžIŕØKÂO1V 33ÅŒ!¬¶~CcóÎÌ@¬;î>ÓàùΆÆmñûƒ˜±56ÇœPqVCã¶ ™Ù~Ý@Ìî  ¢dÇ/µµ‹ÏTᣑ_® ‚ùz»ZCG€$ZQSœßãßÿöKžÚ¯K1V"…ÜDq_pãƒûxÕVÿÙd]„F±ŒÆžPñîÚÆP—5ÄÉÙ¬ÑL÷Õüd£RK7VL¯ŒÚ:BêŒyzäŽ;—…NÁ…ÜÄÐ;GC§€Ù¶eóWŸyúGÿáßkŀ„SŒ•‘%K—7=ðhèóMdûGO‡NA‘Mœ?Rôr÷&BTQ-Yº<È:Ç(Þö€ÈNÅ":yŠ«‚Wj$ÖôµèÔ¹«ݯåM–¡óëwºH€”›]Ÿž÷‘Ý u«Cgø +jª¿þü³[7o „ÛÐtÿžlŠ;È ž›è?ÛÞОÍûÁJ’·¶iÔNÍZÕ°1HM•Ít7Ý¿'þsRK£P4-­m¡#€ÔÏ/äf"·Ž%ËÌtÁ& ˆ¢(—ÏŸ<Ó50|1t€›YS_÷ÍŸŠ+GÜ:Â|3Ӆ¡ó¡SPL™Áø.[ºX]»þ¡ ÛJ/OfŠÞ‰ÿ\€Ô27V-­m£cã¡S€×§³¿÷Puè̑8Õž~§K˜H³+¹ü›GÏþñŠšê­›757­Ûµc»12 QîkZ÷ÍŸfãk™ª­ßÐØŒ33_uq+Ïw64nó~°2d3=3Ӆ؎ ;4v=C¯©lŠÛW @l̍A._8rìxè©6réƒ_þÊèXâ€ë®äòoé:øÚë/|륿û—‡:ÞȎ_  Ú¿ïñoÿé¿QŒ•µî 2ærs}o·†Ž@qLŒõÇvÖÒeU [c;îÓžr tcEÐÒúú•\>tŠŽëxëœÐ˜o"۟Íô„N‰óîÐðõ’ìȱ¡ã)µŠŸîO¿ñµOí„ÅZ²tyӏ†N1ßåÉÌÐ;GC§`±®Í\s‚* CcQÕÖošªYÿ¹…Ü„§(±Ñ-ÖÀðÅë«rhªðÑО›~§ÿlûµ™«¡S@Bœ;4üò«Ÿÿ×ÿ®¥µÍ§ÏïØþí?ý·.«M÷ï¹»¶1tŠù†Îwz?Xî²ñN25®ßçq7jt,Î)=€”Ӎ-VËkm¡#ðkGßûðÎÄí‘H¹BnÂ%ÌpsWrù¶öÃ/|ë¥W~Ò¢!JmEMõŸ<ÿìןÖÅ ³ñÁ}¡#Ì73]°i¿ÜMdã«jªjV%ç¶­Ææ0-]6Ó­Qˆ‡nlQŽ;ÑÝÛ:¿6}-:s.wגυ™ÁSWó“¡S@xóèñŸõRKk[.ߍ÷@ªìß÷ø÷¿ýÒ®ÛC¡øjë7„zš™S“cB§`®æ'ãŒ+ÔšÖ -¯® 2‹93]ˆyV µ–„PÞúúý/Y 5üζǖU¯„9þkÇùœ§Ÿ:”‡¶öÃGŽßûÈn—EŽmËæçž9ÐP·:tJhãƒû²™î™éd}À¢ÿlûC_øãÐ)Xˆ8‹±(ÜšÖ§ihÜvy2ÿ¹ÙþµëŠÿ\€ŽÑ-Êæ~úV|W’ò™>ÿÏÿÙ=ëÿ›Ð)˜£íµÿ·¥ã­Í;ö4¯»7t(³[{zÏ=÷Ìÿ ,ҚúºOí7+–K–.ozàÑþžd­1Œ<™zçhÓý{JôúµõJôÊÄ9ÀtwmãòêÚØŽ»ëwùjÍtoÌïKÚ¿ €Êc§â¢ì}äám[6‡NÁ¯5Ô­þâî]¡S0G._8ôw'"7óÀí{whø[ßù‹–Vÿ ,ж-›ÿô_ûþ·ÿL1–M÷ï ²îæ†ÎwºB©ì\ÍOÆ95Õž>YCcQ-Yº<Ԛǘ'öÒI7¶XOîûbèüÚ>ùÄÒꕡS0G[Ëÿ•ûÕLEÝœ}'Ït…Žå§­ýð‹ßýK7·e¶ûæ ŒuóŠÐYˆÛÆ÷…Ž0ßÌt¡¯«5t nOf Ö=I IºlìºU ƒœëÊ1€èÆkëæMíÙ:ÑÖ͛v~þ¿ ‚9²ã—ì¹þ§>ö óîÐð‹ßý‹á‹¡ƒI·¢Šú±=»¿ó­«K³Úú I»·)Š¢ÑL÷ä˜+ÛËIœ£Kk·-Yº<¶ãnÝÚõ-]Vÿ¹—'3Wó“ñŸ *º±"xò‰ÇWÔT‡N‘vÿóïï ù^þ?ÿÿéèØžz ftlü{?øá‘c'BjۖÍ_}æéý‡ÿÜWÜSHŽñÁ}Aèß\¯Ñ±ò1õþH!7ÛqÉ›*[Ìs{)€+‚†ºÕ{1:Òïý÷4ÞÿÛ¡S0G÷Û?빘÷;ž¿$”»+¹ü˯Tw_Óº§¿ü¥|ç¥oŸðÇ{y8t’bÉÒåM<:Å|…Üą³¡SpK2ƒñ3K—U54nížÛåÊ1€Jµ$t€ qà©ý'ÏtŽ‡’F5ÕUÿbÿÿ:óœrðÿùä_Œ’Ëê8üÜWğ*Ã˯Œ¢ÈpH¹ÏïØŸuËæ­[65Ô­…„jºO6Ó}y2:È™ÁSÍ;—W׆ÂgˆóŸ«$EQT[¿¡ªfUœSt³ ¹‰É± µõb> =̍́§ö‡ŽRÿò÷Ÿø\õŠÐ)˜ãàßþ$ûþ•þ­7ïé;sš$/¿zКbH¡m[6ïß÷øŸ<ÿìßþ§¿þúóÏî}äaÅ7·ñÁ}¡#Ì73]èïi‚ϐÍôÌLb;®q}â®Ç›Çè@E27V4»vlß¶eswo_è éÒP·ú‹=:säò…#o¹É8Ôþ†‹Á`1ÚÚG>›•uÍM÷6ÔÕmݲÉb`êýžGžjë746ïLÚ­E£™îƱŠa’,Ρ±ªšU+ïYÛq ÓØŒsð|güçf3ݛçâ? %tcÅtàËû»¿£‹Õ¿ú—~—8ÿó+¹_ÍÜät÷ö9vÂ2(XŒ¶öà uuþÿ*Úúº†ººæŠ{£(ÚºeSMuµ2¬òÄ9ˆsÝÆ÷e3ÝAŽŸ‰Þ®Ö‡÷ ‚»6s5Îq¥P#Y·eyuíݵño(™.Œ ž^»þ¡˜ÏH ÝX15¯»÷±=»ß—ÏgÇ.åòùw‡†‹xP(-­¯77Ýë:T†¯?ÿ¬ßStK–.ozàÑ€­1,ä&.œíØðࡃpqEQÔØœô…г·¹œo"Û¯(ÝX‘xêK'Ït]ÉåCI…ÿåúýИïàÿýŸoå‡]ùÿÙ»ßàªïûNôDZ$ëœ.úw”"£?FRÒšÄÆ5ØŠÔÆÝÔò ÛÞkZ÷ÁvœfîŽ3u;³¹3nwгsÓÍv:œÙnsí¢Ýfí"¶3ø˜MŒöÚîØîØ2®ùã•g2ž6G"À&÷œqDˆqôûüÎ9¯×#ۑÎ÷aŒŽÞ¿Ïç[œÛ÷ì› *ÕÖMÖ¯ŒNQö^zå5[P=ò¹ÜR¬ÛýÑÒèÇ_föí™ÙÙ÷;³§Þ,ÇÍØŠsÿòOþô‰ÇםC7ëáÛßЩù\.:×qæììWŸúõßûí„ ÔqÏŠ™éÃ!?ÖÿÓ'_îèÙ\S[„«%94vgC[}®!±ãnE[ç}!ó™éܗÇýNvgC[ ¯Ø$ýtc%–ÏeG‡‡ö<œ7:HåûåÏ~Šå®Îè,ðâ Ï9}æ?xjÿ-7øY^EZ¢ŸqW›#G¯?‚ ܊BsS¡¹éGÿ{uâô›GŽŸ™=rôø™³³Ùn܅âÜî''ý<ýfuu¬òGisøè±ÉgŠ<=ÆRè^;òêٝbË—æ_ÿoûKu—R6ß8_ okmiŽNQáò¹ìƒÛ~>: çæ'ÿfßM}Ê€€4éj_5:Œm×ç'ŸüÄ¿ø“?üÒÃ;¶ßÝÑêú=¶ïÙoE§J`jÿCÏœ‚ Ôв:…›ëŠOŒ|þì?”䥲ùƒŒ w?…ržlì‡ Ý!ç&Œå zèÆ–Ä®Ñ*ÜCߑ[‚Šþæé™,ÞÔ§ŒøÊkGŽ™Œ  ÍM£Ã۞xüwþí—ÿø×w>œò’lÏÓ{Oœ~3:P“Ïøí̒è^;R[—º íN~÷ÛÑX Éеm ŒV®ìŒ7ä7Ñ»ç§/ΝOþ\€Š§[ýœkúz£ST¬BsÓ¶­[£S°ÀÌìۇ^zuŸ8ùôTÉÃ@ åsÙ-xâñßù“?üÒØÈв|JïmÚýädtšñ·þí—ÿ8pȅâÜWŸúõâÜ|T*UMm} ïb97óú['ÿ.:x’Œ—®Œ†ÆÞ•yúÄË!çT6ÝØR1:¶tŸðkŸ¶©3õÍ_ŒxiŸøÆ©ÓÖ@P ÍMãc_~"¥ ™?R¡Tò¹l컹3gg¿òÕ¯ R­ìŒ7j)ÜG8ùÝo_¹|1:™L²CcµuÙB[bǕJkP7rÏ@ÅӍ-•BsÓØÈPtŠ Ô߻ЫÇL^º9vüÐkGýéûž=àÁXÊE>—MmCæT(•þÞ5±ïæ=6ùŒý ”^ GÇæ‹çNÙ¬˜I0å84–ÉdZV‡\n7_ù²ë”?ûóÅs‰×Öy_bg•Rˆ–_ IDAT–Ñ1€Š¡ù\vb|{tŠŠòÏþé/-k*D§`ƒž˜¹Õ·1SûÌÌŸ]’<˜÷²Ç¿ø[W]Å©PB»vNÄ>ì8ùÌÞ§ß @EêèÙ\[—N±ÀåKó'ŽEK²zÉæ—¯X™Øq¥ÕÖÓê%¹ñ JèÆ–Ö–ÜÝѝ¢BäsÙ­ÊõÁ¢JUœ›ŸÜû·%y©ÝON–äu aýœkžxüw·nÚäFÇ T ÍM»>yñ؅âÜWŸúu»R)­šÚúnVœ>ñ²•q±’¬^¢F¯J¢>×pgC[òç^Ÿ4ÿÖÉ¿Kþ\€ Š;Æ¢#TˆßxhŒ.·<: L}s²øœË%y©ÃG9vŒ$/ Ëç²»>?ñðŽT, xé•×ü$JeýºÁØæûÌÙÙÝOî @EZÙyoc¡;:ÅÕ^ÿoû£#T¯·NþÝåKÉ}ó5zU*Q—¥›y=ä\€J¥ýœkî_7¢ìuµ¯ºïþŸ‹NÁ3³oï{þÕŸ Ñ1ÊÚèð¶/<úHøu³nƒÒšß»7õÅW^›|f*0)…£c^ôXLmmº¶D–$K—;Úês ‰·¯»rùbÈÑI7–„‰ÛÃJRî~ósFGàj{Ÿñ¥}Á3ggœí ¬­_7ø{¿ý[áßøzîùØPIò¹ìc>›ajÿ—^y-6fùŠ•=›£S\íäw¿œžýgó%S=®\Ÿ˜äecmå=4–Édês QõØôɗCΚHº±$š›¶lLËåhýºÁöžOD§`ÃÿêKÇO•üe=÷Œ5P”µ®öU±e2™ Å9?F‡êj_562›a÷S“'N¿› Óѳ¹¶.]ãVóÅs§ŸûíèU'ɛÆ2q K+j+i¿X•M7–Ñá¡ØEå+ŸË>²ã³Ñ)žÚî¿úKñ²Šs“Ïì]ŠW€Ä¬_7øë;ŽÍàO(­‰ñ±ŸÞÀŠs»Ÿœô%TS[ŸÂ͊Ó'_¶5.aIŽ"µ¶ ÔÔÖ'vÜÒ)Ž „TËŸ8w>ùs*’n,!ù\vt8øIÃ2µã?³Œ¹5: L=ý͙,.ыüÎó‰ ÜmÙø@ì”ÉÁïņ{,úBÁ7NÞýäžÀTž•÷F¿ü$—/ÍKÒŹóNìžÊËd25µõQÿ_ŠOX«Pº±älÙø@쓆åšÐÜŽmÃúè,Pœ›ß÷íÿº€GL>íÖ1Ê^øÚk¡Žò¹løÆÔ_yÍœ”V GÇN~÷Û&c“äMcµuÙB[bÇ-µÆ–˜^9É_2€ÊŠKÔèȶèeæ×Æ>S›[‚Š&¿QŒxiI8|ô˜çPîò¹ìc>àÄéӁ§CEZ¿n0üⱩý,M¥„–¯XÙÙ³9:ÅÕNKJ’CH34öŸB[6ߘü¹óÅsçÏþCòçTÝX¢ú{×lÝŽ!:EÙèï]3žþè,03ûöŸ—Ž$pÐä3S6APîºÚW~ïçAX £ÃCwwŽÇføÊW¿>3ûvl*IGÏæ›“>Âô‰—Ž%àœwޚ/žKìž¶Îû;+­AmŸÑ1€’Ѝ%mb|{ì’ú2òŸ{0:WûڟÿY29;»ïÙɜK'ðÆÙ Å9WxBÉåsÙ];ƒ7+^(Î}å«_÷$¥RS[ŸÂ͊G_{&:Bå›I°bÉæ—¯X™ØqɈš„Kò ‚郖Ïe·l4:v}¿ðó[îêŒNÁ/Ÿðü‘7g;îÐsÏ{€rWhn2:Š«}ÕÃ;¶ÇfxãÔéÉgöÆf ’¬ìŒ·±syÒOrnæu‹ã–Z’ãGQ#VKjùŠ•w6Ž%îåKóoü»äÏš0º±ãc±³§_>—ý•±_ŒNÁÕ&÷þ§$»Pœ3:@›9;u4T¶Ñám÷¯ŒÍpð;Ïzî…Ø T’ŽŽÝø­ci+öÊÂÌô‘D*vUÚBÅ÷EŽ›y=ä\€J¢‹11>!ÕzpøŽÜ²è,°ç¯žšyçB‡üÎón Üš›¢~†n§",];ߖÿµ'÷ømN©,_±²³gstŠÎÍŒ>3Äu×ÕéÜÙäʕ;Úês ‰—€À+Ç®\Ÿr4@Åš‰P¥Ö¯èë=|ôXt4*47mÛº5: çæœôjÈѓOO=ñøï„ ¥Òß×ûbÄzÃ3gg‹sóù\6ù£¡âåsÙÇ}䏟ü§±1ŸòÕ¯?ñøïúmNItôlž>ùòåK)ºÊîõÿ¶¿Ð֝¢]¹|1É;«Þ=?}ð™Ç;®JLŸ|¹ãžMÑ)ʘ¹±0á8§Öo>ôKÑžÚž¿Ü]Œx)äè7N¶+€r·>n÷ډӧ£Ž†Š×ß»fl$liêû̝ÝýäžØ TŒšÚúŽmVœ/žs¯ÒR˜™>œª”EH²ÝšHº±0…æŠð÷Q)Ôß»Šï“ŸŠNÁGŽ?ô÷‘‹ 'ŸÙ[œó];e,ŸËôõ†}â”}k°„&ÆÇîîhÍðâ+¯M>3›Š±²óÞŽÝÝuò»ß¶;®äÜVUÞ=?}qî|t €2Š‹4:<Ÿ¡>m~ëWŠŽÀÕŠþz26À…âÜŸgÄf€[ÔÕ±*äÜâÜ\ȹP=víœ[7µÿ€kz)•ŽŽúî·£ST”+—/ž1rTŠOŒ ŒéÆ"åsÙÑa£cúåÏ~æÎŠ–è,pðàÁ#ÿ}6:Efjÿ™Ù·£SÀâuµëÆ 2uµ¯JÃÛº¯|õëv-PËW¬ììٝbé“/+¡é“ • ¡ãžº±`£ÃÛZ[š£S€B>—ÝöO¢S°@qn>=[“O‹Wú–o欇K`ɍo»?îZÁ÷](Î}å«_Í@ÅèèÙ\[—Nñ¡Ë—捎•{ª*Æ|ñÜ{ \éÆâíÚ9!zpž.·<: LýÍÓ3ÿXŒNñ_yÍ¢ÊWÔܐŒ];êñðÑc.£$jjëÓ¶Yñ£GÇZV'Ь]œ;ÿîùé蔌)@€EӍÅëï]þŒažBsÓ¶­[£S°ÀÌìۇ^z5:Å»Ÿ Ÿù nÅ@_oò‡ž8}:ùC¡ åsÙ4<õèâ1Jee眍…îè2:V*nšª0ŠM7– ;¶GGö…_‹ÉUö|ã/Š/E§XàÌÙÙ}Ï~+:”“ E÷ABú{׌žxŒÊQ^£cÜ 7TU˜Ë—ægŠD§(Kº±T(47¥áMT”õë»z£æ#9vü¥ã§¢S\ßgx«@:MŒÝÝÑ›ÁÅc”Êò+;{6G§øÑ±[÷Þ;oÍÏE§ ÄŒŽ,Žn,-F‡‡–åsÑ)bìúå£#pµ=O=áÚ.çö={ :\Ûc>þÎÎÅc”JGÏæÚºltŠüî·/͏NQƔ(éÌôa#•‹ K‹|.;1^›ÿÙ?ÝŸ¬©‚"óƩӟmæÖÕç:{6G§øÑ±Ežrùâô £E•̯/ÀÍҍ¥ÎèðPøÕÍÉøÍÏ=«}íÏÿ,::svÖû|ž®j[Ù éÑÕŸjld(:…‹Ç(ŽžÍÙ|ctйuìf¹ªâñK p“tc©ShnÚ²±òGǶl| œçÑ)Xàðß¿zä͙è7áÐsÏçlK lÌÌÎ&h>W]A:MŒ ôõF§pñ%PS[ßœv$:ҌŽÝ¬s3*Vžùâ¹÷Þy+:@9э¥ÑèðPønú%•Ïeٝ‚«íÞó×Ñn΅âÜä3{£SÀ:s6 bíÚ9ŸÄÅc”D¡­?Uwzœ~dt„²qq¢j0}ÒZE€› K£|.;:¿|cé<ôàðòæÖè,0õô7gÞ¹âŠüÎóGŽN×wâô›!çvu¬ 9x_¡¹i×ç'¢SdÞ8uz÷S“Ñ)({}ƒãÑ>tfúðù³ÿ¢<(ƪ„Í™7E7–R[6>†åK¡ÐÜŽùçî‹NÁŹù}ßþ¯Ñ)ißþoEG€ë+ÎÍEGb¬_7žuSüÚüƒßyþÐs/D§ ŒÕç:{6G§øÐÞ:–ªëÐÒFeR%._šŸ™> lèÆÒkbÇXt„%ñ›ýRmnyt ˜šüFñâ¥è‹tøè1oòH¿#Gc ͕Œ©ÊÅÄøö»;Ú£Sd&ŸÙ5ÃJÅèèٜžêÜÌë?«­ÍƆI­‹sçß=?‚„èAnœn,œºÚW¥áéÂÒêï]Ó÷ÉOE§`§ßÜ÷Ry?XŽïÙŹùèðQNœŠùyt¡¥)ä\àGåsÙ];ã7+^(Îí~rÒwÎ܊šÚúîµ#Ñ)>ô££c\Óô wPU‘3Ӈ¯\Ÿ <èÆRmb|{øœÍ¥õŸ{0:WÛóáV9;»ïÙÑ)ࣜ8}:äÜþÞ5!çWéj_õðŽíÑ)2oœ:=ùÌÞè”·B[c¡;:Å~ttŒkrÙXµ1:pƒtc©–Ïe·l¬œÑ±_øù-wuF§`_xþț3Ñ)JàÐsÏÏÌŸ®íÄé7/îkm±PRdtx[n•vñ·®op<:‡ŒŽ}„÷ÞykŸx.:‰š>iRà†èÆÒnb|¬2~š‘Ïeeì£SpµÉœÿ):Bi\(ÎM>íXRê¥W^ 9·«}UȹÀOòØ£€a5ˆ‹ÇžEõ¹†ÎžÍÑ)>`tì#šIªÐ»ç§/͏NPtce ‹éoÝCߑ[‚öüÕS3ï\ˆNQ2/ŸòڑcÇ£SÀ5Duc…ŠxÄ *I>—Ýõùø÷w.ãÖuôlÎæ£S|àäw¿ž5©bœ^urÉÀÐ•þÞ5iØŒq+ ÍMÛ¶nNÁ3³ozéÕè%6ùôTtžÚ‰Óož9;rtŸËÆ uÖ¯ŠNáâ1nUMm}÷ڑè87óú¹™×£S€ÎÌô‘Ë—TàÕÈ%s7B7VÊ}tì ÿÛÃÑžÚÔ_ï)^Œ¢ÄÞ8uÚÝ €Í¡çž:º¿W7i4:—ݵs" }íÉ=.ãVô ŽGGø€©«\¹|ÑðP5Ó\—n¬lŒ¥áœÓ"<ö«¿«MýÇÿa©\(Îí{ö@t ø@àŸJ*Bšuµ¯NÅã_ùê×=[Æ¢Õç:{6G§à U9ÿ\WMtnT>—Úót™m„ÿåÏ~fYS!: RhëOþh€ran¬œŒo+¯Ý8ù\vtÛ?‰NÁŹùj«ÚýädtÈL>öTÓ²|®«}UÔéÀ Úµóá4lyñ•×ö=û­è”«šÚúîµ#Ñ)XàâÜùs3¯'ybkÛ@’Ç•‘À;ùŒŽ|4ÝX™™Ø1á&<ôàp]nyt ˜úæäÌ?£S,¹ÃG9V™ªP.Ž;nh øhù\6%[{žÞëâ1­ÐÖXðã’T*èÆ~‚À¯Ì™éÃW._Œ: ýtceŠ¿wÍýeò“Ž®öUÛ¶nNÁ3³oï{þÕè 1:@ âÜ|ìŸDýœ.ƒòÐß»flÄÅc”œŸÁñè|(ၡֶšÚú$O,#5µõCuFÇ>‚n¬üLìØá†üúçÊiÄ­JìùÆ_DGHΙ³³6Ãeò™œgÎÎFŸ,Ÿ37edb|, Ëóß¿x,:åª>×ÐÙ³9:™L&óÞ;oœ{~:ÉM ~ŽÀѱé“/G ~º±òShnJÉs…aýºÁ®žÞè,päØñ—ŽŸŠN‘š}Ïðè+É;ôÜ Û3™Ì–Oá±Gqñ宣gs6ߝ‚€G…jë²*~ŽB[m]6äèwÏO_œ;r4@úéÆÊÒèðPÞ8}„Gv|6:WÛóÔSÑ’v¡8·ïÙÑ)š.GŽÿZôà…n ÊN¡¹ib< Bö<œ×Åœ,NMm}÷ڑè$}ÙXÁBÅ{ëXÔÑ)§+Kù\6%oœ®éŸýÓí˛[£S°ÀÁƒOÌTã³BSûžT€Äœ8ýæWŸúõØ }œ…æŠØ À"lÙø@Jî–vñ‹Vhë·^/Öù³ÿ0_<—䉍-~ů/ð«4}ÂZE€kӍ•«-èKãÒÂBsÓ¶ ë£S°@qn~rïßF§3ùôTtªÂ‰ÓoþË?ùÓ Å¹Ønƒòµkçí-ÍÑ)2Šsá5?å«op<:BUKxHš¶.[hëOòÄ2žVqŸxîœwÞ 9 åtceltd[t„kø_G‡ksË£S°ÀÔä7Šß»"Ìá£Ç^zåµèTž”c­-Í[6>›XŽ|.»kçDtŠL&“9|ôØä3ž0c1ês =›£ST¯„/sÓØ üZ%üo@¹Ð•±þÞ5[7¥ë2‰þÞ5÷ÝÿsÑ)X`föí}/‰NÌ{–Ô¡ç^HC1–ÉdF‡‡¢#·€¿wÍØH*~#Oí?àâ1§£gs6ߝ¢œuòï._Jt!j«n솵uÞuôôIk®A7VÞF‡‡–åsÑ)>Žó³[¢#pµ¯ýùŸEGˆwæì¬z €¥Pœ›ßýÔäמܓ†b¬µ¥ÙBEšãcwwŽG§Èd\<ÆbÕÔÖw¯‰NQÎÍŒžäqÙ|cCËê$O,kËW¬ŒêŒ/_šŸ™®ögŠ~œn¬Œš›¶lLËèØ/üüÆöžOD§`Ãÿê‘7g¢S€Â¡çžŸ™};:åý=Š¿ó|tŒås1WY¥õØ£€á!H±h…¶þÆBwtŠêråòń/34v³¿bçÎ&ڛ”ÝXÙJÃuÍù\ö—¶Y)ž:»÷üut„ŽžPœÛ÷ìèTˆâÜüä3S¿ÿ‡üÆ©ÓÑY>àŠ1š$…æŠ]Ÿwñå­op<:BuIþN)—Ý¬À¯Øô‰—¯\Ÿu:@:éÆÊ^>—‹N‘yèÁáåÍ­Ñ)X`êéoÎŒs!:EŠüÎó®LàÖzî…/þÁ—Šö§ë‘‹4|C”Ðúuƒ)¹^zjÿ—^y-:å§>×ÐÙã Úä$|§T6ßž|ÅÊ$O¬k3í)@ÊéÆ*Áúuƒ}œ ÍMÛ¶n À+ÎÍïûÏ/D§H}û¿€2v蹟øÿgJnûQ}œnƒÊ31Ÿ= ;B2™Ìî§&í'gV¯lªÊŹóNòD §­ëŸš£^¹ ~º± 1±#òIáß|è—Oçšöü»¯¿w9:Eê>zìÐs*CnÎûßoÅ̝Žs ±ß K$ŸË>öè#Ñ)2q lVLFòµG`ÇSÖ"¯›yýâÜùšÓRH7V!ºÚWE-Üèï]Ó÷ÉO…ÍOrâô›‡þ¿ïF§H©}Ï(ÎÍG§  çæ=÷ÂWŸúõßøâïNí?ÎV,“ÉŒ uµ¯ŠN,‰®öUc#CÑ)2™LæS§]<Æ"4ެ6`”€é‰.TŒ³¡­>א䉣>×pgC[ÔéFÇ~TMtJfb|ûK¯Œ–ü†ŸßøÜƒ ŸÈuíùþ2:Bz9;»ïÙ.eà'™™}ûÈÑã'NŸùÎêfÝÝÑîµE8qêÍè‘ú{×DGà&LŒ8õæá£Ç¢ƒdŠöèj_eƒ+7«»äÜÙ×/_ò„âRyæ‹ç’<± ïŒ…¶„`þÐô‰—;îÙr4,©+—çϟý‡èa–¯h«©­NQ–tc•#ŸËŽíyzo’‡þÂÏol¹«3ɹ®_xþÈé3Ñ)Rmjÿ-7š›¢ƒð™Ùٗ^y-ŸÏEýÈþȱã3gß>qúô‘£ÇS;vM»vNDG(K Ϝ6õÿ›èܜÇ}ä‹ð¥4Žõ»Ÿšìêh÷47¥>×ÐÖyßÉï~;:HŚI|È,à­hmxýÈþ£ç‹çÞ{ç­å+V†œKçÝóÓ¯þ—ÝÑ)Âüìÿ²«¡eut∫(£ÃÛ=÷|b?ÐÉ粿2ö‹ÉœÅ *ÎÍOþÍŸèe`òéœ)¹Œ€L&sæìì¿þŸ7Ù,ËçºÚÛ3™LWÇ{ûû>(Ìò¹Ü-.œ™}{fv6“Éœ8õfqnîÄ©7gfgË« ûQïØn›"Tƒ|.»ëóÿ:7~œñ؏ÿNtÊÌêµÃgŠ'<ÛT=^”g¡â-ªÏ5޶ D­7œ™>¬xŸn¬ÒìÚ9ñG_þÓdÎzèÁá;r˒9‹4õ7OÏüc1:Exñ•×¶;n¡@ ](Μ¿:ì‡ ÄŠöøI<Ð×{Ý,ÎÍœqêt©â¥ÇýëG‡·E§²~ÝàØÈÐGü÷01ï_HÔèðБ£ÇÓPöOí?PhnÞ²ñè ”“†–Ձ³2ìÜÙ×>Ñec·®Ð6pôµgBŽŸ|i~fúH¡­?ät€TùXtJ/™k'Ÿðk.·H©oþûâÅKÑ)ÊÆ§Nzî…èpӖås=úH>—$*ŸËŠçŠÁÉgöž8ýft ÊLwÿHm?ŒJéÊå‹ _6ÖÚ6PS[Ÿä‰©Š¶>ðζäûT€tҍU BsÓØÈВÑ߻Ыçú+ŒHґcÇœv4:E™™|foqn>:ܜ]ŸŸpÍT§®öUïØ"“Éd.çv?9é{inJ}®Á:ŸÒš™>|ùR¢¿  ÝIWÁ¿’Ó'^ŸrùbÔéé¡«L£ÃCËò¹¥{ýÇ~õW–îÅYœ©ÿø¢#”Ÿ Ź}ÏÆßÙ7î×w>Œ~Ý`t Ìèð¶¹j1oœ:=ùÌÞè”™Õk‡³ùÆè•ã܌…ŠåªÐ68F™ðž!@:éÆ*S>—_ªÇ ù³ŸYÖTX¢gq—}ìÑG¢S|ÀÅcܬ†–Ձ7-U’é“/'|¢¡±Òjl [«xnæõ‹sç£NH ÝX%›Ø1Vò×üß?÷Ku¹å%YnÅÔ7'‹ß»¢Œ>zìȱãÑ)à£lÝŽa×ç'¢SiÑß»f©/™ŸA.cºûG·ÉUŒ„×âÕÖe mýIžXñ mý¿ŒŽèÆ*YïšûKzEWûª°Æ']ffßÞ÷ü«Ñ)ʞÑ1ÒìáÛcÀU&ÆÇ–bSÈ"žxŒ›UŸkhëŒ/:Ey»8wþÝóÓIžhhl)~U§O$=w6º± 7±£”·Žýæç,á«Q{ŸñÑ*Á™³³ûžýVt ž†_ßù°UŠÀ5íÚ9áâ1ÊÔêµÃÙ|ctŠ2–|±ž°‚î/ž{¢NHÝX…+47•jÕÆúuƒí=Ÿ(ÉKQ*GŽéø©èbß³¬‚ U–ås_xô‘-Mí×ÖÕŸjt8›3™ÌמÜãâ1nJßàxt„2–ðB< —HCËêÀ’8ᵜi£«|£ÃC­-Í·ø"ù\ö‘Ÿ-IJhÏSOEGšŠsVÁËò¹ßûíßZ_ÒýØ@åuX³°òIDATÞVÚEú·â+_ýº§Ížq -«‡fÊÚ{ïŒ5_<—ä‰v`.ÀßÓ'­Uªšn¬òåsÙ[–pÇ/~fyskIòP*SOóÄÌùèåàwž÷¬+i0Ð×ûå'ŸÔÕŸ*:Pví|8%›ϜÝýäžè”“îþ‘ÚºltŠò“üžËƖNà×öò¥ù™é#Q§„ӍU…-èë]ô§š›¶mX_Â<ܺâÜüŸÿl¡éM>=€j762ô{¿ýÏó9?+nH>—}ìÑG¢S|àÅW^s/7®>×` i÷Éæ—¯X™ä‰UeùŠ•kϝ}=êh€pº±j1:²ø+Ümì3µ¹å% 훚üFñ{—£ST ÃGœôÊkÑ)šR­-͏ñ·&ÆÇ¢ƒeŠ¿wM©î™Ÿu{žÞk7nõÚáÀb ÍL¹|)Ñå¥V_.µÈµŠ'^ŸrùbÔé±tcÕ¢¿wÍÖM÷‰ƒëݟ.3³oï{ÉØûR™|fÊ5 $oldè‰Ç·¿wMt ,MŒÝÝѝâ.ãŠô ŽGG('ÉúXšžÔÚº"§'“_Ñ º±*21Ÿ}kèíÁ-K†[ñµ?ÿ³è•ìÌÙÙ}ψN@ùម=ŠÀ­xìÑG\×pgC[Ôégtc@µÒU‘|.»eã͍ŽýÂÏol»çK”‡Åyñ…珌9¢Âzîù™Ù·£SPù–åsc#C_~â_n]¡¹ib|{tŠžxŒ›ÒÝ?R[ç‘ëK~Ä'v€©z睛yýâÜùšÓéÆªËÄøXkKó ~p>—ý•±_\Ò<,ÂäÞÿ¡ò](Î`©mÝŽá‰Ç×íb@ mÙøÀýë£S|`ÏÓ{;‚òPŸkhëÔÁ\ß¹™€*éKFì×ÙèPtcUçÆþòЃÃwä–-in֞¿zjæ Ñ)ªÂÁï<ï<Käþuƒò‡_Úõù‰BsSt ÒìÚùð?¹Ô\<ƍ[œv8›oŒN‘jçÎ'ÜaÜÙÐVŸkHòĪ»Vѕc@uҍUõëúz¯ûa…æŠm[·&‡Wœ›?ôâ+Ñ)ªÈŸý–ÀPb}œñ·{ô­°Dò¹ìc>âŠs_ùê×£SP6úÇ£#€ZòÃ=‹þªPàèä»ç§ß{ç­šÓ¢èƪÑĎ돎ýæC¿”@nʞ¿Ü]üÞåèUäðÑc‡ž{!:bëŠ ò‡_úœßþç®–ZWûª±‘¡è8|ôØä3SÑ)( -«mðûÉ÷øåHRlit šBº±jtÝwJýœkú>ù©Äòp#Nœ~óÐß[ñ—ŽÉgöZÀ­hmi²AHØÄøØì IÆÔþ֕sƒºûGjë²Ñ)ÒèâÜùwÏO'ybkۀ…ŠIª©­,#]9T!ÝX•Z–Ïý€ÿõ7>÷`’až{þÒ*’Šsûž=€²tÿºÁ/<úȗŸøãcZ1 y»vN|ěŸ„¹xŒTŸkÜ,—fÓ'^NøÄÆBwÂ'ø5Ÿ/ž›™>u:@ÝX•Êç²£Ã×ûåÏ~Šå®Îdãp~ëÈŸNQ¥Šö˜™};:eãîŽö‡wlÿ“?üÒc>²~Ý`t zš›v}~":Å\<ƍ[œv8›oŒN‘:.«±_ósg_< yº±ê5:Œ­µ¥ùª˜ÏeÜöó!yøIŠsóûžýVtŠª6ùôÞè€Ý@_ïû•؏ÿÎèð6ƒb@¬_7žuӆèpñ7®op<:BºŒ÷Î[óÅsIžØÚ6PS[Ÿä‰d¢×*ÎLŸrùbÔéÉ«‰@€];'þèËú£ÿ䡇ïÈ-‹ÊÃ5MýÍÓ3ÿXŒNQÕ^|åµ-ǎ÷÷®‰@ºŽ¶4¯_7ØÕŸª¿¯7Ÿs9 Fãۏ=~æl*¶PLí?ÐÕŸÊL-×Õвº­ëŸä·ŠÖôI «E¡m êê¯Ë—ægНìŒ7ät€äéÆªZŸÞÃGœÿ·…æŠm[·ÆF"“ÉdŸÿ?2»ýý¿œ™}ûÐK¯ÆÆ!“ÉL>=õÄ㿝€xwwŽ÷÷­)47÷÷­1€_>—}ìÑG~ÿÿ8:Èv?5ÙÕÑ\W÷ڑ™é×/¹Š.“Édf’-Kjë² ’(…¶þÚºlÔ¿ùçf^÷KTÝXµÛµsâ·ÿKïÿõ~--Ëè«ÝÇnÿÁ¥ùÛ겙Lfê›ÿŸxñRt 2oœ:œïÙoo‹@Òúz -M…ææ®ŽU]ííæÃ€²ÓÕŸêáÛ÷€cOøûyìŒëª©­ïèÙüú‘ýÑAâÍLIž)qÓX¬BÛ@ÔÐä™éÃÝs#õ¹†ÓŠ«v…抱‘¡©ýú{×tõôFÇáºüœL]öȱã‡^;…ì{öÀ–üH ‚ÝÝўÏåº:Ve2™þŸ5ù\®«}Ut(€Þväèñ® ‰õƩӓÏLMŒE!í:îÙ43}øÝóÓÑA‚%<4–Éd[,TŒÔØÒžPôÌôáŽ{6E€Û~ðƒDg Xqnþ‹ð¥ÿë÷ÿeM…è,|èóïþÁý«3磃𡱑!ïá~hföí™ÙºÀæÈÑã7òa'Nœ¹š³×ŒGg ïÚýäsÙBKóûÝÕŸ*ŸÏe2—J@õ07F&ŸË~ñó^<ûÝK³ßÎ‡^Ÿ>{ûõÑ)Xàõ'£#€H¡¹é/ŒÑ<é¡#“ÉdúÖm|áÿýWóÅsÑAøÐí5µ?žíöè,ÐÝÕ€[ò±è€EßàxtøW.÷Ž£Sð¡Ö–æÑá¡èÜÝhhYÝXpÛjº¬lº}°÷ãÑ)øÀÄøX>—NÀ-эñ!£c)tOë…\Ö­cñúzׯŒNÀ­Òñ¡ú\CgÏæè,°<{[_ûÑ)ÈL싎@ èÆX £gsm­qéò©®ï7®X¢ªmÝŽ¡«}Ut J@7Æ5µõÝkG¢SpµOwß¡z-Ëç&Æ·G§ 4tc\meçœw6ŽE§`UÍß_Ýޝ¢JmÙž!Ÿ3L P!tc\ƒÑ±žk.:B5jmižwÓ@åЍq -«[Û¢S°@ӝû™žæèUg×Ήè”’nŒkëî©­³G.]>Ùþœ\öŽèUd ¯·¿wMt JI7ƵÕçÚ:ï‹NÁu5™Ouç¢STCc•G7ÆOÔѳ9›oŒNÁ}mW*¢*Œ š›¢SPbº1~¢šÚúΞÍÑ)žÚ†µuÑ*ß²|ntx(:¥§㣬쌷±Ð‚ w^¹û.ó|Kktx(Ÿsß@ҍqFÇRèÓ«/EGšdwwŽo‹NÀ’Ѝq -«Ûºî‹NÁ˳·­ïoNQ±&vŒEG`©èÆžŸîµ#µuöË¥KÏÇçrÙ;¢ST û× ö÷®‰NÀRэq}5µõmFÇÒ¥®&³ŸoYtŠ 4±c{t–nŒ²zíp6ߝ‚î.\j+¬ˆNQQÆF† ÍMÑ)XBº1nT÷ڑè\íg»o‹ŽP9Z[šG‡‡¢S°ŽtcÜšB[c¡;: îŒÒ×՝¢BŒåsîÕšpº1n‚ѱh¿˜ËÖG§({}œ[6>€%§ã&,_±²³gst XžœmmW>:EÙÙ€$èÆž9=›këìK—Þ•—š–G§(c[7mèï]€$èÆž95µõFÇRŠ®&Óß~[tŠrµ,ŸŠN@BtcÜŽŽ{6eóÑ)X û§°ºœ%:EYÚ²qC¡¹): э±}ƒãÑžZOk1:Bùimiž‹N@rtc,FCËêÖ¶è,°²éöŸéiŽNQfcÕF7Æ"u÷DGàjŸlÿ^.[¢l ôõ®_7€DéÆX€ú\CgÏæè,PW“ék¿#:E٘Øah  êèÆXŒŽžÍµuÙè,ð©®ï7®X¢ lÝŽ¡«}Ut ’Šcñjjë»×Ú¬˜:ŸîŸ=:BÚ-Ëç&Æ·G§ €nŒ[²²óÞ;Ú¢S°Àªæï¯no‰N‘j£ÃCùœ‘G€j€ãVK¡»æ¢#€WkKóèð¶èÄЍq«ZV·uݝ‚šîüØúþÖè)µkçDtÂèÆ(ÎžÍµu6Ô¥KÏÇçrÙ;¢S€Î@_oïšè„эQõ¹†¶N£céRW“ùTw.:Eêšrº1J££gs6ߝ‚úÚ®4þT>:EŠŒ š›¢SI7FiÔÔÖwölŽNÁÕ6¬­‹ŽËò¹Ñá¡èӍQ2+;ïm,tG§`ÂW>±º5:E*LŒoÏç܊Pítc”R÷ڑè\­ÿ®bt„xwwŽoÙø@t âéÆ(¥å+V¶uݝ‚–go[ß_í£c;Æ¢# º1J¬{íHmÍuéÒóñ¹\öŽèaî_7Øß»&:© £ÄjjëÛ:Ž¥K]Mf}ß²è1–ås;¶G§ -tc”ÞêµÃÙ|ct ž»p©­°":E€-7š›¢Sº1–Dßàxt®öɎKÑ’ÖÚÒ<:<€э±$ZV7º£S°ÀÊŠÛ{?"Q£ÃCùœÛïønŒ¥bt,…îiœËÖG§HÈ@_D§ ]tc,•ú\CgÏæè,°<{ÛÚ®|tŠ„ŒŽl‹Ž@êèÆXB=›këlŽK—Þ•—š–G§Xr[7mèï]€Ôэ±„jjë;ŒŽ¥L]MŠ¿ý¶èKkY>71Ÿ=:i€ciuܳéΆ¶è,ÐýÓ?XÝޝb mÙž!Ÿ3°À5èÆXrÝkG¢#pµ»æ¢#,•Ö–æ‰ñ±è€”nŒ%×вºµm : 4Ýù±ŸéiŽN±$c|ÝIèî7:–:Ÿlÿ^.[¢ÄúzׯŒN@zéÆHB}®¡³gst š«Éôµß¢Ä&và£èÆHHGÏæÚºlt øT×÷W,‹NQ2c#C]í«¢Sjº1RS[ßœÖfÅÔùt÷íÑJcY>7:<€ŽÓ‘œ•÷6º£S°Àªæïß}WctŠÊç &pº1åÖ±úôêKÑnUkKóèð¶è”݉jhYÝÖu_t Xžœm}ktŠ[²kçDtʃnŒ€uöl®­³û.]z>>—Ëޝb‘úzû{×D§ <èÆHZ}®¡­ÓèXºÔÕd>՝‹N±H†Æžqº1tôlÎæ£S°@_ە¶ÂŠè7mldšÐܝ€²¡#@Mm}÷ڑè\íg»o‹Žps–ås£ÃCÑ)('º1bÚú ÝÑ)X pç•O¬nNq&Æ·çsî®à&èÆct,…úï*FGžQwwŽoÙø@t ʌnŒ0ËW¬lëº/: ,ÏÞ¶Ÿ¿çŽ:I7F*K¡{Z/ä²õÑ)èëݲñè”1Ý©PŸkèìٝ‚–go[ەN±Àϱè”7ÝiÑѳ¹¶Î®Œté]y©qŲèغiCWûªè”7ÝiQS[ßœv$: ÔÕd>Ý}{tŠL&“Y–ÏMŒoN@ÙӍ‘"+;¡-: ¬jþþêö–è™-7äsÆ žUº1ÒÅèX Ü5 µ¥ybÜMc”€nŒtihYÝÚ6‚šîüØÏô4PŒP*º1R§»ßèXê|²ý{¹l}ÈÑ}œë× † @åэ‘:õ¹†ÎžÍÑ)X ®&ó©î˜ëŸvíœ9€Š€#:z6góÑ)X ¯íJãOå>tldšÐܔð¡T0ÝiTS[ot,…6¬­KòžeùÜèðP’'Pñtc€ÔÊÎ{ ÝÑ)X p畻ïJnžotx(Ÿ‹Yä@¥Ò‘^FÇRèÓ«/%sPkKóèð¶dΠzèÆH¯†–Õm]÷E§`åÙÛÖ÷·&pЮ œ@µÑ‘j=›këlÕK—žÏå²w,é÷¯ìï]³€GPtc€Z}®¡­ÓèXºÔÕdÖ÷-[Ò#&vl_Ò× jéÆH»Õk‡³ùÆè,pwáR[aÅœøØÈP¡¹i‰^€*§£ t¯‰ŽÀÕ~¶û¶¥xÙeùÜèðÐRŒ2dtc”…B[c¡;: îŒò‰Õ­%ىñíùœæX*º1ʃѱê¿«XÚèëݲñÒŸ&ü(ÝåaùŠ•=›£S°Àòìm÷~¢”ƒŽl+á«ÀÓQ6:z6×ÖÙ¶—.œ+/55,/ÉKmÝŽ¡¿wMI^ ~Ýe£Š¶ŸÃèXÊÔÕdúÛo»õ×Y–ύÝúëÀGӍQN:îٔÍ7F§`îŸþÁêö–[|‘-7šK¹ž®I7F™éŽÀÕzZ‹·òé­-͆ÆH†nŒ2Óвº±Ð‚V6Ý>ØûñEúÄøX>ç&9’ £üK¡{Z/ä²õ‹øÄŸÞõëKž®I7Fù©Ï5tölŽNÁ˳·õµß±ˆOœØ1Vò0ð“èÆ(K=›këláK—Ou}¿qŲ›ú”­›6tµ¯Z¢<ðãtc”¥šÚúîµ#Ñ)žÚ§»o¿ñ^–ÏMŒo_º0ðãtc”«•÷ÞÙН‚V5u{Ë ~ð–ò9Ã$J7F3:–BwÍÝȇµ¶4OŒ»i €€éÆ(c -«[Û¢S°@ӝ[ßßzÝÛµs"0pÝå­»€¶Î^Ÿtéùø\.{ÇG|À@_oïšÄòÀéÆ(oõ¹†¶Îû¢S°@]MæSݹøCcDэQö:z6góÑ)X ¯íJãOå¯ù? š›ÎïӍQöjjë;{6G§àjÖÖýø?\–ύ%Þ§£¬ìŒ·±Ð‚ w^¹û®«çùF‡‡ò9÷ÃF7F…è^;«}zõ¥ýÛ»;ÚG‡·E…€ŒnŒŠ±|Åʶ®û¢S°Àòìmëû[ø·;ÆÃ@F7F%é^;R[g__ºô||.—œ#“ÉÜ¿n°¿wMtªnŒÊQS[ßÖyßí5uÑAøP]Mf}ß²L&3±c{tÈÔD€RZœvøÊåùšZÓc)Òٓ¹çµ…æŠè ¹í?øAtH‚ŠT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT Ýÿ{v ÈßzK£ 7À…àpáÆžpc\ž1.Ün € 7À…àpáÆžpc\ž1.Ün € 7À…àpœ —æò&7IEND®B`‚libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/master.xml0000644000175000017500000001044311260457741032571 0ustar twernertwerner ]> Hibernate Validator Reference Guide &versionNumber; &versionNumber; 1 ©rightYear; ©rightHolder; Preface Annotations are a very convenient and elegant way to specify invariant constraints for a domain model. You can, for example, express that a property should never be null, that the account balance should be strictly positive, etc. These domain model constraints are declared in the bean itself by annotating its properties. A validator can then read them and check for constraint violations. The validation mechanism can be executed in different layers in your application without having to duplicate any of these rules (presentation layer, data access layer). Following the DRY principle, Hibernate Validator has been designed for that purpose. Hibernate Validator works at two levels. First, it is able to check in-memory instances of a class for constraint violations. Second, it can apply the constraints to the Hibernate metamodel and incorporate them into the generated database schema. Each constraint annotation is associated to a validator implementation responsible for checking the constraint on the entity instance. A validator can also (optionally) apply the constraint to the Hibernate metamodel, allowing Hibernate to generate DDL that expresses the constraint. With the appropriate event listener, you can execute the checking operation on inserts and updates done by Hibernate. Hibernate Validator is not limited to use with Hibernate. You can easily use it anywhere in your application as well as with any Java Persistence provider (entity listener provided). When checking instances at runtime, Hibernate Validator returns information about constraint violations in an array of InvalidValue s. Among other information, the InvalidValue contains an error description message that can embed the parameter values bundle with the annotation (eg. length limit), and message strings that may be externalized to a ResourceBundle . libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/modules/0000755000175000017500000000000011402110375032205 5ustar twernertwerner././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/modules/defineconstraints.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/modules/defin0000644000175000017500000003665611260457741033252 0ustar twernertwerner Defining constraints
What is a constraint? A constraint is a rule that a given element (field, property or bean) has to comply to. The rule semantic is expressed by an annotation. A constraint usually has some attributes used to parameterize the constraints limits. The constraint applies to the annotated element.
Built in constraints Hibernate Validator comes with some built-in constraints, which covers most basic data checks. As we'll see later, you're not limited to them, you can literally in a minute write your own constraints. Built-in constraints Annotation Apply on Runtime checking Hibernate Metadata impact @Length(min=, max=) property (String) check if the string length match the range Column length will be set to max @Max(value=) property (numeric or string representation of a numeric) check if the value is less than or equals to max Add a check constraint on the column @Min(value=) property (numeric or string representation of a numeric) check if the value is more than or equals to min Add a check constraint on the column @NotNull property check if the value is not null Column(s) are not null @NotEmpty property check if the string is not null nor empty. Check if the connection is not null nor empty Column(s) are not null (for String) @Past property (date or calendar) check if the date is in the past Add a check constraint on the column @Future property (date or calendar) check if the date is in the future none @Pattern(regex="regexp", flag=) or @Patterns( {@Pattern(...)} ) property (string) check if the property match the regular expression given a match flag (see java.util.regex.Pattern ) none @Range(min=, max=) property (numeric or string representation of a numeric) check if the value is between min and max (included) Add a check constraint on the column @Size(min=, max=) property (array, collection, map) check if the element size is between min and max (included) none @AssertFalse property check that the method evaluates to false (useful for constraints expressed in code rather than annotations) none @AssertTrue property check that the method evaluates to true (useful for constraints expressed in code rather than annotations) none @Valid property (object) perform validation recursively on the associated object. If the object is a Collection or an array, the elements are validated recursively. If the object is a Map, the value elements are validated recursively. none @Email property (String) check whether the string is conform to the email address specification none @CreditCardNumber property (String) check whether the string is a well formated credit card number (derivative of the Luhn algorithm) none @Digits property (numeric or string representation of a numeric) check whether the property is a number having up to integerDigits integer digits and fractionalDigits fractonal digits define column precision and scale @EAN property (string) check whether the string is a properly formated EAN or UPC-A code none
Error messages Hibernate Validator comes with a default set of error messages translated in about ten languages (if yours is not part of it, please sent us a patch). You can override those messages by creating a ValidatorMessages.properties or ( ValidatorMessages_loc.properties ) and override the needed keys. You can even add your own additional set of messages while writing your validator annotations. If Hibernate Validator cannot resolve a key from your resourceBundle nor from ValidatorMessage, it falls back to the default built-in values. Alternatively you can provide a ResourceBundle while checking programmatically the validation rules on a bean or if you want a completly different interpolation mechanism, you can provide an implementation of org.hibernate.validator.MessageInterpolator (check the JavaDoc for more informations).
Writing your own constraints Extending the set of built-in constraints is extremely easy. Any constraint consists of two pieces: the constraint descriptor (the annotation) and the constraint validator (the implementation class). Here is a simple user-defined descriptor: @ValidatorClass(CapitalizedValidator.class) @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Capitalized { CapitalizeType type() default Capitalize.FIRST; String message() default "has incorrect capitalization" } type is a parameter describing how the property should to be capitalized. This is a user parameter fully dependant on the annotation business. message is the default string used to describe the constraint violation and is mandatory. You can hard code the string or you can externalize part/all of it through the Java ResourceBundle mechanism. Parameters values are going to be injected inside the message when the {parameter} string is found (in our example Capitalization is not {type} would generate Capitalization is not FIRST ), externalizing the whole string in ValidatorMessages.properties is considered good practice. See . @ValidatorClass(CapitalizedValidator.class) @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Capitalized { CapitalizeType type() default Capitalize.FIRST; String message() default "{validator.capitalized}"; } #in ValidatorMessages.properties validator.capitalized = Capitalization is not {type} As you can see the {} notation is recursive. To link a descriptor to its validator implementation, we use the @ValidatorClass meta-annotation. The validator class parameter must name a class which implements Validator<ConstraintAnnotation> . We now have to implement the validator (ie. the rule checking implementation). A validation implementation can check the value of the a property (by implementing PropertyConstraint ) and/or can modify the hibernate mapping metadata to express the constraint at the database level (by implementing PersistentClassConstraint ) public class CapitalizedValidator implements Validator<Capitalized>, PropertyConstraint { private CapitalizeType type; //part of the Validator<Annotation> contract, //allows to get and use the annotation values public void initialize(Capitalized parameters) { type = parameters.type(); } //part of the property constraint contract public boolean isValid(Object value) { if (value==null) return true; if ( !(value instanceof String) ) return false; String string = (String) value; if (type == CapitalizeType.ALL) { return string.equals( string.toUpperCase() ); } else { String first = string.substring(0,1); return first.equals( first.toUpperCase(); } } } The isValid() method should return false if the constraint has been violated. For more examples, refer to the built-in validator implementations. We only have seen property level validation, but you can write a Bean level validation annotation. Instead of receiving the return instance of a property, the bean itself will be passed to the validator. To activate the validation checking, just annotated the bean itself instead. A small sample can be found in the unit test suite. If your constraint can be applied multiple times (with different parameters) on the same property or type, you can use the following annotation form: @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Patterns { Pattern[] value(); } @Target(METHOD) @Retention(RUNTIME) @Documented @ValidatorClass(PatternValidator.class) public @interface Pattern { String regexp(); } Basically an annotation containing the value attribute as an array of validator annotations.
Annotating your domain model Since you are already familiar with annotations now, the syntax should be very familiar public class Address { private String line1; private String line2; private String zip; private String state; private String country; private long id; // a not null string of 20 characters maximum @Length(max=20) @NotNull public String getCountry() { return country; } // a non null string @NotNull public String getLine1() { return line1; } //no constraint public String getLine2() { return line2; } // a not null string of 3 characters maximum @Length(max=3) @NotNull public String getState() { return state; } // a not null numeric string of 5 characters maximum // if the string is longer, the message will //be searched in the resource bundle at key 'long' @Length(max=5, message="{long}") @Pattern(regex="[0-9]+") @NotNull public String getZip() { return zip; } // should always be true @AssertTrue public boolean isValid() { return true; } // a numeric between 1 and 2000 @Id @Min(1) @Range(max=2000) public long getId() { return id; } } While the example only shows public property validation, you can also annotate fields of any kind of visibility @MyBeanConstraint(max=45 public class Dog { @AssertTrue private boolean isMale; @NotNull protected String getName() { ... }; ... } You can also annotate interfaces. Hibernate Validator will check all superclasses and interfaces extended or implemented by a given bean to read the appropriate validator annotations. public interface Named { @NotNull String getName(); ... } public class Dog implements Named { @AssertTrue private boolean isMale; public String getName() { ... }; } The name property will be checked for nullity when the Dog bean is validated.
././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/modules/checkconstraints.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/src/main/docbook/en-US/modules/check0000644000175000017500000002375111260457741033232 0ustar twernertwerner Using the Validator framework Hibernate Validator is intended to be used to implement multi-layered data validation, where constraints are expressed in a single place (the annotated domain model) and checked in various different layers of the application. This chapter will cover Hibernate Validator usage for different layers
Database schema-level validation Out of the box, Hibernate Annotations will translate the constraints you have defined for your entities into mapping metadata. For example, if a property of your entity is annotated @NotNull, its columns will be declared as not null in the DDL schema generated by Hibernate. Using hbm2ddl, domain model constraints will be expressed into the database schema. If, for some reason, the feature needs to be disabled, set hibernate.validator.apply_to_ddl to false.
ORM integration Hibernate Validator integrates with both Hibernate and all pure Java Persistence providers
Hibernate event-based validation Hibernate Validator has two built-in Hibernate event listeners. Whenever a PreInsertEvent or PreUpdateEvent occurs, the listeners will verify all constraints of the entity instance and throw an exception if any constraint is violated. Basically, objects will be checked before any inserts and before any updates made by Hibernate. This includes changes applied by cascade! This is the most convenient and the easiest way to activate the validation process. On constraint violation, the event will raise a runtime InvalidStateException which contains an array of InvalidValues describing each failure. If Hibernate Validator is present in the classpath, Hibernate Annotations (or Hibernate EntityManager) will use it transparently. If, for some reason, you want to disable this integration, set hibernate.validator.autoregister_listeners to false If the beans are not annotated with validation annotations, there is no runtime performance cost. In case you need to manually set the event listeners for Hibernate Core, use the following configuration in hibernate.cfg.xml: <hibernate-configuration> ... <event type="pre-update"> <listener class="org.hibernate.validator.event.ValidateEventListener"/> </event> <event type="pre-insert"> <listener class="org.hibernate.validator.event.ValidateEventListener"/> </event> </hibernate-configuration>
Java Persistence event-based validation Hibernate Validator is not tied to Hibernate for event based validation: a Java Persistence entity listener is available. Whenever an listened entity is persisted or updated, Hibernate Validator will verify all constraints of the entity instance and throw an exception if any constraint is violated. Basically, objects will be checked before any inserts and before any updates made by the Java Persistence provider. This includes changes applied by cascade! On constraint violation, the event will raise a runtime InvalidStateException which contains an array of InvalidValues describing each failure. Here is how to make a class validatable: @Entity @EntityListeners( JPAValidateListener.class ) public class Submarine { ... } Compared to the Hibernate event, the Java Persistence listener has two drawbacks. You need to define the entity listener on every validatable entity. The DDL generated by your provider will not reflect the constraints.
Application-level validation Hibernate Validator can be applied anywhere in your application code. ClassValidator personValidator = new ClassValidator( Person.class ); ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) ); InvalidValue[] validationMessages = addressValidator.getInvalidValues(address); The first two lines prepare the Hibernate Validator for class checking. The first one relies upon the error messages embedded in Hibernate Validator (see ), the second one uses a resource bundle for these messages. It is considered a good practice to execute these lines once and cache the validator instances. The third line actually validates the Address instance and returns an array of InvalidValues. Your application logic will then be able to react to the failure. You can also check a particular property instead of the whole bean. This might be useful for property per property user interaction ClassValidator addressValidator = new ClassValidator( Address.class, ResourceBundle.getBundle("messages", Locale.ENGLISH) ); //only get city property invalid values InvalidValue[] validationMessages = addressValidator.getInvalidValues(address, "city"); //only get potential city property invalid values InvalidValue[] validationMessages = addressValidator.getPotentialInvalidValues("city", "Paris")
Presentation layer validation When working with JSF and JBoss Seam, one can triggers the validation process at the presentation layer using Seam's JSF tags <s:validate> and <s:validateAll/>, letting the constraints be expressed on the model, and the violations presented in the view <h:form> <div> <h:messages/> </div> <s:validateAll> <div> Country: <h:inputText value="#{location.country}" required="true"/> </div> <div> Zip code: <h:inputText value="#{location.zip}" required="true"/> </div> <div> <h:commandButton/> </div> </s:validateAll> </h:form> Going even further, and adding Ajax4JSF to the loop will bring client side validation with just a couple of additional JSF tags, again without validation definition duplication. Check the JBoss Seam documentation for more information.
Validation informations As a validation information carrier, hibernate provide an array of InvalidValue. Each InvalidValue has a buch of methods describing the individual issues. getBeanClass() retrieves the failing bean type getBean()retrieves the failing instance (if any ie not when using getPotentianInvalidValues()) getValue() retrieves the failing value getMessage() retrieves the proper internationalized error message getRootBean() retrieves the root bean instance generating the issue (useful in conjunction with @Valid), is null if getPotentianInvalidValues() is used. getPropertyPath() retrieves the dotted path of the failing property starting from the root bean
libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/changelog.txt0000644000175000017500000000326111070443367027160 0ustar twernertwernerHibernate Validator Changelog ============================= 3.1.0.GA (10-09-2008) ---------------------- 3.1.0.CR2 (20-08-2008) ---------------------- ** Bug * [HV-15] - @Past validation annotation generates incorrect DDL for Oracle 8.x * [HV-53] - AssertTrue and AssertFalse not compatible with null values * [HV-65] - @Past cannot use current_date as per the ANSI SQL spec * [HV-66] - 3.1.0.CR1 incompatible with Hibernate 3.3.0 3.1.0.CR1 (27-05-2008) ---------------------- ** Bug * [HV-14] - Minor typo in regular expression in class EmailValidator * [HV-48] - There is no DefaultValidatorMessage_en leading to no message loaded when locale is explicit and the system default is not en ** Improvement * [HV-57] - Move to slf4j ** New Feature * [HV-54] - Add pom * [HV-55] - Make build independent of Hibernate Core structure * [HV-56] - Move to Hibernate Core 3.3 ** Patch * [HV-36] - DefaultValidatorMessages_ja.properties 3.0.0.GA (19-03-2007) --------------------- Initial release as a standalone product (see Hibernate Annotations changelog for previous informations) ** Bug * [HV-2] - Deprecate String support for both @Past and @Future validating Strings * [HV-3] - @Email fail on empty strings * [HV-7] - Two level @Valid annotation doesn't work ** Improvement * [HV-5] - Multiple validators of the same type per element (John Gilbert) ** New Feature * [HV-1] - Make ClassValidator independent of Hibernate Annotations * [HV-6] - @EAN * [HV-8] - Make Validator support pure JavaPersistence players * [HV-9] - @Digits(integerDigits, fractionalDigits) * [HV-10] - @CreditCardNumber for Hibernate Validator libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/lgpl.txt0000644000175000017500000006347411070443223026172 0ustar twernertwerner GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libhibernate-validator-java-4.0.2.GA/hibernate-validator-legacy/pom.xml0000644000175000017500000002044111275002113025767 0ustar twernertwerner 4.0.0 hibernate-validator-parent org.hibernate 4.0.2.GA ../pom.xml hibernate-validator-legacy jar Hibernate Validator Legacy 4.0.2.GA http://validator.hibernate.org GNU LESSER GENERAL PUBLIC LICENSE http://www.gnu.org/licenses/lgpl.txt Following the DRY (Don't Repeat Yourself) principle, Hibernate Validator let's you express your domain constraints once (and only once) and ensure their compliance at various level of your system automatically. org.hibernate hibernate-core 3.3.1.GA org.hibernate hibernate-commons-annotations 3.1.0.GA org.slf4j slf4j-api org.hibernate ejb3-persistence 1.0.2.GA true org.hibernate hibernate-annotations 3.4.0.GA true org.hibernate hibernate-entitymanager 3.4.0.GA true javassist javassist 3.4.GA test asm asm 1.5.3 test asm asm-attrs 1.5.3 test org.slf4j slf4j-log4j12 test log4j log4j 1.2.14 test junit junit 3.8.1 test javax.transaction jta 1.1 test hsqldb hsqldb 1.8.0.2 test dist maven-assembly-plugin src/main/assembly/dist.xml org.apache.maven.plugins maven-javadoc-plugin ${basedir}/src/main/javadoc/stylesheet.css make-javadoc package javadoc org.jboss.maven.plugins maven-jdocbook-plugin 2.1.0 true org.hibernate hibernate-jdocbook-style 1.0.2 jdocbook-style master.xml ${basedir}/src/main/docbook/en-US en-US ${basedir}/src/main/docbook/en-US/images pdf classpath:/xslt/hibernate/pdf/main-pdf.xsl hibernate-validator-legacy-guide.pdf html_single classpath:/xslt/hibernate/html/main-single.xsl index.html html classpath:/xslt/hibernate/html/main-chunk.xsl index.html true - true make-doc site resources generate libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/0000755000175000017500000000000011402110367025174 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/0000755000175000017500000000000011402110366025762 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/0000755000175000017500000000000011402110365026740 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/0000755000175000017500000000000011402110365027661 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/0000755000175000017500000000000011402110365030450 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/0000755000175000017500000000000011402110365032411 5ustar twernertwerner././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/valid0000755000175000017500000000000011402110365033431 5ustar twernertwerner././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/validator/quickstart/libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/valid0000755000175000017500000000000011402110366033432 5ustar twernertwerner././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/validator/quickstart/BootstrapTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/valid0000644000175000017500000000712711262172500033445 0ustar twernertwerner/** * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import java.lang.annotation.ElementType; import java.util.Locale; import javax.validation.Configuration; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.Path; import javax.validation.TraversableResolver; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidatorConfiguration; /** * A module test that shows the different bootstrap possibilities of Hibernate Validator. * * @author Hardy Ferentschik */ public class BootstrapTest { @Test public void testBuildDefaultValidatorFactory() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); assertNotNull( validator ); } @Test public void testByDefaultProvider() { Configuration config = Validation.byDefaultProvider().configure(); config.messageInterpolator( new MyMessageInterpolator() ) .traversableResolver( new MyTraversableResolver() ) .constraintValidatorFactory( new MyConstraintValidatorFactory() ); ValidatorFactory factory = config.buildValidatorFactory(); Validator validator = factory.getValidator(); assertNotNull( validator ); } @Test public void testByProvider() { HibernateValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure(); config.messageInterpolator( new MyMessageInterpolator() ) .traversableResolver( new MyTraversableResolver() ) .constraintValidatorFactory( new MyConstraintValidatorFactory() ); ValidatorFactory factory = config.buildValidatorFactory(); Validator validator = factory.getValidator(); assertNotNull( validator ); } public class MyMessageInterpolator implements MessageInterpolator { public String interpolate(String messageTemplate, Context context) { return null; } public String interpolate(String messageTemplate, Context context, Locale locale) { return null; } } public class MyTraversableResolver implements TraversableResolver { public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return true; } public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return true; } } public class MyConstraintValidatorFactory implements ConstraintValidatorFactory { public > T getInstance(Class key) { return null; } } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/validator/quickstart/GroupTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/valid0000644000175000017500000000713511262172500033444 0ustar twernertwerner/** * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.groups.Default; import static org.junit.Assert.assertEquals; import org.junit.BeforeClass; import org.junit.Test; /** * A module test that shows how to use the grouping functionality of Bean Validation. * * @author Hardy Ferentschik */ public class GroupTest { private static Validator validator; @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Test public void testDriveAway() { // create a car and check that everything is ok with it. Car car = new Car( "Morris", "DD-AB-123", 2 ); Set> constraintViolations = validator.validate( car ); assertEquals( 0, constraintViolations.size() ); // but has it passed the vehicle inspection? constraintViolations = validator.validate( car, CarChecks.class ); assertEquals( 1, constraintViolations.size() ); assertEquals( "The car has to pass the vehicle inspection first", constraintViolations.iterator().next().getMessage() ); // let's go to the vehicle inspection car.setPassedVehicleInspection( true ); assertEquals( 0, validator.validate( car ).size() ); // now let's add a driver. He is 18, but has not passed the driving test yet Driver john = new Driver( "John Doe" ); john.setAge( 18 ); car.setDriver( john ); constraintViolations = validator.validate( car, DriverChecks.class ); assertEquals( 1, constraintViolations.size() ); assertEquals( "You first have to pass the driving test", constraintViolations.iterator().next().getMessage() ); // ok, John passes the test john.passedDrivingTest( true ); assertEquals( 0, validator.validate( car, DriverChecks.class ).size() ); // just checking that everything is in order now assertEquals( 0, validator.validate( car, Default.class, CarChecks.class, DriverChecks.class ).size() ); } @Test public void testOrderedChecks() { Car car = new Car( "Morris", "DD-AB-123", 2 ); car.setPassedVehicleInspection( true ); Driver john = new Driver( "John Doe" ); john.setAge( 18 ); john.passedDrivingTest( true ); car.setDriver( john ); assertEquals( 0, validator.validate( car, OrderedChecks.class ).size() ); } @Test public void testOrderedChecksWithRedefinedDefault() { RentalCar rentalCar = new RentalCar( "Morris", "DD-AB-123", 2 ); rentalCar.setPassedVehicleInspection( true ); Driver john = new Driver( "John Doe" ); john.setAge( 18 ); john.passedDrivingTest( true ); rentalCar.setDriver( john ); assertEquals( 0, validator.validate( rentalCar, Default.class, DriverChecks.class ).size() ); } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/validator/quickstart/CarTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/test/java/org/hibernate/valid0000644000175000017500000000722611262172500033445 0ustar twernertwerner/** * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import static org.junit.Assert.assertEquals; import org.junit.BeforeClass; import org.junit.Test; /** *

* A module test that shows how to use the Bean Validation (BV) API to validate * the constraint annotations at the exemplary {@link Car} model class. *

*

* The interface {@link Validator} is the main entry point the BV API. The * test makes use of the validate() method of that interface, which * returns a set of ConstraintViolations, that describe the * problems occurred during validation. *

*

* In case the object in question could be validated successfully this set will * be empty. *

* * @author Gunnar Morling * @author Hardy Ferentschik */ public class CarTest { /** * The validator to be used for object validation. Will be retrieved once * for all test methods. */ private static Validator validator; /** * Retrieves the validator instance. */ @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } /** * One constraint violation due to the manufacturer field being null * expected. */ @Test public void manufacturerIsNull() { Car car = new Car( null, "DD-AB-123", 4 ); Set> constraintViolations = validator.validate( car ); assertEquals( 1, constraintViolations.size() ); assertEquals( "may not be null", constraintViolations.iterator().next().getMessage() ); } /** * One constraint violation due to the licensePlate field being too short * expected. */ @Test public void licensePlateTooShort() { Car car = new Car( "Morris", "D", 4 ); Set> constraintViolations = validator.validate( car ); assertEquals( 1, constraintViolations.size() ); assertEquals( "size must be between 2 and 14", constraintViolations.iterator().next().getMessage() ); } /** * One constraint violation due to the seatCount field being too low * expected. */ @Test public void seatCountTooLow() { Car car = new Car( "Morris", "DD-AB-123", 1 ); Set> constraintViolations = validator.validate( car ); assertEquals( 1, constraintViolations.size() ); assertEquals( "must be greater than or equal to 2", constraintViolations.iterator().next().getMessage() ); } /** * No constraint violation expected, as all fields of the validated Car * instance have proper values. */ @Test public void carIsValid() { Car car = new Car( "Morris", "DD-AB-123", 2 ); Set> constraintViolations = validator.validate( car ); assertEquals( 0, constraintViolations.size() ); } } libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/0000755000175000017500000000000011402110367026707 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/resources/0000755000175000017500000000000011402110367030721 5ustar twernertwerner././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/resources/log4j.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/resources/log4j.properti0000644000175000017500000000155111173623006033534 0ustar twernertwerner### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file hibernate.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=hibernate.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to socket - chainsaw ### log4j.appender.socket=org.apache.log4j.net.SocketAppender log4j.appender.socket.remoteHost=localhost log4j.appender.socket.port=4560 log4j.appender.socket.locationInfo=true ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=debug, stdout libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/0000755000175000017500000000000011402110366027627 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/0000755000175000017500000000000011402110366030416 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/0000755000175000017500000000000011402110366032357 5ustar twernertwerner././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000755000175000017500000000000011402110366033377 5ustar twernertwerner././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000755000175000017500000000000011402110367033400 5ustar twernertwerner././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/Car.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000564311262172500033413 0ustar twernertwerner/** * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import javax.validation.Valid; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** * An example entity class enriched with constraint annotations from * the Bean Validation API (
JSR * 303). Have a look at {@link org.hibernate.validator.quickstart.CarTest} to learn, how the Bean Validation * API can be used to validate {@code Car} instances. * * @author Gunnar Morling * @author Hardy Ferentschik */ public class Car { /** * By annotating the field with @NotNull we specify, that null is not a valid * value. */ @NotNull private String manufacturer; /** * This String field shall not only not allowed to be null, it shall also between * 2 and 14 characters long. */ @NotNull @Size(min = 2, max = 14) private String licensePlate; /** * This int field shall have a value of at least 2. */ @Min(2) private int seatCount; @AssertTrue(message = "The car has to pass the vehicle inspection first", groups = CarChecks.class) private boolean passedVehicleInspection; @Valid private Driver driver; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public String getLicensePlate() { return licensePlate; } public void setLicensePlate(String licensePlate) { this.licensePlate = licensePlate; } public int getSeatCount() { return seatCount; } public void setSeatCount(int seatCount) { this.seatCount = seatCount; } public boolean getPassedVehicleInspection() { return passedVehicleInspection; } public void setPassedVehicleInspection(boolean passed) { this.passedVehicleInspection = passed; } public Driver getDriver() { return driver; } public void setDriver(Driver driver) { this.driver = driver; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/Person.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000226611262172500033411 0ustar twernertwerner// $Id: Person.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import javax.validation.constraints.NotNull; /** * @author Hardy Ferentschik */ public class Person { @NotNull private String name; public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/OrderedChecks.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000214511262172500033405 0ustar twernertwerner// $Id: OrderedChecks.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import javax.validation.GroupSequence; import javax.validation.groups.Default; /** * @author Hardy Ferentschik */ @GroupSequence({ Default.class, CarChecks.class, DriverChecks.class }) public interface OrderedChecks { } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/RentalCar.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000225511262172500033407 0ustar twernertwerner// $Id: RentalCar.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import javax.validation.GroupSequence; /** * @author Hardy Ferentschik */ @GroupSequence({ RentalCar.class, CarChecks.class }) public class RentalCar extends Car { public RentalCar(String manufacturer, String licencePlate, int seatCount) { super( manufacturer, licencePlate, seatCount ); } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/DriverChecks.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000171411262172500033406 0ustar twernertwerner// $Id: DriverChecks.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; /** * @author Hardy Ferentschik */ public interface DriverChecks { } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/CarChecks.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000170611262172500033407 0ustar twernertwerner// $Id: CarChecks.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; /** * @author Hardy Ferentschik */ public interface CarChecks { } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/validator/quickstart/Driver.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/src/main/java/org/hibernate/valid0000644000175000017500000000276011262172500033410 0ustar twernertwerner// $Id: Driver.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.quickstart; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.Min; /** * @author Hardy Ferentschik */ public class Driver extends Person { @Min(value = 18, message = "You have to be 18 to drive a car", groups = DriverChecks.class) public int age; @AssertTrue(message = "You first have to pass the driving test", groups = DriverChecks.class) public boolean hasDrivingLicense; public Driver(String name) { super( name ); } public void passedDrivingTest(boolean b) { hasDrivingLicense = b; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } libhibernate-validator-java-4.0.2.GA/hibernate-validator-archetype/pom.xml0000644000175000017500000000335311275002113026512 0ustar twernertwerner 4.0.0 hibernate-validator-parent org.hibernate 4.0.2.GA ../pom.xml org.hibernate hibernate-validator-quickstart Hibernate Validator Quickstart junit junit 4.5 test org.slf4j slf4j-log4j12 runtime org.hibernate hibernate-validator ${project.parent.version} test maven-compiler-plugin 1.5 1.5 jboss http://repository.jboss.com/maven2 libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/0000755000175000017500000000000011402110405025271 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/0000755000175000017500000000000011402110405026060 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/0000755000175000017500000000000011402110404027036 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/0000755000175000017500000000000011402110405031051 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/0000755000175000017500000000000011402110404031637 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/0000755000175000017500000000000011402110404032757 5ustar twernertwerner././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000755000175000017500000000000011402110404033473 5ustar twernertwerner././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/impl/libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000755000175000017500000000000011402110404033473 5ustar twernertwerner././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/impl/packaging/libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000755000175000017500000000000011402110404033473 5ustar twernertwerner././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000755000175000017500000000000011402110404033473 5ustar twernertwerner././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/default/libhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000755000175000017500000000000011402110404033473 5ustar twernertwerner././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/testharness/impl/packaging/jsr299/default/beans.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/org/jboss/tes0000644000175000017500000000000011173623006033477 0ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/log4j.xml0000644000175000017500000000267311173623006032635 0ustar twernertwerner ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/jndi.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/resources/jndi.properti0000644000175000017500000000031111173623006033571 0ustar twernertwerner#jboss JNDI properties java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.provider.url=jnp://localhost:1099 java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaceslibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/test/java/0000755000175000017500000000000011402110404027757 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/0000755000175000017500000000000011402110405027004 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/resources/0000755000175000017500000000000011402110405031016 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/resources/META-INF/0000755000175000017500000000000011402110405032156 5ustar twernertwerner././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/resources/META-INF/jboss-test-harness.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/resources/META-INF/jbos0000644000175000017500000000041311213707342033050 0ustar twernertwernerorg.jboss.testharness.spi.StandaloneContainers=org.hibernate.jsr303.tck.util.StandaloneContainersImpl org.jboss.testharness.api.TestLauncher=org.jboss.testharness.impl.runner.servlet.ServletTestLauncher org.jboss.testharness.testPackage=org.hibernate.jsr303.tck.testslibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/src/main/java/0000755000175000017500000000000011402110405027725 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator-tck-runner/pom.xml0000644000175000017500000002615311275002113026621 0ustar twernertwerner hibernate-validator-parent org.hibernate 4.0.2.GA 4.0.0 hibernate-validator-tck-runner Hibernate Validator TCK Runner Aggregates dependencies and run's the JSR-303 TCK javax.validation validation-api org.hibernate hibernate-validator ${version} org.slf4j slf4j-log4j12 runtime org.testng testng jdk15 org.hibernate.jsr303.tck jsr303-tck 1.0.1.GA org.jboss.test-harness jboss-test-harness-jboss-as-51 1.0.0 /opt/java/jboss-5.1.0.GA org.hibernate.validator.HibernateValidator org.apache.maven.plugins maven-dependency-plugin copy generate-test-sources copy true org.hibernate.jsr303.tck jsr303-tck xml suite false javax.validation validation-api true ${project.build.directory}/dependency/lib org.hibernate hibernate-validator true ${project.build.directory}/dependency/lib org.slf4j slf4j-log4j12 true ${project.build.directory}/dependency/lib org.apache.maven.plugins maven-surefire-plugin ${project.build.directory}/dependency/jsr303-tck-suite.xml -Xmx128m once validation.provider ${validation.provider} org.apache.maven.plugins maven-surefire-report-plugin generate-test-report test report-only ${project.build.directory}/surefire-reports test-report incontainer-debug debug -Xnoagent -Djava.compiler=NONE -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005 incontainer incontainer org.apache.maven.plugins maven-surefire-plugin ${project.build.directory}/dependency/jsr303-tck-suite.xml validation.provider ${validation.provider} org.jboss.testharness.standalone false jboss.home ${jboss.home} org.jboss.testharness.container.javaOpts -Xms128m -Xmx384m -XX:MaxPermSize=128m -Dorg.jboss.resolver.warning=true -Dvalidation.provider=${validation.provider} ${remote.debug} org.jboss.testharness.container.forceRestart true org.jboss.testharness.runIntegrationTests true org.jboss.testharness.libraryDirectory target/dependency/lib org.jboss.testharness.outputDirectory target write-artifacts-to-disk dumpArtifacts org.codehaus.mojo exec-maven-plugin generate-jsr-303-artifacts test-compile java test org.jboss.testharness.api.TCK dumpArtifacts true org.jboss.testharness.outputDirectory target/jsr303-artifacts org.jboss.testharness.libraryDirectory target/jsr303-artifacts/dependencies libhibernate-validator-java-4.0.2.GA/license.txt0000644000175000017500000002613611131145407021463 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libhibernate-validator-java-4.0.2.GA/src/0000755000175000017500000000000011402110404020045 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/src/site/0000755000175000017500000000000011402110404021011 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/src/site/site.xml0000644000175000017500000000077411173623006022523 0ustar twernertwerner Maven http://maven.apache.org/images/apache-maven-project.png http://maven.apache.org/ http://maven.apache.org/images/maven-small.gif libhibernate-validator-java-4.0.2.GA/hibernate-validator/0000755000175000017500000000000011402110365023210 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/license.txt0000644000175000017500000002613611144263744025420 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. libhibernate-validator-java-4.0.2.GA/hibernate-validator/readme.txt0000644000175000017500000000443711275001114025215 0ustar twernertwerner Hibernate Validator What is it? ----------- This is the reference implementation of JSR 303 - Bean Validation. Bean Validation defines a metadata model and API for JavaBean validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML validation descriptors. History ------- Prior to version 4.x Hibernate Validators was based on a different source base which is not based on JSR 303. This code can be accessed via http://anonsvn.jboss.org/repos/hibernate/validator/trunk/hibernate-validator-legacy Status ------ This is the first GA release of Hibernate Validator 4. Documentation ------------- The documentation for this release is included in the docs directory of distribution package or online under https://www.hibernate.org/5.html Release Notes ------------- The full list of changes can be found at http://opensource.atlassian.com/projects/hibernate/secure/ReleaseNote.jspa?projectId=10060&version=10982 System Requirements ------------------- JDK 1.5 or above. Using Hibernate Validator ------------------------- - Copy hibernate-validator-*.jar together will all jar files from lib into the classpath of your application. In case you are running on JDK5 you have to also include all the jar files from the jdk5 subdirectory. or - Add the following to your maven or ivy dependency list: org.hibernate hibernate-validator ${project.version} Hibernate Validator can be found in this repository: http://repository.jboss.com/maven2/ Licensing --------- Please see the file called license.txt Hibernate Validator URLs ------------------------ Home Page: http://validator.hibernate.org/ Migration Guide: http://www.hibernate.org/468.html Downloads: http://www.hibernate.org/6.html Mailing Lists: http://www.hibernate.org/20.html Source Code: http://anonsvn.jboss.org/repos/hibernate/validator/trunk/ Issue Tracking: http://opensource.atlassian.com/projects/hibernate/browse/HV libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/0000755000175000017500000000000011402110365023777 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/site/0000755000175000017500000000000011402110365024743 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/site/site.xml0000644000175000017500000000073611173623006026445 0ustar twernertwerner Maven http://maven.apache.org/images/apache-maven-project.png http://maven.apache.org/ http://maven.apache.org/images/maven-small.gif libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/0000755000175000017500000000000011402110345024754 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/0000755000175000017500000000000011402110346026767 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/0000755000175000017500000000000011402110346027556 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/0000755000175000017500000000000011402110346031517 5ustar twernertwerner././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000755000175000017500000000000011402110346033504 5ustar twernertwerner././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000755000175000017500000000000011402110346033504 5ustar twernertwerner././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/mapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000644000175000017500000000116311245243312033514 0ustar twernertwerner org.hibernate.validator.xml ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/my-interface-impl-mapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000644000175000017500000000111611272032647033521 0ustar twernertwerner org.hibernate.validator.xml ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/mixedconfiguration/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000755000175000017500000000000011402110346033504 5ustar twernertwerner././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/mixedconfiguration/xml-mappings.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000755000175000017500000000250111274325274033526 0ustar twernertwerner org.hibernate.validator.xml.mixedconfiguration.xml 1 ././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/mixedconfiguration/annotation-mappings.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000755000175000017500000000046611274325274033536 0ustar twernertwerner ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/my-interface-mapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000644000175000017500000000111211272032647033515 0ustar twernertwerner org.hibernate.validator.xml ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/empty-my-interface-mapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000644000175000017500000000066411272253663033533 0ustar twernertwerner org.hibernate.validator.xml ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/xml/properties-mapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/org/hibernate/validator/0000644000175000017500000000114211265335074033522 0ustar twernertwerner org.hibernate.validator.xml ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/ValidationMessages_es.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/ValidationMessages_es.pr0000644000175000017500000000007611213774651033625 0ustar twernertwernerjavax.validation.constraints.NotNull.message=no puede ser nulllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/resources/log4j.properties0000644000175000017500000000207511245224703032140 0ustar twernertwerner### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file hibernate.log ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=hibernate.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to socket - chainsaw ### log4j.appender.socket=org.apache.log4j.net.SocketAppender log4j.appender.socket.remoteHost=localhost log4j.appender.socket.port=4560 log4j.appender.socket.locationInfo=true ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=debug, stdout log4j.logger.org.hibernate.validator.engine.ValidatorImpl=trace #log4j.logger.org.hibernate.validatorengine.ConstraintTree=trace log4j.logger.org.hibernate.validator.engine.ResourceBundleMessageInterpolator=info libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/0000755000175000017500000000000011402110327025675 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/0000755000175000017500000000000011402110327026464 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/0000755000175000017500000000000011402110327030425 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/0000755000175000017500000000000011402110344032411 5ustar twernertwerner././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110336033433 5ustar twernertwerner././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/ValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000432611262172500033447 0ustar twernertwerner// $Id: ValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; import javax.validation.metadata.BeanDescriptor; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertCorrectPropertyPaths; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class ValidatorTest { /** * HV-208 */ @Test public void testPropertyPathDoesNotStartWithLeadingDot() { Validator validator = TestUtil.getValidator(); A testInstance = new A(); Set> constraintViolations = validator.validate( testInstance ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "b" ); } /** * HV-132 - supper hasBoolean format */ @Test public void testHasBoolean() { Validator validator = TestUtil.getValidator(); BeanDescriptor beanDescr = validator.getConstraintsForClass( B.class ); assertTrue( beanDescr.isBeanConstrained() ); } class A { @NotNull String b; } class B { private boolean b; @AssertTrue public boolean hasB() { return b; } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110334033431 5ustar twernertwerner././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/CyclicGroupSequence.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000206711262172500033447 0ustar twernertwerner// $Id: CyclicGroupSequence.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.GroupSequence; /** * @author Hardy Ferentschik */ @GroupSequence(value = CyclicGroupSequence.class) public interface CyclicGroupSequence { } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/CyclicGroupSequence2.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000207211262172500033443 0ustar twernertwerner// $Id: CyclicGroupSequence2.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.GroupSequence; /** * @author Hardy Ferentschik */ @GroupSequence(value = CyclicGroupSequence1.class) public interface CyclicGroupSequence2 { } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/GroupChainGeneratorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000747711262172500033461 0ustar twernertwerner// $Id: GroupChainGeneratorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.validation.ValidationException; import javax.validation.groups.Default; import static org.testng.Assert.assertEquals; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class GroupChainGeneratorTest { GroupChainGenerator generator; @BeforeTest public void init() { generator = new GroupChainGenerator(); } @Test(expectedExceptions = ValidationException.class) public void testGroupChainForNonInterface() { Set> groups = new HashSet>(); groups.add( String.class ); generator.getGroupChainFor( groups ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testGroupChainForNull() { generator.getGroupChainFor( null ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testGroupChainForEmptySet() { generator.getGroupChainFor( new HashSet>() ); } @Test(expectedExceptions = ValidationException.class) public void testCyclicGroupSequences() { Set> groups = new HashSet>(); groups.add( CyclicGroupSequence1.class ); generator.getGroupChainFor( groups ); } @Test(expectedExceptions = ValidationException.class) public void testCyclicGroupSequence() { Set> groups = new HashSet>(); groups.add( CyclicGroupSequence.class ); generator.getGroupChainFor( groups ); } @Test public void testGroupDuplicates() { Set> groups = new HashSet>(); groups.add( First.class ); groups.add( Second.class ); groups.add( Last.class ); GroupChain chain = generator.getGroupChainFor( groups ); int count = countGroups( chain ); assertEquals( count, 3, "Wrong number of groups" ); groups.clear(); groups.add( First.class ); groups.add( First.class ); chain = generator.getGroupChainFor( groups ); count = countGroups( chain ); assertEquals( count, 1, "Wrong number of groups" ); groups.clear(); groups.add( First.class ); groups.add( Last.class ); groups.add( First.class ); chain = generator.getGroupChainFor( groups ); count = countGroups( chain ); assertEquals( count, 2, "Wrong number of groups" ); } private int countGroups(GroupChain chain) { Iterator groupIterator = chain.getGroupIterator(); int count = 0; while ( groupIterator.hasNext() ) { groupIterator.next(); count++; } return count; } @Test public void testSequenceResolution() { Set> groups = new HashSet>(); groups.add( Address.Complete.class ); GroupChain chain = generator.getGroupChainFor( groups ); Iterator> sequences = chain.getSequenceIterator(); List sequence = sequences.next(); assertEquals( sequence.get( 0 ).getGroup(), Default.class, "Wrong group" ); assertEquals( sequence.get( 1 ).getGroup(), Address.HighLevelCoherence.class, "Wrong group" ); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/Address.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000413311262172500033443 0ustar twernertwerner// $Id: Address.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.GroupSequence; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import javax.validation.groups.Default; /** * @author Emmanuel Bernard */ @GroupSequence({ Address.class, Address.HighLevelCoherence.class }) @ZipCodeCoherenceChecker(groups = Address.HighLevelCoherence.class) public class Address { @NotNull @Size(max = 50) private String street; @NotNull @Size(max = 5) private String zipcode; @NotNull @Size(max = 30) private String city; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getZipcode() { return zipcode; } public void setZipcode(String zipcode) { this.zipcode = zipcode; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } /** * Check conherence on the overall object * Needs basic checking to be green first */ public interface HighLevelCoherence { } /** * Check both basic constraints and high level ones. * High level constraints are not checked if basic constraints fail. */ @GroupSequence(value = { Default.class, HighLevelCoherence.class }) public interface Complete { } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/ZipCodeCoherenceChecker.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000306011262172500033441 0ustar twernertwerner// $Id: ZipCodeCoherenceChecker.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.TYPE; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; /** * @author Emmanuel Bernard */ @Target({ TYPE, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented @Constraint(validatedBy = ZipCodeCoherenceValidator.class) public @interface ZipCodeCoherenceChecker { public abstract String message() default "{validator.zipCodeCoherenceChecker}"; public abstract Class[] groups() default { }; } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/ZipCodeCoherenceValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000247611262172500033453 0ustar twernertwerner// $Id: ZipCodeCoherenceValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class ZipCodeCoherenceValidator implements ConstraintValidator { public void initialize(ZipCodeCoherenceChecker parameters) { } public boolean isValid(Address value, ConstraintValidatorContext constraintValidatorContext) { return false; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/First.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000175511262172500033452 0ustar twernertwerner// $Id: First.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; /** * Group executed first in the validation * * @author Emmanuel Bernard */ public interface First { } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/Second.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000176411262172500033452 0ustar twernertwerner// $Id: Second.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; /** * Group executed second during the validation * * @author Emmanuel Bernard */ public interface Second { } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/GroupChainTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000001065511262172500033451 0ustar twernertwerner// $Id: GroupChainTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import java.util.ArrayList; import java.util.List; import javax.validation.GroupDefinitionException; import javax.validation.groups.Default; import static org.testng.FileAssert.fail; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class GroupChainTest { @Test public void testAssertDefaultGroupSequenceIsExpandableWithDefaultAtEndOfSequence() { // create a dummy sequence Group a = new Group( GroupA.class, TestSequence.class ); Group b = new Group( GroupB.class, TestSequence.class ); Group c = new Group( GroupC.class, TestSequence.class ); Group defaultGroup = new Group( Default.class, TestSequence.class ); List sequence = new ArrayList(); sequence.add( a ); sequence.add( b ); sequence.add( c ); sequence.add( defaultGroup ); GroupChain chain = new GroupChain(); chain.insertSequence( sequence ); // create test default sequence List> defaultSequence = new ArrayList>(); defaultSequence.add( Default.class ); defaultSequence.add( GroupA.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } defaultSequence.clear(); defaultSequence.add( GroupA.class ); defaultSequence.add( Default.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } defaultSequence.clear(); defaultSequence.add( Default.class ); defaultSequence.add( GroupC.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } defaultSequence.clear(); defaultSequence.add( GroupC.class ); defaultSequence.add( Default.class ); chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); } @Test public void testAssertDefaulGroupSequenceIsExpandableWithDefaultAtBeginningOfSequence() { // create a dummy sequence Group a = new Group( GroupA.class, TestSequence.class ); Group b = new Group( GroupB.class, TestSequence.class ); Group c = new Group( GroupC.class, TestSequence.class ); Group defaultGroup = new Group( Default.class, TestSequence.class ); List sequence = new ArrayList(); sequence.add( defaultGroup ); sequence.add( a ); sequence.add( b ); sequence.add( c ); GroupChain chain = new GroupChain(); chain.insertSequence( sequence ); // create test default sequence List> defaultSequence = new ArrayList>(); defaultSequence.add( Default.class ); defaultSequence.add( GroupA.class ); chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); defaultSequence.clear(); defaultSequence.add( GroupA.class ); defaultSequence.add( Default.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } defaultSequence.clear(); defaultSequence.add( Default.class ); defaultSequence.add( GroupC.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } defaultSequence.clear(); defaultSequence.add( GroupC.class ); defaultSequence.add( Default.class ); try { chain.assertDefaultGroupSequenceIsExpandable( defaultSequence ); fail(); } catch ( GroupDefinitionException e ) { // success } } } interface TestSequence { } interface GroupA { } interface GroupB { } interface GroupC { } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/CyclicGroupSequence1.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000207211262172500033443 0ustar twernertwerner// $Id: CyclicGroupSequence1.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.GroupSequence; /** * @author Hardy Ferentschik */ @GroupSequence(value = CyclicGroupSequence2.class) public interface CyclicGroupSequence1 { } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/groups/Last.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000175211262172500033447 0ustar twernertwerner// $Id: Last.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; /** * Group executed Last in the validation * * @author Emmanuel Bernard */ public interface Last { } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/serialization/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110336033433 5ustar twernertwerner././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/serialization/SerializableClass.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000212111262172500033436 0ustar twernertwerner// $Id: SerializableClass.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.serialization; import java.io.Serializable; import javax.validation.constraints.NotNull; /** * @author Hardy Ferentschik */ public class SerializableClass implements Serializable { @NotNull private String foo; } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/serialization/UnSerializableClass.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000204011262172500033436 0ustar twernertwerner// $Id: UnSerializableClass.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.serialization; import javax.validation.constraints.NotNull; /** * @author Hardy Ferentschik */ public class UnSerializableClass { @NotNull private String foo; } ././@LongLink0000000000000000000000000000023600000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/serialization/ConstraintViolationSerializationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000602411262172500033444 0ustar twernertwerner// $Id: ConstraintViolationSerializationTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.serialization; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.NotSerializableException; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class ConstraintViolationSerializationTest { /** * HV-245 */ @Test public void testSuccessfulSerialization() throws Exception { Validator validator = TestUtil.getValidator(); SerializableClass testInstance = new SerializableClass(); Set> constraintViolations = validator.validate( testInstance ); byte[] bytes = serialize( constraintViolations ); Set> deserializedViolations = deserialize( bytes ); assertNumberOfViolations( deserializedViolations, 1 ); } /** * HV-245 */ @Test(expectedExceptions = NotSerializableException.class) public void testUnSuccessfulSerialization() throws Exception { Validator validator = TestUtil.getValidator(); UnSerializableClass testInstance = new UnSerializableClass(); Set> constraintViolations = validator.validate( testInstance ); serialize( constraintViolations ); } private byte[] serialize(Object o) throws Exception { ByteArrayOutputStream stream = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream( stream ); out.writeObject( o ); out.close(); byte[] serialized = stream.toByteArray(); stream.close(); return serialized; } private Set> deserialize(byte[] byteData) throws Exception { ByteArrayInputStream byteIn = new ByteArrayInputStream( byteData ); ObjectInputStream in = new ObjectInputStream( byteIn ); Set> deserializedViolations = ( Set> ) in.readObject(); in.close(); byteIn.close(); return deserializedViolations; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/messageinterpolation/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110334033431 5ustar twernertwerner././@LongLink0000000000000000000000000000023100000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/messageinterpolation/MessageInterpolationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000703711262172500033451 0ustar twernertwerner// $Id: MessageInterpolationTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.messageinterpolation; import java.io.ByteArrayInputStream; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import static org.testng.Assert.assertEquals; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.engine.ResourceBundleMessageInterpolator; /** * Tests for HV-184 * * @author Hardy Ferentschik */ public class MessageInterpolationTest { private Validator validator; @BeforeClass public void createValidator() throws Exception { final StringBuilder lines = new StringBuilder(); lines.append( "bar=Message is \\\\{escaped\\\\}" ).append( "\r\n" ); lines.append( "baz=Message is US$ {value}" ).append( "\r\n" ); lines.append( "qux=Message is {missing}" ).append( "\r\n" ); lines.append( "escaped=wrong" ).append( "\r\n" ); final ResourceBundle bundle = new PropertyResourceBundle( new ByteArrayInputStream( lines.toString().getBytes() ) ); Configuration config = ( Configuration ) Validation.byDefaultProvider() .configure() .messageInterpolator( new ResourceBundleMessageInterpolator( bundle ) ); ValidatorFactory factory = config.buildValidatorFactory(); validator = factory.getValidator(); } @Test public void testCurlyBracesEscapingShouldBeRespected() { final ConstraintViolation violation = validator.validate( new Foo(), Bar.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is {escaped}" ); } @Test public void testAppendReplacementNeedsToEscapeBackslashAndDollarSign() { final ConstraintViolation violation = validator.validate( new Foo(), Baz.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is US$ 5" ); } @Test public void testUnknownParametersShouldBePreserved() { final ConstraintViolation violation = validator.validate( new Foo(), Qux.class ).iterator().next(); assertEquals( violation.getMessage(), "Message is {missing}" ); } public static interface Bar { } public static interface Baz { } public static interface Qux { } public static class Foo { @NotNull(message = "{bar}", groups = { Bar.class }) public String getBar() { return null; } @Min(value = 5, message = "{baz}", groups = { Baz.class }) public int getBaz() { return 0; } @NotNull(message = "{qux}", groups = { Qux.class }) public String getQux() { return null; } } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/messageinterpolation/User.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000242411274520070033446 0ustar twernertwerner// $Id:$ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.messageinterpolation; import org.hibernate.validator.constraints.Email; import org.hibernate.validator.constraints.Range; /** * @author Hardy Ferentschik */ public class User { @Email private String email; @Range(min = 18, max = 21) private int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } } ././@LongLink0000000000000000000000000000024600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/messageinterpolation/ResourceBundleMessageInterpolatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000002632511262172500033452 0ustar twernertwerner// $Id: ResourceBundleMessageInterpolatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.messageinterpolation; import java.util.Enumeration; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.NoSuchElementException; import java.util.ResourceBundle; import javax.validation.MessageInterpolator; import javax.validation.constraints.Max; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import static org.testng.Assert.assertEquals; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import org.hibernate.validator.engine.MessageInterpolatorContext; import org.hibernate.validator.engine.ResourceBundleMessageInterpolator; import org.hibernate.validator.metadata.ConstraintDescriptorImpl; import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.ConstraintOrigin; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * Tests for message interpolation. * * @author Hardy Ferentschik */ public class ResourceBundleMessageInterpolatorTest { private ResourceBundleMessageInterpolator interpolator; private NotNull notNull; private ConstraintDescriptorImpl notNullDescriptor; private Size size; private ConstraintDescriptorImpl sizeDescriptor; @BeforeTest public void setUp() { // Create some annotations for testing using AnnotationProxies AnnotationDescriptor descriptor = new AnnotationDescriptor( NotNull.class ); notNull = AnnotationFactory.create( descriptor ); notNullDescriptor = new ConstraintDescriptorImpl( notNull, new ConstraintHelper(), java.lang.annotation.ElementType.FIELD, ConstraintOrigin.DEFINED_LOCALLY ); AnnotationDescriptor sizeAnnotationDescriptor = new AnnotationDescriptor( Size.class ); size = AnnotationFactory.create( sizeAnnotationDescriptor ); sizeDescriptor = new ConstraintDescriptorImpl( size, new ConstraintHelper(), java.lang.annotation.ElementType.FIELD, ConstraintOrigin.DEFINED_LOCALLY ); } @Test public void testSuccessfulInterpolation() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "message interpolation successful"; String actual = interpolator.interpolate( "{simple.key}", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "message interpolation successful message interpolation successful"; actual = interpolator.interpolate( "{simple.key} {simple.key}", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "The message interpolation successful completed"; actual = interpolator.interpolate( "The {simple.key} completed", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "{{simple.key}}"; actual = interpolator.interpolate( "{{simple.key}}", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testMessageLiterals() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "{"; String actual = interpolator.interpolate( "\\{", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "}"; actual = interpolator.interpolate( "\\}", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "\\"; actual = interpolator.interpolate( "\\", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testUnSuccessfulInterpolation() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "foo"; // missing {} String actual = interpolator.interpolate( "foo", context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "#{foo {}"; actual = interpolator.interpolate( "#{foo {}", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testUnknownTokenInterpolation() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "{bar}"; // unknown token {} String actual = interpolator.interpolate( "{bar}", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testKeyWithDashes() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "message interpolation successful"; // unknown token {} String actual = interpolator.interpolate( "{key-with-dashes}", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testKeyWithSpaces() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "message interpolation successful"; // unknown token {} String actual = interpolator.interpolate( "{key with spaces}", context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testDefaultInterpolation() { interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "may not be null"; String actual = interpolator.interpolate( notNull.message(), context ); assertEquals( actual, expected, "Wrong substitution" ); expected = "size must be between 0 and 2147483647"; // unknown token {} context = new MessageInterpolatorContext( sizeDescriptor, null ); actual = interpolator.interpolate( size.message(), context ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testMessageInterpolationWithLocale() { interpolator = new ResourceBundleMessageInterpolator(); String expected = "kann nicht null sein"; MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String actual = interpolator.interpolate( notNull.message(), context, Locale.GERMAN ); assertEquals( actual, expected, "Wrong substitution" ); } @Test public void testUserResourceBundle() { interpolator = new ResourceBundleMessageInterpolator(); MessageInterpolator.Context context = new MessageInterpolatorContext( notNullDescriptor, null ); String expected = "no puede ser null"; String actual = interpolator.interpolate( notNull.message(), context, new Locale( "es", "ES" ) ); assertEquals( actual, expected, "Wrong substitution" ); } /** * HV-102 */ @Test public void testRecursiveMessageInterpolation() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Max.class ); descriptor.setValue( "message", "{replace.in.user.bundle1}" ); descriptor.setValue( "value", 10l ); Max max = AnnotationFactory.create( descriptor ); ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( max, new ConstraintHelper(), java.lang.annotation.ElementType.FIELD, ConstraintOrigin.DEFINED_LOCALLY ); interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( constraintDescriptor, null ); String expected = "{replace.in.default.bundle2}"; String actual = interpolator.interpolate( max.message(), context ); assertEquals( actual, expected, "Within default bundle replacement parameter evaluation should not be recursive!" ); } /** * HV-182 */ @Test public void testCorrectMessageInterpolationIfParameterCannotBeReplaced() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Max.class ); String message = "Message should stay unchanged since {fubar} is not replaceable"; descriptor.setValue( "message", message ); descriptor.setValue( "value", 10l ); Max max = AnnotationFactory.create( descriptor ); ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( max, new ConstraintHelper(), java.lang.annotation.ElementType.FIELD, ConstraintOrigin.DEFINED_LOCALLY ); interpolator = new ResourceBundleMessageInterpolator( new TestResourceBundle() ); MessageInterpolator.Context context = new MessageInterpolatorContext( constraintDescriptor, null ); String actual = interpolator.interpolate( max.message(), context ); assertEquals( actual, message, "The message should not have changed." ); } /** * A dummy resource bundle which can be passed to the constructor of ResourceBundleMessageInterpolator to replace * the user specified resource bundle. */ class TestResourceBundle extends ResourceBundle implements Enumeration { private Map testResources; Iterator iter; public TestResourceBundle() { testResources = new HashMap(); // add some test messages testResources.put( "simple.key", "message interpolation successful" ); testResources.put( "key-with-dashes", "message interpolation successful" ); testResources.put( "key with spaces", "message interpolation successful" ); testResources.put( "replace.in.user.bundle1", "{replace.in.user.bundle2}" ); testResources.put( "replace.in.user.bundle2", "{replace.in.default.bundle1}" ); iter = testResources.keySet().iterator(); } public Object handleGetObject(String key) { return testResources.get( key ); } public Enumeration getKeys() { return this; } public boolean hasMoreElements() { return iter.hasNext(); } public String nextElement() { if ( hasMoreElements() ) { return iter.next(); } else { throw new NoSuchElementException(); } } } } ././@LongLink0000000000000000000000000000025200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/messageinterpolation/MessageInterpolationWithDefaultBundleTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000730111274520070033445 0ustar twernertwerner// $Id:$ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.messageinterpolation; import java.util.Locale; import java.util.Set; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.Validator; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.engine.ResourceBundleMessageInterpolator; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class MessageInterpolationWithDefaultBundleTest { private Locale defaultLocale; @BeforeClass public void storeDefaultLocale() { defaultLocale = Locale.getDefault(); } @AfterClass public void restoreDefaultLocale() { Locale.setDefault( defaultLocale ); } /** * HV-268 */ @Test public void testEmailAndRangeMessageEnglishLocale() { Locale.setDefault( Locale.ENGLISH ); Configuration config = TestUtil.getConfiguration(); config.messageInterpolator( new ResourceBundleMessageInterpolator() ); Validator validator = config.buildValidatorFactory().getValidator(); User user = new User(); user.setEmail( "foo" ); user.setAge( 16 ); Set> constraintViolations = validator.validate( user ); assertNumberOfViolations( constraintViolations, 2 ); assertCorrectConstraintViolationMessages( constraintViolations, "not a well-formed email address", "must be between 18 and 21" ); } /** * HV-268 */ @Test public void testEmailAndRangeMessageGermanLocale() { Locale.setDefault( Locale.GERMAN ); Configuration config = TestUtil.getConfiguration(); config.messageInterpolator( new ResourceBundleMessageInterpolator() ); Validator validator = config.buildValidatorFactory().getValidator(); User user = new User(); user.setEmail( "foo" ); user.setAge( 16 ); Set> constraintViolations = validator.validate( user ); assertNumberOfViolations( constraintViolations, 2 ); assertCorrectConstraintViolationMessages( constraintViolations, "keine g\u00FCltige E-Mail-Adresse", "muss zwischen 18 und 21 liegen" ); } /** * HV-268 */ @Test public void testEmailAndRangeMessageFrenchLocale() { Locale.setDefault( Locale.FRENCH ); Configuration config = TestUtil.getConfiguration(); config.messageInterpolator( new ResourceBundleMessageInterpolator() ); Validator validator = config.buildValidatorFactory().getValidator(); User user = new User(); user.setEmail( "foo" ); user.setAge( 16 ); Set> constraintViolations = validator.validate( user ); assertNumberOfViolations( constraintViolations, 2 ); assertCorrectConstraintViolationMessages( constraintViolations, "Address email mal form\u00E9e", "doit \u00EAtre entre 18 et 21" ); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110336033433 5ustar twernertwerner././@LongLink0000000000000000000000000000023500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/CachedTraversableResolverTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000001073311262172500033446 0ustar twernertwerner// $Id: CachedTraversableResolverTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.traversableresolver; import java.lang.annotation.ElementType; import java.util.HashSet; import java.util.Set; import javax.validation.Configuration; import javax.validation.TraversableResolver; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.Path; import javax.validation.groups.Default; import static org.testng.Assert.fail; import org.testng.annotations.Test; /** * @author Emmanuel Bernard */ //this test is specific to Hibernate Validator public class CachedTraversableResolverTest { @Test public void testCache() { TraversableResolver resolver = new AskOnceTR(); Configuration config = (Configuration) Validation.byDefaultProvider() .configure() .traversableResolver( resolver ); ValidatorFactory factory = config.buildValidatorFactory(); Suit suit = new Suit(); suit.setTrousers( new Trousers() ); suit.setJacket( new Jacket() ); suit.setSize( 3333 ); suit.getTrousers().setLength( 32321 ); suit.getJacket().setWidth( 432432 ); Validator v = factory.getValidator(); try { v.validate( suit, Default.class, Cloth.class ); } catch ( IllegalStateException e ) { fail( "Traversable Called several times for a given object" ); } v = factory.usingContext().traversableResolver( new AskOnceTR() ).getValidator(); try { v.validateProperty( suit, "size", Default.class, Cloth.class ); } catch ( IllegalStateException e ) { fail( "Traversable Called several times for a given object" ); } v = factory.usingContext().traversableResolver( new AskOnceTR() ).getValidator(); try { v.validateValue( Suit.class, "size", 2, Default.class, Cloth.class ); } catch ( IllegalStateException e ) { fail( "Traversable Called several times for a given object" ); } } private static class AskOnceTR implements TraversableResolver { private Set askedReach = new HashSet(); private Set askedCascade = new HashSet(); private boolean isTraversable(Set asked, Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { Holder h = new Holder( traversableObject, traversableProperty ); if ( asked.contains( h ) ) { throw new IllegalStateException( "Called twice" ); } asked.add( h ); return true; } public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return isTraversable( askedReach, traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return isTraversable( askedCascade, traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } public static class Holder { Object NULL = new Object(); Object to; Path.Node tp; public Holder(Object traversableObject, Path.Node traversableProperty) { to = traversableObject == null ? NULL : traversableObject; tp = traversableProperty; } @Override public int hashCode() { return to.hashCode() + tp.hashCode(); } @Override public boolean equals(Object obj) { if ( !( obj instanceof Holder ) ) { return false; } Holder that = ( Holder ) obj; return to != NULL && to == that.to && tp.equals( that.tp ); } } } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/Trousers.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000244311262172500033445 0ustar twernertwerner// $Id: Trousers.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.traversableresolver; import javax.validation.constraints.Min; import javax.validation.constraints.Max; import javax.validation.groups.Default; /** * @author Emmanuel Bernard */ public class Trousers { @Min(value=70, groups = {Default.class, Cloth.class}) @Max(value=220) private Integer length; public Integer getLength() { return length; } public void setLength(Integer length) { this.length = length; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/Jacket.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000220211262172500033436 0ustar twernertwerner// $Id: Jacket.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.traversableresolver; import javax.validation.constraints.Max; /** * @author Emmanuel Bernard */ public class Jacket { Integer width; @Max(30) public Integer getWidth() { return width; } public void setWidth(Integer width) { this.width = width; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/Cloth.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000171511262172500033446 0ustar twernertwerner// $Id: Cloth.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.traversableresolver; /** * @author Emmanuel Bernard */ public interface Cloth { } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/traversableresolver/Suit.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000326711262172500033452 0ustar twernertwerner// $Id: Suit.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.traversableresolver; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.Valid; import javax.validation.GroupSequence; import javax.validation.groups.Default; /** * @author Emmanuel Bernard */ @GroupSequence( {Suit.class, Cloth.class }) public class Suit { @Max(value=50, groups = { Default.class, Cloth.class}) @Min(1) private Integer size; @Valid private Trousers trousers; private Jacket jacket; public Trousers getTrousers() { return trousers; } public void setTrousers(Trousers trousers) { this.trousers = trousers; } @Valid public Jacket getJacket() { return jacket; } public void setJacket(Jacket jacket) { this.jacket = jacket; } public Integer getSize() { return size; } public void setSize(Integer size) { this.size = size; } } ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/proxy/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000755000175000017500000000000011402110334033431 5ustar twernertwerner././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/proxy/A.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000206311271345076033455 0ustar twernertwerner// $Id: A.java 17838 2009-10-26 16:11:42Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.proxy; import javax.validation.constraints.Min; import javax.validation.constraints.Size; interface A { @Min(5) public Integer getInteger(); @Size(min = 2) public String getString(); }././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/proxy/B.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000176011271345076033460 0ustar twernertwerner// $Id: B.java 17838 2009-10-26 16:11:42Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.proxy; import javax.validation.constraints.Min; import javax.validation.constraints.Size; public interface B extends A { }././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/proxy/ProxyTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000530111271345076033453 0ustar twernertwerner// $Id: ProxyTest.java 17838 2009-10-26 16:11:42Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * See HV-257 * * @author Hardy Ferentschik */ public class ProxyTest { @Test public void testValidateA() { InvocationHandler handler = new CustomInvocationHandler( "some object" ); A a = ( A ) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[] { A.class }, handler ); assertEquals( Integer.valueOf( 0 ), a.getInteger() ); Validator validator = TestUtil.getValidator(); Set> violations = validator.validate( a ); assertNumberOfViolations( violations, 2 ); } @Test public void testValidateB() { InvocationHandler handler = new CustomInvocationHandler( "some object" ); B b = ( B ) Proxy.newProxyInstance( getClass().getClassLoader(), new Class[] { B.class }, handler ); assertEquals( Integer.valueOf( 0 ), b.getInteger() ); Validator validator = TestUtil.getValidator(); Set> violations = validator.validate( b ); assertNumberOfViolations( violations, 2 ); } private class CustomInvocationHandler implements InvocationHandler { private Object o; public CustomInvocationHandler(Object o) { this.o = o; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ( method.getName().equals( "getInteger" ) ) { method.setAccessible( true ); return 0; } if ( method.getName().equals( "getString" ) ) { return "a"; } return method.invoke( o, args ); } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engine/PathImplTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/engin0000644000175000017500000000675511262172500033457 0ustar twernertwerner// $Id: PathImplTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.util.Iterator; import javax.validation.Path; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class PathImplTest { @Test public void testParsing() { String property = "order[3].deliveryAddress.addressline[1]"; Path path = PathImpl.createPathFromString( property ); Iterator propIter = path.iterator(); assertTrue( propIter.hasNext() ); Path.Node elem = propIter.next(); assertEquals( "order", elem.getName() ); assertTrue( elem.isInIterable() ); assertEquals( new Integer( 3 ), elem.getIndex() ); assertTrue( propIter.hasNext() ); elem = propIter.next(); assertEquals( "deliveryAddress", elem.getName() ); assertFalse( elem.isInIterable() ); assertEquals( null, elem.getIndex() ); assertTrue( propIter.hasNext() ); elem = propIter.next(); assertEquals( "addressline", elem.getName() ); assertTrue( elem.isInIterable() ); assertEquals( new Integer( 1 ), elem.getIndex() ); assertFalse( propIter.hasNext() ); } @Test public void testParseMapBasedProperty() { String property = "order[foo].deliveryAddress"; Path path = PathImpl.createPathFromString( property ); Iterator propIter = path.iterator(); assertTrue( propIter.hasNext() ); Path.Node elem = propIter.next(); assertEquals( "order", elem.getName() ); assertTrue( elem.isInIterable() ); assertEquals( "foo", elem.getKey() ); assertTrue( propIter.hasNext() ); elem = propIter.next(); assertEquals( "deliveryAddress", elem.getName() ); assertFalse( elem.isInIterable() ); assertEquals( null, elem.getIndex() ); assertFalse( propIter.hasNext() ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNull() { PathImpl.createPathFromString( null ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testUnbalancedBraces() { PathImpl.createPathFromString( "foo[.bar" ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testIndexInMiddleOfProperty() { PathImpl.createPathFromString( "f[1]oo.bar" ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testTrailingPathSeperator() { PathImpl.createPathFromString( "foo.bar." ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testLeadingPathSeperator() { PathImpl.createPathFromString( ".foo.bar" ); } @Test public void testEmptyString() { Path path = PathImpl.createPathFromString( "" ); assertTrue( path.iterator().hasNext() ); } } ././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/bootstrap/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/boots0000755000175000017500000000000011402110344033460 5ustar twernertwerner././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/bootstrap/ValidationTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/boots0000644000175000017500000001051011262172500033465 0ustar twernertwerner// $Id: ValidationTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.bootstrap; import java.util.Set; import javax.validation.Configuration; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.ConstraintValidatorFactory; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.constraints.impl.NotNullValidator; import org.hibernate.validator.engine.ConfigurationImpl; import org.hibernate.validator.engine.ConstraintValidatorFactoryImpl; import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.engine.ValidatorFactoryImpl; import org.hibernate.validator.HibernateValidator; /** * Tests the Bean Validation bootstrapping. * * @author Hardy Ferentschik */ public class ValidationTest { @Test public void testBootstrapAsServiceWithBuilder() { HibernateValidatorConfiguration configuration = Validation .byProvider( HibernateValidator.class ) .configure(); assertDefaultBuilderAndFactory( configuration ); } @Test public void testBootstrapAsServiceDefault() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); assertDefaultFactory( factory ); } @Test public void testCustomConstraintValidatorFactory() { Configuration configuration = Validation.byDefaultProvider().configure(); assertDefaultBuilderAndFactory( configuration ); ValidatorFactory factory = configuration.buildValidatorFactory(); Validator validator = factory.getValidator(); Customer customer = new Customer(); customer.setFirstName( "John" ); Set> constraintViolations = validator.validate( customer ); assertEquals( constraintViolations.size(), 1, "Wrong number of constraints" ); ConstraintViolation constraintViolation = constraintViolations.iterator().next(); assertEquals( "may not be empty", constraintViolation.getMessage(), "Wrong message" ); // get a new factory using a custom configuration configuration = Validation.byDefaultProvider().configure(); configuration.constraintValidatorFactory( new ConstraintValidatorFactory() { public > T getInstance(Class key) { if ( key == NotNullValidator.class ) { return ( T ) new BadlyBehavedNotNullConstraintValidator(); } return new ConstraintValidatorFactoryImpl().getInstance( key ); } } ); factory = configuration.buildValidatorFactory(); validator = factory.getValidator(); constraintViolations = validator.validate( customer ); assertEquals( constraintViolations.size(), 0, "Wrong number of constraints" ); } private void assertDefaultBuilderAndFactory(Configuration configuration) { assertNotNull( configuration ); assertTrue( configuration instanceof ConfigurationImpl ); ValidatorFactory factory = configuration.buildValidatorFactory(); assertDefaultFactory( factory ); } private void assertDefaultFactory(ValidatorFactory factory) { assertNotNull( factory ); assertTrue( factory instanceof ValidatorFactoryImpl ); } class BadlyBehavedNotNullConstraintValidator extends NotNullValidator { @Override public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { return true; } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/bootstrap/Order.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/boots0000644000175000017500000000223711262172500033474 0ustar twernertwerner// $Id: Order.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.bootstrap; import javax.validation.constraints.NotNull; /** * @author Hardy Ferentschik */ public class Order { @NotNull Integer orderNumber; public Integer getOrderNumber() { return orderNumber; } public void setOrderNumber(Integer orderNumber) { this.orderNumber = orderNumber; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/bootstrap/Customer.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/boots0000644000175000017500000000337011262172500033473 0ustar twernertwerner// $Id: Customer.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.bootstrap; import java.util.HashSet; import java.util.Set; import javax.validation.Valid; import org.hibernate.validator.constraints.NotEmpty; /** * @author Hardy Ferentschik */ public class Customer { @NotEmpty private String firstName; private String middleName; @NotEmpty private String lastName; @Valid private Set orders = new HashSet(); public void addOrder(Order order) { orders.add( order ); } public Set getOrders() { return orders; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000755000175000017500000000000011402110345033367 5ustar twernertwerner././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/ValidatorTypeTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000342011265402406033401 0ustar twernertwerner// $Id: ValidatorTypeTest.java 17747 2009-10-14 17:06:14Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.validation.ConstraintValidator; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNull; import org.testng.annotations.Test; /** * Tests for message resolution. * * @author Emmanuel Bernard */ public class ValidatorTypeTest { @Test public void testTypeDiscovery() { List>> validators = new ArrayList>>(); validators.add( PositiveConstraintValidator.class ); Map>> validatorsTypes = ValidatorTypeHelper .getValidatorsTypes( validators ); assertEquals( validatorsTypes.get( Integer.class ), PositiveConstraintValidator.class ); assertNull( validatorsTypes.get( String.class ) ); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/TestUtil.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000002442711274325274033422 0ustar twernertwerner// $Id: TestUtil.java 17911 2009-11-04 16:24:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.io.InputStream; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.Path; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.ElementDescriptor; import javax.validation.metadata.PropertyDescriptor; import org.slf4j.Logger; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.FileAssert.fail; import org.hibernate.validator.HibernateValidator; import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.engine.PathImpl; /** * Tests for the ReflectionHelper. * * @author Hardy Ferentschik */ public class TestUtil { private static final Logger log = LoggerFactory.make(); private static Validator hibernateValidator; private TestUtil() { } public static Validator getValidator() { if ( hibernateValidator == null ) { Configuration configuration = getConfiguration(); hibernateValidator = configuration.buildValidatorFactory().getValidator(); } return hibernateValidator; } public static Configuration getConfiguration() { return Validation.byProvider( HibernateValidator.class ).configure(); } /** * @param path The path to the xml file which should server as validation.xml for the returned * Validator. * * @return A Validator instance which respects the configuration specified in the file with the path * path. */ public static Validator getValidatorWithCustomConfiguration(String path) { Thread.currentThread().setContextClassLoader( new CustomValidationXmlClassLoader( path ) ); HibernateValidatorConfiguration configuration = Validation .byProvider( HibernateValidator.class ) .configure(); return configuration.buildValidatorFactory().getValidator(); } /** * @return A Validator instance which ignores validation.xml. */ public static Validator getValidatorIgnoringValidationXml() { Thread.currentThread().setContextClassLoader( new IgnoringValidationXmlClassLoader() ); HibernateValidatorConfiguration configuration = Validation .byProvider( HibernateValidator.class ) .configure(); return configuration.buildValidatorFactory().getValidator(); } public static ConstraintDescriptor getSingleConstraintDescriptorFor(Class clazz, String property) { Set> constraintDescriptors = getConstraintDescriptorsFor( clazz, property ); assertTrue( constraintDescriptors.size() == 1, "This method should only be used when there is a single constraint" ); return constraintDescriptors.iterator().next(); } public static PropertyDescriptor getPropertyDescriptor(Class clazz, String property) { Validator validator = getValidator(); return validator.getConstraintsForClass( clazz ).getConstraintsForProperty( property ); } public static Set> getConstraintDescriptorsFor(Class clazz, String property) { ElementDescriptor elementDescriptor = getPropertyDescriptor( clazz, property ); return elementDescriptor.getConstraintDescriptors(); } public static void assertCorrectConstraintViolationMessages(Set> violations, String... messages) { List actualMessages = new ArrayList(); for ( ConstraintViolation violation : violations ) { actualMessages.add( violation.getMessage() ); } assertTrue( actualMessages.size() == messages.length, "Wrong number or error messages" ); for ( String expectedMessage : messages ) { assertTrue( actualMessages.contains( expectedMessage ), "The message '" + expectedMessage + "' should have been in the list of actual messages: " + actualMessages ); actualMessages.remove( expectedMessage ); } assertTrue( actualMessages.isEmpty(), "Actual messages contained more messages as specidied expected messages" ); } public static void assertCorrectConstraintTypes(Set> violations, Class... expectedConsraintTypes) { List actualConstraintTypes = new ArrayList(); for ( ConstraintViolation violation : violations ) { actualConstraintTypes.add( ( ( Annotation ) violation.getConstraintDescriptor().getAnnotation() ).annotationType().getName() ); } assertEquals( expectedConsraintTypes.length, actualConstraintTypes.size(), "Wrong number of constraint types." ); for ( Class expectedConstraintType : expectedConsraintTypes ) { assertTrue( actualConstraintTypes.contains( expectedConstraintType.getName() ), "The constraint type " + expectedConstraintType.getName() + " should have been violated." ); } } public static void assertCorrectPropertyPaths(Set> violations, String... propertyPaths) { List propertyPathsOfViolations = new ArrayList(); for ( ConstraintViolation violation : violations ) { propertyPathsOfViolations.add( violation.getPropertyPath() ); } for ( String propertyPath : propertyPaths ) { Path expectedPath = PathImpl.createPathFromString( propertyPath ); boolean containsPath = false; for ( Path actualPath : propertyPathsOfViolations ) { if ( assertEqualPaths( expectedPath, actualPath ) ) { containsPath = true; break; } } if ( !containsPath ) { fail( expectedPath + " is not in the list of path instances contained in the actual constraint violations: " + propertyPathsOfViolations ); } } } public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class rootBean, Object invalidValue, String propertyPath, Class leafBean) { assertEquals( violation.getLeafBean().getClass(), leafBean, "Wrong leaf bean type" ); assertConstraintViolation( violation, errorMessage, rootBean, invalidValue, propertyPath ); } public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class rootBean, Object invalidValue, String propertyPath) { assertEquals( violation.getPropertyPath(), PathImpl.createPathFromString( propertyPath ), "Wrong propertyPath" ); assertConstraintViolation( violation, errorMessage, rootBean, invalidValue ); } public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class rootBean, Object invalidValue) { assertEquals( violation.getInvalidValue(), invalidValue, "Wrong invalid value" ); assertConstraintViolation( violation, errorMessage, rootBean ); } public static void assertConstraintViolation(ConstraintViolation violation, String errorMessage, Class rootBean) { assertEquals( violation.getRootBean().getClass(), rootBean, "Wrong root bean type" ); assertConstraintViolation( violation, errorMessage ); } public static void assertConstraintViolation(ConstraintViolation violation, String message) { assertEquals( violation.getMessage(), message, "Wrong message" ); } public static void assertNumberOfViolations(Set violations, int expectedViolations) { assertEquals( violations.size(), expectedViolations, "Wrong number of constraint violations" ); } public static boolean assertEqualPaths(Path p1, Path p2) { Iterator p1Iterator = p1.iterator(); Iterator p2Iterator = p2.iterator(); while ( p1Iterator.hasNext() ) { Path.Node p1Node = p1Iterator.next(); if ( !p2Iterator.hasNext() ) { return false; } Path.Node p2Node = p2Iterator.next(); // do the comparison on the node values if ( p2Node.getName() == null ) { if ( p1Node.getName() != null ) { return false; } } else if ( !p2Node.getName().equals( p1Node.getName() ) ) { return false; } if ( p2Node.isInIterable() != p1Node.isInIterable() ) { return false; } if ( p2Node.getIndex() == null ) { if ( p1Node.getIndex() != null ) { return false; } } else if ( !p2Node.getIndex().equals( p1Node.getIndex() ) ) { return false; } if ( p2Node.getKey() == null ) { if ( p1Node.getKey() != null ) { return false; } } else if ( !p2Node.getKey().equals( p1Node.getKey() ) ) { return false; } } return !p2Iterator.hasNext(); } private static class CustomValidationXmlClassLoader extends ClassLoader { private final String customValidationXmlPath; CustomValidationXmlClassLoader(String pathToCustomValidationXml) { super( CustomValidationXmlClassLoader.class.getClassLoader() ); customValidationXmlPath = pathToCustomValidationXml; } public InputStream getResourceAsStream(String path) { String finalPath = path; if ( "META-INF/validation.xml".equals( path ) ) { log.info( "Using {} as validation.xml", customValidationXmlPath ); finalPath = customValidationXmlPath; } return super.getResourceAsStream( finalPath ); } } private static class IgnoringValidationXmlClassLoader extends ClassLoader { IgnoringValidationXmlClassLoader() { super( IgnoringValidationXmlClassLoader.class.getClassLoader() ); } public InputStream getResourceAsStream(String path) { if ( "META-INF/validation.xml".equals( path ) ) { log.info( "Ignoring call to load validation.xml" ); return null; } return super.getResourceAsStream( path ); } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/annotationfactory/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000755000175000017500000000000011402110345033367 5ustar twernertwerner././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/annotationfactory/AnnotationFactoryTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000415211262172500033400 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util.annotationfactory; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class AnnotationFactoryTest { @Test public void createAnnotationProxy() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Size.class ); descriptor.setValue( "min", 5 ); descriptor.setValue( "max", 10 ); Size size = AnnotationFactory.create( descriptor ); assertEquals( size.min(), 5, "Wrong parameter value" ); assertEquals( size.max(), 10, "Wrong parameter value" ); } @Test(expectedExceptions = IllegalArgumentException.class) public void createAnnotationProxyMissingRequiredParamter() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Pattern.class ); AnnotationFactory.create( descriptor ); } @Test public void createAnnotationProxyWithRequiredParamter() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Pattern.class ); descriptor.setValue( "regexp", ".*" ); Pattern pattern = AnnotationFactory.create( descriptor ); assertEquals( ".*", pattern.regexp(), "Wrong parameter value" ); } } ././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/Positive.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000310111262172500033371 0ustar twernertwerner// $Id: Positive.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.annotation.Target; import java.lang.annotation.Retention; import java.lang.annotation.Documented; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import javax.validation.Constraint; /** * @author Emmanuel Bernard */ @Constraint( validatedBy = { PositiveConstraintValidator.class }) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented public @interface Positive { public abstract String message() default "{validation.positive}"; public abstract Class[] groups() default {}; } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/ReflectionHelperTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000001344211262172500033402 0ustar twernertwerner// $Id: ReflectionHelperTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeSet; import javax.validation.Payload; import javax.validation.ValidationException; import javax.validation.constraints.NotNull; import javax.validation.groups.Default; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; /** * Tests for the ReflectionHelper. * * @author Hardy Ferentschik */ public class ReflectionHelperTest { @Test public void testIsIterable() throws Exception { Type type = TestTypes.class.getField( "stringList" ).getGenericType(); assertTrue( ReflectionHelper.isIterable( type ) ); assertTrue( ReflectionHelper.isIterable( TreeSet.class ) ); assertTrue( ReflectionHelper.isIterable( List.class ) ); assertTrue( ReflectionHelper.isIterable( HashSet.class ) ); assertTrue( ReflectionHelper.isIterable( Iterable.class ) ); assertTrue( ReflectionHelper.isIterable( Collection.class ) ); assertFalse( ReflectionHelper.isIterable( null ) ); assertFalse( ReflectionHelper.isIterable( Object.class ) ); } @Test public void testIsMap() throws Exception { assertTrue( ReflectionHelper.isMap( Map.class ) ); assertTrue( ReflectionHelper.isMap( SortedMap.class ) ); Type type = TestTypes.class.getField( "objectMap" ).getGenericType(); assertTrue( ReflectionHelper.isMap( type ) ); assertFalse( ReflectionHelper.isMap( null ) ); assertFalse( ReflectionHelper.isMap( Object.class ) ); } @Test public void testGetIndexedType() throws Exception { Type type = TestTypes.class.getField( "stringList" ).getGenericType(); assertEquals( String.class, ReflectionHelper.getIndexedType( type ) ); type = TestTypes.class.getField( "objectMap" ).getGenericType(); assertEquals( Object.class, ReflectionHelper.getIndexedType( type ) ); type = TestTypes.class.getField( "stringArray" ).getGenericType(); assertEquals( String.class, ReflectionHelper.getIndexedType( type ) ); } @Test public void testGetIndexedValueForMap() { Map map = new HashMap(); Object testObject = new Object(); String key = "key"; map.put( key, testObject ); Object value = ReflectionHelper.getMappedValue( map, key ); assertEquals( value, testObject, "We should be able to retrieve the indexed object" ); value = ReflectionHelper.getMappedValue( map, "foo" ); assertNull( value, "A non existent index should return the null value" ); value = ReflectionHelper.getMappedValue( map, "2" ); assertNull( value, "A non existent index should return the null value" ); } @Test public void testGetIndexedValueForList() { List list = new ArrayList(); Object testObject = new Object(); list.add( testObject ); Object value = ReflectionHelper.getIndexedValue( list, 0 ); assertEquals( value, testObject, "We should be able to retrieve the indexed object" ); value = ReflectionHelper.getIndexedValue( list, 2 ); assertNull( value, "A non existent index should return the null value" ); } @Test public void testGetIndexedValueForNull() { Object value = ReflectionHelper.getIndexedValue( null, 0 ); assertNull( value ); } @Test public void testGetMessageParameter() { NotNull testAnnotation = new NotNull() { public String message() { return "test"; } public Class[] groups() { return new Class[] { Default.class }; } public Class[] payload() { @SuppressWarnings("unchecked") Class[] classes = new Class[] { }; return classes; } public Class annotationType() { return this.getClass(); } }; String message = ReflectionHelper.getAnnotationParameter( testAnnotation, "message", String.class ); assertEquals( "test", message, "Wrong message" ); Class[] group = ReflectionHelper.getAnnotationParameter( testAnnotation, "groups", Class[].class ); assertEquals( group[0], Default.class, "Wrong message" ); try { ReflectionHelper.getAnnotationParameter( testAnnotation, "message", Integer.class ); fail(); } catch ( ValidationException e ) { assertTrue( e.getMessage().startsWith( "Wrong parameter type." ), "Wrong exception message" ); } try { ReflectionHelper.getAnnotationParameter( testAnnotation, "foo", Integer.class ); fail(); } catch ( ValidationException e ) { assertTrue( e.getMessage().startsWith( "The specified annotation defines no parameter" ), "Wrong exception message" ); } } public class TestTypes { public List stringList; public Map objectMap; public String[] stringArray; } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/PositiveConstraintValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000216711262172500033404 0ustar twernertwerner// $Id: PositiveConstraintValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; /** * @author Emmanuel Bernard */ public class PositiveConstraintValidator extends BoundariesConstraintValidator { public void initialize(Positive constraintAnnotation) { super.initialize( 0, Integer.MAX_VALUE ); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/BoundariesConstraintValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000270211262172500033377 0ustar twernertwerner// $Id: BoundariesConstraintValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.annotation.Annotation; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Emmanuel Bernard */ public abstract class BoundariesConstraintValidator implements ConstraintValidator { private int low; private int high; protected void initialize(int low, int high) { this.low = low; this.high = high; } public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) { return value >= low && value <= high; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/IdentitySetTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/util/0000644000175000017500000000375611262172500033411 0ustar twernertwerner// $Id: IdentitySetTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.util.HashSet; import java.util.Set; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class IdentitySetTest { @SuppressWarnings("unchecked") @Test public void testAddIdenticalInstance() { Set identitySet = new IdentitySet(); Set hashSet = new HashSet(); assertTrue( identitySet.size() == 0 ); assertTrue( hashSet.size() == 0 ); Object o1 = new Object() { int counter = 0; public int hashCode() { return counter++; } public boolean equals() { return false; } }; identitySet.add( o1 ); hashSet.add( o1 ); assertTrue( identitySet.size() == 1 ); assertTrue( hashSet.size() == 1 ); identitySet.add( o1 ); hashSet.add( o1 ); assertTrue( identitySet.size() == 1 ); assertTrue( hashSet.size() == 2 ); Object o2 = new Object() { int counter = 0; public int hashCode() { return counter++; } public boolean equals() { return false; } }; identitySet.add( o2 ); hashSet.add( o2 ); assertTrue( identitySet.size() == 2 ); assertTrue( hashSet.size() == 3 ); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/ValidationMessages.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/Valid0000644000175000017500000000463411262172500033410 0ustar twernertwerner// $Id: ValidationMessages.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.PropertyResourceBundle; import java.util.ResourceBundle; import org.slf4j.Logger; import org.hibernate.validator.util.LoggerFactory; /** * @author Hardy Ferentschik */ public class ValidationMessages extends ResourceBundle { private static final Logger log = LoggerFactory.make(); private static final String DEFAULT_PROPERTIES_FILE_NAME = "/org/hibernate/validator/ValidationMessages.properties"; private Map messages = new HashMap(); public ValidationMessages() throws Exception { log.info( "For test purposes are we proxying the buildin messages!" ); addTestPropertiesToBundle(); log.info( "Adding the following properties to default properties {}", messages ); loadDefaultValidationProperties(); } private void addTestPropertiesToBundle() { messages.put( "replace.in.default.bundle1", "{replace.in.default.bundle2}" ); messages.put( "replace.in.default.bundle2", "foobar" ); } private void loadDefaultValidationProperties() throws IOException { InputStream in = this.getClass() .getResourceAsStream( DEFAULT_PROPERTIES_FILE_NAME ); PropertyResourceBundle propertyBundle = new PropertyResourceBundle( in ); setParent( propertyBundle ); } protected Object handleGetObject(String key) { return messages.get( key ); } public Enumeration getKeys() { throw new RuntimeException( "Not needed for testing purposes." ); } } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000755000175000017500000000000011402110330033417 5ustar twernertwerner././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/ConstraintHelperTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000555011262172500033441 0ustar twernertwerner// $Id: ConstraintHelperTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.util.List; import javax.validation.constraints.NotNull; import javax.validation.constraints.Pattern; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.util.SetAccessibility; /** * @author Hardy Ferentschik */ public class ConstraintHelperTest { private static ConstraintHelper constraintHelper; @BeforeClass public static void init() { constraintHelper = new ConstraintHelper(); } @Test public void testGetMultiValueConstraints() throws Exception { Engine engine = new Engine(); Field[] fields = engine.getClass().getDeclaredFields(); assertNotNull( fields ); assertTrue( fields.length == 1 ); setAccessibility( fields[0] ); Annotation annotation = fields[0].getAnnotation( Pattern.List.class ); assertNotNull( annotation ); List multiValueConstraintAnnotations = constraintHelper.getMultiValueConstraints( annotation ); assertTrue( multiValueConstraintAnnotations.size() == 2, "There should be two constraint annotations" ); assertTrue( multiValueConstraintAnnotations.get( 0 ) instanceof Pattern, "Wrong constraint annotation" ); assertTrue( multiValueConstraintAnnotations.get( 1 ) instanceof Pattern, "Wrong constraint annotation" ); Order order = new Order(); fields = order.getClass().getDeclaredFields(); assertNotNull( fields ); assertTrue( fields.length == 1 ); setAccessibility( fields[0] ); annotation = fields[0].getAnnotation( NotNull.class ); assertNotNull( annotation ); multiValueConstraintAnnotations = constraintHelper.getMultiValueConstraints( annotation ); assertTrue( multiValueConstraintAnnotations.size() == 0, "There should be no constraint annotations" ); } void setAccessibility(Member member) { SetAccessibility.action( member ).run(); } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/ElementDescriptorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000551711262172500033444 0ustar twernertwerner// $Id: ElementDescriptorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.util.Set; import javax.validation.Validator; import javax.validation.metadata.BeanDescriptor; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.ElementDescriptor; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; /** * @author Hardy Ferentschik */ public class ElementDescriptorTest { @Test public void testGetTypeForConstrainedBean() { Validator validator = TestUtil.getValidator(); BeanDescriptor beanDescriptor = validator.getConstraintsForClass( Customer.class ); assertEquals( beanDescriptor.getElementClass(), Customer.class, "Wrong type." ); } @Test public void testGetTypeForConstrainedProperty() { ElementDescriptor elementDescriptor = TestUtil.getPropertyDescriptor( Order.class, "orderNumber" ); assertEquals( elementDescriptor.getElementClass(), Integer.class, "Wrong type." ); } /** * HV-95 */ @Test public void testElementDescriptorForProperty() { ElementDescriptor elementDescriptor = TestUtil.getPropertyDescriptor( Order.class, "orderNumber" ); Set> constraintDescriptors = elementDescriptor.getConstraintDescriptors(); assertTrue( constraintDescriptors.size() == 1, "There should be a descriptor" ); } /** * HV-95 */ @Test public void testElementDescriptorImmutable() { ElementDescriptor elementDescriptor = TestUtil.getPropertyDescriptor( Order.class, "orderNumber" ); Set> constraintDescriptors = elementDescriptor.getConstraintDescriptors(); try { constraintDescriptors.add( null ); fail( "Set should be immutable" ); } catch ( UnsupportedOperationException e ) { // success } try { constraintDescriptors.remove( null ); fail( "Set should be immutable" ); } catch ( UnsupportedOperationException e ) { // success } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/Engine.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000262311262172500033437 0ustar twernertwerner// $Id: Engine.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import javax.validation.constraints.Pattern; /** * @author Hardy Ferentschik */ public class Engine { @Pattern.List({ @Pattern(regexp = "^[A-Z0-9-]+$", message = "must contain alphabetical characters only"), @Pattern(regexp = "^....-....-....$", message = "must match ....-....-....") }) private String serialNumber; public String getSerialNumber() { return serialNumber; } public void setSerialNumber(String serialNumber) { this.serialNumber = serialNumber; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/Person.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000223611262172500033437 0ustar twernertwerner// $Id: Person.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import org.hibernate.validator.constraints.NotEmpty; /** * @author Hardy Ferentschik */ public interface Person { @NotEmpty(groups = PersonValidation.class) String getFirstName(); String getMiddleName(); @NotEmpty String getLastName(); public interface PersonValidation { } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/Order.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000231011262172500033430 0ustar twernertwerner// $Id: Order.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import javax.validation.constraints.NotNull; /** * @author Hardy Ferentschik */ public class Order { @NotNull(message = "Order number must be specified") Integer orderNumber; public Integer getOrderNumber() { return orderNumber; } public void setOrderNumber(Integer orderNumber) { this.orderNumber = orderNumber; } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metadata/Customer.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/metad0000644000175000017500000000332111262172500033433 0ustar twernertwerner// $Id: Customer.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.util.ArrayList; import java.util.List; import javax.validation.Valid; /** * @author Hardy Ferentschik */ public class Customer implements Person { private String firstName; private String middleName; private String lastName; @Valid private List orderList = new ArrayList(); public void addOrder(Order order) { orderList.add( order ); } public List getOrderList() { return orderList; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000755000175000017500000000000011402110344033460 5ustar twernertwerner././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Item.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000175711262172500033502 0ustar twernertwerner// $Id: Item.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.Valid; /** * @author Hardy Ferentschik */ class Item { @Valid Interval interval; } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Elevator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000225011262172500033467 0ustar twernertwerner// $Id: Elevator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; /** * @author Hardy Ferentschik */ public class Elevator { @Range(min = -2, max = 50, message = "Invalid floor") private int currentFloor; public int getCurrentFloor() { return currentFloor; } public void setCurrentFloor(int currentFloor) { this.currentFloor = currentFloor; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/ObjectConstraintValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000245311262172500033474 0ustar twernertwerner// $Id: ObjectConstraintValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class ObjectConstraintValidator implements ConstraintValidator { public void initialize(Object annotation) { } public boolean isValid(java.lang.Object value, ConstraintValidatorContext constraintValidatorContext) { return true; } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/ValidatorResolutionTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000001453011262172500033473 0ustar twernertwerner// $Id: ValidatorResolutionTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertConstraintViolation; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class ValidatorResolutionTest { @Test public void testResolutionOfMultipleSizeValidators() { Validator validator = TestUtil.getValidator(); Suburb suburb = new Suburb(); List postcodes = new ArrayList(); postcodes.add( 12345 ); suburb.setIncludedPostCodes( postcodes ); // all values are null and should pass Set> constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 0 ); suburb.setName( "" ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "size must be between 5 and 10", Suburb.class, "", "name" ); suburb.setName( "Hoegsbo" ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 0 ); suburb.addFacility( Suburb.Facility.SHOPPING_MALL, false ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "size must be between 2 and 2", Suburb.class, suburb.getFacilities(), "facilities" ); suburb.addFacility( Suburb.Facility.BUS_TERMINAL, true ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 0 ); suburb.addStreetName( "Sikelsgatan" ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "size must be between 2 and 2147483647", Suburb.class, suburb.getStreetNames(), "streetNames" ); suburb.addStreetName( "Marklandsgatan" ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 0 ); Coordinate[] boundingBox = new Coordinate[3]; boundingBox[0] = new Coordinate( 0l, 0l ); boundingBox[1] = new Coordinate( 0l, 1l ); boundingBox[2] = new Coordinate( 1l, 0l ); suburb.setBoundingBox( boundingBox ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "size must be between 4 and 1000", Suburb.class, suburb.getBoundingBox(), "boundingBox" ); boundingBox = new Coordinate[4]; boundingBox[0] = new Coordinate( 0l, 0l ); boundingBox[1] = new Coordinate( 0l, 1l ); boundingBox[2] = new Coordinate( 1l, 0l ); boundingBox[3] = new Coordinate( 1l, 1l ); suburb.setBoundingBox( boundingBox ); constraintViolations = validator.validate( suburb ); assertNumberOfViolations( constraintViolations, 0 ); } /** * HV-233 */ @Test public void testObjectArraysAndPrimitiveArraysAreSubtypesOfObject() { Validator validator = TestUtil.getValidator(); Foo testEntity = new Foo( new Object[] { }, new int[] { } ); Set> constraintViolations = validator.validate( testEntity ); assertNumberOfViolations( constraintViolations, 0 ); } /** * HV-233 */ @Test public void testObjectArraysAndPrimitiveArraysAreSubtypesOfClonable() { Validator validator = TestUtil.getValidator(); Bar testEntity = new Bar( new Object[] { }, new int[] { } ); Set> constraintViolations = validator.validate( testEntity ); assertNumberOfViolations( constraintViolations, 0 ); } /** * HV-233 */ @Test public void testObjectArraysAndPrimitiveArraysAreSubtypesOfSerializable() { Validator validator = TestUtil.getValidator(); Fubar testEntity = new Fubar( new Object[] { }, new int[] { } ); Set> constraintViolations = validator.validate( testEntity ); assertNumberOfViolations( constraintViolations, 0 ); } /** * HV-233 */ @Test public void testSubTypeArrayIsSubtypeOfSuperTypeArray() { Validator validator = TestUtil.getValidator(); SubTypeEntity testEntity = new SubTypeEntity( new SubType[] { } ); Set> constraintViolations = validator.validate( testEntity ); assertNumberOfViolations( constraintViolations, 0 ); } public class Foo { @Object private Object[] objectArray; @Object private int[] intArray; public Foo(Object[] objectArray, int[] intArray) { this.objectArray = objectArray; this.intArray = intArray; } } public class Bar { @Cloneable private Object[] objectArray; @Cloneable private int[] intArray; public Bar(Object[] objectArray, int[] intArray) { this.objectArray = objectArray; this.intArray = intArray; } } public class Fubar { @Serializable private Object[] objectArray; @Serializable private int[] intArray; public Fubar(Object[] objectArray, int[] intArray) { this.objectArray = objectArray; this.intArray = intArray; } } public class SubTypeEntity { @SuperTypeArray private SubType[] subTypeArray; public SubTypeEntity(SubType[] subTypeArray) { this.subTypeArray = subTypeArray; } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/SubType.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000172111262172500033471 0ustar twernertwerner// $Id: SubType.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; /** * @author Hardy Ferentschik */ public class SubType extends SuperType { } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/SuperType.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000170311262172500033471 0ustar twernertwerner// $Id: SuperType.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; /** * @author Hardy Ferentschik */ public class SuperType { } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/SuperTypeArray.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000333711262172500033476 0ustar twernertwerner// $Id: SuperTypeArray.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * @author Hardy Ferentschik */ @Constraint(validatedBy = { SuperTypeArrayValidator.class }) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented public @interface SuperTypeArray { public abstract String message() default "{org.hibernate.validator.constraints.SuperTypeArray.message}"; public abstract Class[] groups() default { }; public abstract Class[] payload() default { }; } ././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/ClassValidatorWithTypeVariableTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000720611265361201033476 0ustar twernertwerner// $Id: ClassValidatorWithTypeVariableTest.java 17744 2009-10-14 14:38:57Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.util.Date; import java.util.HashSet; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Valid; import javax.validation.Validator; import javax.validation.constraints.NotNull; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertCorrectConstraintTypes; import static org.hibernate.validator.util.TestUtil.assertCorrectPropertyPaths; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * HV-250 */ public class ClassValidatorWithTypeVariableTest { private Validator validator; @BeforeClass public void setUp() { validator = TestUtil.getValidator(); } @Test public void offersNull() { Batch batch = new Batch( null ); Set> violations = validator.validate( batch ); assertNumberOfViolations( violations, 1 ); assertCorrectPropertyPaths( violations, "offers" ); assertCorrectConstraintTypes( violations, NotNull.class ); } @Test public void offerItemNull() { ItemAOffer offer = new ItemAOffer( null ); Set> offers = new HashSet>(); offers.add( offer ); Batch batch = new Batch( offers ); Set> violations = validator.validate( batch ); assertNumberOfViolations( violations, 1 ); assertCorrectPropertyPaths( violations, "offers[].item" ); assertCorrectConstraintTypes( violations, NotNull.class ); } @Test public void offerItemDateNull() { ItemA item = new ItemA( null ); ItemOffer offer = new ItemAOffer( item ); Set> offers = new HashSet>(); offers.add( offer ); Batch batch = new Batch( offers ); Set> violations = validator.validate( batch ); assertNumberOfViolations( violations, 1 ); assertCorrectPropertyPaths( violations, "offers[].item.date" ); assertCorrectConstraintTypes( violations, NotNull.class ); } private class Batch { @NotNull @Valid private Set> offers = new HashSet>(); public Batch(Set> offers) { this.offers = offers; } } private abstract class Item { @NotNull private Date date; public Item(Date date) { this.date = date; } } private abstract class ItemOffer { @NotNull @Valid private T item; public ItemOffer(T item) { this.item = item; } } private class ItemA extends Item { public ItemA(Date date) { super( date ); } } private class ItemAOffer extends ItemOffer { public ItemAOffer(ItemA item) { super( item ); } } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Cloneable.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000332511262172500033473 0ustar twernertwerner// $Id: Cloneable.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * @author Hardy Ferentschik */ @Constraint(validatedBy = { CloneableConstraintValidator.class }) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented public @interface Cloneable { public abstract String message() default "{org.hibernate.validator.constraints.Cloneable.message}"; public abstract Class[] groups() default { }; public abstract Class[] payload() default { }; } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/StartLessThanEndImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000277211262172500033500 0ustar twernertwerner// $Id: StartLessThanEndImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class StartLessThanEndImpl implements ConstraintValidator { public void initialize(StartLessThanEnd constraintAnnotation) { } public boolean isValid(Interval value, ConstraintValidatorContext c) { if ( value.start > value.end ) { c.disableDefaultConstraintViolation(); c.buildConstraintViolationWithTemplate( c.getDefaultConstraintMessageTemplate() ).addNode( "start" ).addConstraintViolation(); return false; } return true; } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Object.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000323111262172500033467 0ustar twernertwerner// $Id: Object.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * @author Hardy Ferentschik */ @Constraint(validatedBy = { ObjectConstraintValidator.class }) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented public @interface Object { String message() default "{org.hibernate.validator.constraints.Object.message}"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Serializable.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000334111262172500033471 0ustar twernertwerner// $Id: Serializable.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * @author Hardy Ferentschik */ @Constraint(validatedBy = { SerializableConstraintValidator.class }) @Target({ METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Documented public @interface Serializable { public abstract String message() default "{org.hibernate.validator.constraints.Serializable.message}"; public abstract Class[] groups() default { }; public abstract Class[] payload() default { }; } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/SerializableConstraintValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000251511262172500033473 0ustar twernertwerner// $Id: SerializableConstraintValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class SerializableConstraintValidator implements ConstraintValidator { public void initialize(Serializable annotation) { } public boolean isValid( java.io.Serializable value, ConstraintValidatorContext constraintValidatorContext) { return true; } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/StartLessThanEnd.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000265111262172500033474 0ustar twernertwerner// $Id: StartLessThanEnd.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; /** * @author Hardy Ferentschik */ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = StartLessThanEndImpl.class) public @interface StartLessThanEnd { String message() default "x"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/ConstraintTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000454311262172500033476 0ustar twernertwerner// $Id: ConstraintTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertConstraintViolation; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class ConstraintTest { @Test public void testRangeConstraint() { Validator validator = TestUtil.getValidator(); Elevator elevator = new Elevator(); elevator.setCurrentFloor( -3 ); Set> constraintViolations = validator.validate( elevator ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "Invalid floor" ); elevator.setCurrentFloor( -2 ); constraintViolations = validator.validate( elevator ); assertNumberOfViolations( constraintViolations, 0 ); elevator.setCurrentFloor( 45 ); constraintViolations = validator.validate( elevator ); assertNumberOfViolations( constraintViolations, 0 ); elevator.setCurrentFloor( 50 ); constraintViolations = validator.validate( elevator ); assertNumberOfViolations( constraintViolations, 0 ); elevator.setCurrentFloor( 51 ); constraintViolations = validator.validate( elevator ); assertNumberOfViolations( constraintViolations, 1 ); assertConstraintViolation( constraintViolations.iterator().next(), "Invalid floor" ); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Coordinate.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000217611262172500033476 0ustar twernertwerner// $Id: Coordinate.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; /** * @author Hardy Ferentschik */ /** * @author Hardy Ferentschik */ public class Coordinate { long longitude; long latitude; public Coordinate(long longitude, long latitude) { this.longitude = longitude; this.latitude = latitude; } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000755000175000017500000000000011402110343033457 5ustar twernertwerner././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/PastValidatorForDateTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000361511262172500033475 0ustar twernertwerner// $Id: PastValidatorForDateTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Date; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class PastValidatorForDateTest { private static PastValidatorForDate constraint; @BeforeClass public static void init() { constraint = new PastValidatorForDate(); } @Test public void testIsValid() { Date futureDate = getFutureDate(); Date pastDate = getPastDate(); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( pastDate, null ) ); assertFalse( constraint.isValid( new Date(), null ) ); assertFalse( constraint.isValid( futureDate, null ) ); } private Date getFutureDate() { Date date = new Date(); long timeStamp = date.getTime(); date.setTime( timeStamp + 31557600000l ); return date; } private Date getPastDate() { Date date = new Date(); long timeStamp = date.getTime(); date.setTime( timeStamp - 31557600000l ); return date; } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/DigitsValidatorForStringTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000640711262172500033477 0ustar twernertwerner// $Id: DigitsValidatorForStringTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.constraints.Digits; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef */ public class DigitsValidatorForStringTest { private static DigitsValidatorForString constraint; @BeforeClass public static void init() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 5 ); descriptor.setValue( "fraction", 2 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); constraint = new DigitsValidatorForString(); constraint.initialize( p ); } @Test public void testIsValid() { assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( "0", null ) ); assertTrue( constraint.isValid( "500.2", null ) ); assertTrue( constraint.isValid( "-12456.22", null ) ); assertTrue( constraint.isValid( "-000000000.22", null ) ); //should throw number format exception assertFalse( constraint.isValid( "", null ) ); assertFalse( constraint.isValid( "256874.0", null ) ); assertFalse( constraint.isValid( "12.0001", null ) ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeIntegerLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", -1 ); descriptor.setValue( "fraction", 1 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForString constraint = new DigitsValidatorForString(); constraint.initialize( p ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeFractionLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 1 ); descriptor.setValue( "fraction", -1 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForString constraint = new DigitsValidatorForString(); constraint.initialize( p ); } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/NotNullValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000252011262172500033467 0ustar twernertwerner// $Id: NotNullValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class NotNullValidatorTest { @Test public void testIsValid() { NotNullValidator constraint = new NotNullValidator(); assertFalse( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( new Object(), null ) ); } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/AssertFalseValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000311311262172500033466 0ustar twernertwerner// $Id: AssertFalseValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Alaa Nassef */ public class AssertFalseValidatorTest { private static AssertFalseValidator constraint; @BeforeClass public static void init() { constraint = new AssertFalseValidator(); } @Test public void testIsValid() { assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( false, null ) ); assertTrue( constraint.isValid( Boolean.FALSE, null ) ); assertFalse( constraint.isValid( true, null ) ); assertFalse( constraint.isValid( Boolean.TRUE, null ) ); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/DigitsValidatorForNumberTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000001134111262172500033470 0ustar twernertwerner// $Id: DigitsValidatorForNumberTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.constraints.Digits; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class DigitsValidatorForNumberTest { @Test public void testIsValid() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 5 ); descriptor.setValue( "fraction", 2 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForNumber constraint = new DigitsValidatorForNumber(); constraint.initialize( p ); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( Byte.valueOf( "0" ), null ) ); assertTrue( constraint.isValid( Double.valueOf( "500.2" ), null ) ); assertTrue( constraint.isValid( new BigDecimal( "-12345.12" ), null ) ); assertFalse( constraint.isValid( new BigDecimal( "-123456.12" ), null ) ); assertFalse( constraint.isValid( new BigDecimal( "-123456.123" ), null ) ); assertFalse( constraint.isValid( new BigDecimal( "-12345.123" ), null ) ); assertFalse( constraint.isValid( new BigDecimal( "12345.123" ), null ) ); assertTrue( constraint.isValid( Float.valueOf( "-000000000.22" ), null ) ); assertFalse( constraint.isValid( Integer.valueOf( "256874" ), null ) ); assertFalse( constraint.isValid( Double.valueOf( "12.0001" ), null ) ); } @Test public void testIsValidZeroLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 0 ); descriptor.setValue( "fraction", 0 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForNumber constraint = new DigitsValidatorForNumber(); constraint.initialize( p ); assertTrue( constraint.isValid( null, null ) ); assertFalse( constraint.isValid( Byte.valueOf( "0" ), null ) ); assertFalse( constraint.isValid( Double.valueOf( "500.2" ), null ) ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeIntegerLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", -1 ); descriptor.setValue( "fraction", 1 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForNumber constraint = new DigitsValidatorForNumber(); constraint.initialize( p ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeFractionLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 1 ); descriptor.setValue( "fraction", -1 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForNumber constraint = new DigitsValidatorForNumber(); constraint.initialize( p ); } @Test public void testTrailingZerosAreTrimmed() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Digits.class ); descriptor.setValue( "integer", 12 ); descriptor.setValue( "fraction", 3 ); descriptor.setValue( "message", "{validator.digits}" ); Digits p = AnnotationFactory.create( descriptor ); DigitsValidatorForNumber constraint = new DigitsValidatorForNumber(); constraint.initialize( p ); assertTrue( constraint.isValid( 0.001d, null ) ); assertTrue( constraint.isValid( 0.00100d, null ) ); assertFalse( constraint.isValid( 0.0001d, null ) ); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/DateHolder.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000345211262172500033474 0ustar twernertwerner// $Id: DateHolder.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Calendar; import java.util.Date; import javax.validation.constraints.Future; import javax.validation.constraints.Past; /** * @author Hardy Ferentschik */ public class DateHolder { @Past private Calendar calendarWithPastDate; @Future private Calendar calendarWithFutureDate; @Past private Date past; @Past private Date future; public DateHolder() { calendarWithPastDate = Calendar.getInstance(); calendarWithPastDate.add( Calendar.YEAR, -1 ); past = calendarWithPastDate.getTime(); calendarWithFutureDate = Calendar.getInstance(); calendarWithFutureDate.add( Calendar.YEAR, 1 ); future = calendarWithFutureDate.getTime(); } public Calendar getCalendarWithPastDate() { return calendarWithPastDate; } public Calendar getCalendarWithFutureDate() { return calendarWithFutureDate; } public Date getPast() { return past; } public Date getFuture() { return future; } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/MaxValidatorForStringTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000643511262172500033500 0ustar twernertwerner// $Id: MaxValidatorForStringTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.Max; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Hardy Ferentschik */ public class MaxValidatorForStringTest { @Test public void testIsValidMax() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Max.class ); descriptor.setValue( "value", 15l ); descriptor.setValue( "message", "{validator.max}" ); Max m = AnnotationFactory.create( descriptor ); MaxValidatorForString constraint = new MaxValidatorForString(); constraint.initialize( m ); testMaxValidator( constraint ); } @Test public void testIsValidDecimalMax() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMax.class ); descriptor.setValue( "value", "15.0E0" ); descriptor.setValue( "message", "{validator.max}" ); DecimalMax m = AnnotationFactory.create( descriptor ); DecimalMaxValidatorForString constraint = new DecimalMaxValidatorForString(); constraint.initialize( m ); testMaxValidator( constraint ); } @Test public void testInitializeDecimalMaxWithInvalidValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMax.class ); descriptor.setValue( "value", "foobar" ); descriptor.setValue( "message", "{validator.max}" ); DecimalMax m = AnnotationFactory.create( descriptor ); DecimalMaxValidatorForNumber constraint = new DecimalMaxValidatorForNumber(); try { constraint.initialize( m ); fail(); } catch ( IllegalArgumentException e ) { // success } } private void testMaxValidator(ConstraintValidator constraint) { assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( "15", null ) ); assertTrue( constraint.isValid( "15.0", null ) ); assertTrue( constraint.isValid( "10", null ) ); assertTrue( constraint.isValid( "14.99", null ) ); assertTrue( constraint.isValid( "-14.99", null ) ); assertFalse( constraint.isValid( "20", null ) ); //number format exception assertFalse( constraint.isValid( "15l", null ) ); } } ././@LongLink0000000000000000000000000000022400000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/FutureValidatorForCalendarTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000372411262172500033476 0ustar twernertwerner// $Id: FutureValidatorForCalendarTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Calendar; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class FutureValidatorForCalendarTest { private static FutureValidatorForCalendar constraint; @BeforeClass public static void init() { constraint = new FutureValidatorForCalendar(); } @Test public void testIsValid() { Calendar futureDate = getFutureDate(); Calendar pastDate = getPastDate(); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( futureDate, null ) ); assertFalse( constraint.isValid( pastDate, null ) ); } private Calendar getFutureDate() { Calendar cal = Calendar.getInstance(); int year = cal.get( Calendar.YEAR ); cal.set( Calendar.YEAR, year + 1 ); return cal; } private Calendar getPastDate() { Calendar cal = Calendar.getInstance(); int year = cal.get( Calendar.YEAR ); cal.set( Calendar.YEAR, year - 1 ); return cal; } } ././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/EmailValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000414511262172500033474 0ustar twernertwerner// $Id: EmailValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Hardy Ferentschik */ public class EmailValidatorTest { private static EmailValidator validator; @BeforeClass public static void init() { validator = new EmailValidator(); } @Test public void testEmail() throws Exception { isRightEmail( "emmanuel@hibernate.org" ); isRightEmail( "" ); isRightEmail( null ); isRightEmail( "emmanuel@hibernate" ); isRightEmail( "emma-n_uel@hibernate" ); isRightEmail( "emma+nuel@hibernate.org" ); isRightEmail( "emma=nuel@hibernate.org" ); isRightEmail( "emmanuel@[123.12.2.11]" ); isWrongEmail( "emmanuel.hibernate.org" ); isWrongEmail( "emma nuel@hibernate.org" ); isWrongEmail( "emma(nuel@hibernate.org" ); isWrongEmail( "emmanuel@" ); isWrongEmail( "emma\nnuel@hibernate.org" ); isWrongEmail( "emma@nuel@hibernate.org" ); } private void isRightEmail(String email) { assertTrue( validator.isValid( email, null ), "Expected a valid email." ); } private void isWrongEmail(String email) { assertFalse( validator.isValid( email, null ), "Expected a invalid email." ); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/PastValidatorForCalendarTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000402611262172500033472 0ustar twernertwerner// $Id: PastValidatorForCalendarTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Calendar; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import org.hibernate.validator.constraints.impl.PastValidatorForCalendar; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class PastValidatorForCalendarTest { private static PastValidatorForCalendar constraint; @BeforeClass public static void init() { constraint = new PastValidatorForCalendar(); } @Test public void testIsValid() { Calendar futureDate = getFutureDate(); Calendar pastDate = getPastDate(); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( pastDate, null ) ); assertFalse( constraint.isValid( futureDate, null ) ); } private Calendar getFutureDate() { Calendar cal = Calendar.getInstance(); int year = cal.get( Calendar.YEAR ); cal.set( Calendar.YEAR, year + 1 ); return cal; } private Calendar getPastDate() { Calendar cal = Calendar.getInstance(); int year = cal.get( Calendar.YEAR ); cal.set( Calendar.YEAR, year - 1 ); return cal; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/PatternValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000611211262172500033470 0ustar twernertwerner// $Id: PatternValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.constraints.Pattern; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Hardy Ferentschik */ public class PatternValidatorTest { @Test public void testIsValid() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Pattern.class ); descriptor.setValue( "regexp", "foobar" ); descriptor.setValue( "message", "pattern does not match" ); Pattern p = AnnotationFactory.create( descriptor ); PatternValidator constraint = new PatternValidator(); constraint.initialize( p ); assertTrue( constraint.isValid( null, null ) ); assertFalse( constraint.isValid( "", null ) ); assertFalse( constraint.isValid( "bla bla", null ) ); assertFalse( constraint.isValid( "This test is not foobar", null ) ); } @Test public void testIsValidForEmptyStringRegexp() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Pattern.class ); descriptor.setValue( "regexp", "|^.*foo$" ); descriptor.setValue( "message", "pattern does not match" ); Pattern p = AnnotationFactory.create( descriptor ); PatternValidator constraint = new PatternValidator(); constraint.initialize( p ); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( "", null ) ); assertFalse( constraint.isValid( "bla bla", null ) ); assertTrue( constraint.isValid( "foo", null ) ); assertTrue( constraint.isValid( "a b c foo", null ) ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testInvalidRegularExpression() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Pattern.class ); descriptor.setValue( "regexp", "(unbalanced parentheses" ); descriptor.setValue( "message", "pattern does not match" ); Pattern p = AnnotationFactory.create( descriptor ); PatternValidator constraint = new PatternValidator(); constraint.initialize( p ); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/LengthValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000672411262172500033501 0ustar twernertwerner// $Id: LengthValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * Tests the LengthConstraint. * * @author Hardy Ferentschik */ public class LengthValidatorTest { @Test public void testIsValid() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Length.class ); descriptor.setValue( "min", 1 ); descriptor.setValue( "max", 3 ); descriptor.setValue( "message", "{validator.length}" ); Length l = AnnotationFactory.create( descriptor ); LengthValidator constraint = new LengthValidator(); constraint.initialize( l ); assertTrue( constraint.isValid( null, null ) ); assertFalse( constraint.isValid( "", null ) ); assertTrue( constraint.isValid( "f", null ) ); assertTrue( constraint.isValid( "fo", null ) ); assertTrue( constraint.isValid( "foo", null ) ); assertFalse( constraint.isValid( "foobar", null ) ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeMinValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Length.class ); descriptor.setValue( "min", -1 ); descriptor.setValue( "max", 1 ); descriptor.setValue( "message", "{validator.length}" ); Length p = AnnotationFactory.create( descriptor ); LengthValidator constraint = new LengthValidator(); constraint.initialize( p ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeMaxValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Length.class ); descriptor.setValue( "min", 1 ); descriptor.setValue( "max", -1 ); descriptor.setValue( "message", "{validator.length}" ); Length p = AnnotationFactory.create( descriptor ); LengthValidator constraint = new LengthValidator(); constraint.initialize( p ); } @Test(expectedExceptions = IllegalArgumentException.class) public void testNegativeLength() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Length.class ); descriptor.setValue( "min", 5 ); descriptor.setValue( "max", 4 ); descriptor.setValue( "message", "{validator.length}" ); Length p = AnnotationFactory.create( descriptor ); LengthValidator constraint = new LengthValidator(); constraint.initialize( p ); } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/MaxValidatorForNumberTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000742011262172500033473 0ustar twernertwerner// $Id: MaxValidatorForNumberTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.Max; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class MaxValidatorForNumberTest { @Test public void testIsValidMax() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Max.class ); descriptor.setValue( "value", 15l ); descriptor.setValue( "message", "{validator.max}" ); Max m = AnnotationFactory.create( descriptor ); MaxValidatorForNumber constraint = new MaxValidatorForNumber(); constraint.initialize( m ); testMaxValidator( constraint ); } @Test public void testIsValidDecimalMax() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMax.class ); descriptor.setValue( "value", "15.0E0" ); descriptor.setValue( "message", "{validator.max}" ); DecimalMax m = AnnotationFactory.create( descriptor ); DecimalMaxValidatorForNumber constraint = new DecimalMaxValidatorForNumber(); constraint.initialize( m ); testMaxValidator( constraint ); } @Test public void testInitializeDecimalMaxWithInvalidValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMax.class ); descriptor.setValue( "value", "foobar" ); descriptor.setValue( "message", "{validator.max}" ); DecimalMax m = AnnotationFactory.create( descriptor ); DecimalMaxValidatorForNumber constraint = new DecimalMaxValidatorForNumber(); try { constraint.initialize( m ); fail(); } catch ( IllegalArgumentException e ) { // success } } private void testMaxValidator(ConstraintValidator constraint) { byte b = 1; Byte bWrapper = 127; assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( b, null ) ); assertTrue( constraint.isValid( 15l, null ) ); assertTrue( constraint.isValid( 15, null ) ); assertTrue( constraint.isValid( 15.0, null ) ); assertTrue( constraint.isValid( BigDecimal.valueOf( -156000000000.0 ), null ) ); assertTrue( constraint.isValid( BigInteger.valueOf( -10000000l ), null ) ); assertTrue( constraint.isValid( 10, null ) ); assertTrue( constraint.isValid( 14.99, null ) ); assertTrue( constraint.isValid( -14.99, null ) ); assertFalse( constraint.isValid( 20, null ) ); assertFalse( constraint.isValid( bWrapper, null ) ); assertFalse( constraint.isValid( BigDecimal.valueOf( 156000000000.0 ), null ) ); assertFalse( constraint.isValid( BigInteger.valueOf( 10000000l ), null ) ); } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/MinValidatorForStringTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000650711262172500033500 0ustar twernertwerner// $Id: MinValidatorForStringTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class MinValidatorForStringTest { @Test public void testIsValidMinValidator() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Min.class ); descriptor.setValue( "value", 15l ); descriptor.setValue( "message", "{validator.min}" ); Min m = AnnotationFactory.create( descriptor ); MinValidatorForString constraint = new MinValidatorForString(); constraint.initialize( m ); testMinValidator( constraint ); } @Test public void testIsValidDecimalMinValidator() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMin.class ); descriptor.setValue( "value", "1500E-2" ); descriptor.setValue( "message", "{validator.min}" ); DecimalMin m = AnnotationFactory.create( descriptor ); DecimalMinValidatorForString constraint = new DecimalMinValidatorForString(); constraint.initialize( m ); testMinValidator( constraint ); } @Test public void testInitializeDecimalMaxWithInvalidValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMin.class ); descriptor.setValue( "value", "foobar" ); descriptor.setValue( "message", "{validator.min}" ); DecimalMin m = AnnotationFactory.create( descriptor ); DecimalMinValidatorForNumber constraint = new DecimalMinValidatorForNumber(); try { constraint.initialize( m ); fail(); } catch ( IllegalArgumentException e ) { // success } } private void testMinValidator(ConstraintValidator constraint) { assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( "20", null ) ); assertTrue( constraint.isValid( "15", null ) ); assertTrue( constraint.isValid( "15.0", null ) ); assertFalse( constraint.isValid( "10", null ) ); assertFalse( constraint.isValid( "14.99", null ) ); assertFalse( constraint.isValid( "-14.99", null ) ); //number format exception assertFalse( constraint.isValid( "15l", null ) ); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/FutureValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000302611262172500033471 0ustar twernertwerner// $Id: FutureValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; /** * @author Hardy Ferentschik */ public class FutureValidatorTest { /** * HV-158 */ @Test public void testFutureAndPast() { Validator validator = TestUtil.getValidator(); DateHolder dateHolder = new DateHolder(); Set> constraintViolations = validator.validate( dateHolder ); assertEquals( constraintViolations.size(), 1, "Wrong number of constraints" ); } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/FutureValidatorForDateTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000362511262172500033476 0ustar twernertwerner// $Id: FutureValidatorForDateTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Date; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class FutureValidatorForDateTest { private static FutureValidatorForDate constraint; @BeforeClass public static void init() { constraint = new FutureValidatorForDate(); } @Test public void testIsValid() { Date futureDate = getFutureDate(); Date pastDate = getPastDate(); assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( futureDate, null ) ); assertFalse( constraint.isValid( new Date(), null ) ); assertFalse( constraint.isValid( pastDate, null ) ); } private Date getFutureDate() { Date date = new Date(); long timeStamp = date.getTime(); date.setTime( timeStamp + 31557600000l ); return date; } private Date getPastDate() { Date date = new Date(); long timeStamp = date.getTime(); date.setTime( timeStamp - 31557600000l ); return date; } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/AssertTrueValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000311011262172500033463 0ustar twernertwerner// $Id: AssertTrueValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Alaa Nassef */ public class AssertTrueValidatorTest { private static AssertTrueValidator constraint; @BeforeClass public static void init() { constraint = new AssertTrueValidator(); } @Test public void testIsValid() { assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( true, null ) ); assertTrue( constraint.isValid( Boolean.TRUE, null ) ); assertFalse( constraint.isValid( false, null ) ); assertFalse( constraint.isValid( Boolean.FALSE, null ) ); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/SizeValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000001401711265402406033477 0ustar twernertwerner// $Id: SizeValidatorTest.java 17747 2009-10-14 17:06:14Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; import javax.validation.ConstraintValidator; import javax.validation.constraints.Size; import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertFalse; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef */ public class SizeValidatorTest { @Test public void testIsValidObjectArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArray.class ); assertSizes( validator, Object[].class ); } @Test public void testIsValidBooleanArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfBoolean.class ); assertSizes( validator, boolean[].class ); } @Test public void testIsValidByteArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfByte.class ); assertSizes( validator, byte[].class ); } @Test public void testIsValidCharArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfChar.class ); assertSizes( validator, char[].class ); } @Test public void testIsValidDoubleArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfDouble.class ); assertSizes( validator, double[].class ); } @Test public void testIsValidFloatArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfFloat.class ); assertSizes( validator, float[].class ); } @Test public void testIsValidIntArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfInt.class ); assertSizes( validator, int[].class ); } @Test public void testIsValidLongArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfLong.class ); assertSizes( validator, long[].class ); } @Test public void testIsValidShortArray() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForArraysOfShort.class ); assertSizes( validator, short[].class ); } @Test public void testIsValidCollection() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForCollection.class ); assertTrue( validator.isValid( null, null ) ); Collection collection = new ArrayList(); assertFalse( validator.isValid( collection, null ) ); collection.add( "firstItem" ); assertTrue( validator.isValid( collection, null ) ); collection.add( "secondItem" ); assertTrue( validator.isValid( collection, null ) ); collection.add( "thirdItem" ); assertFalse( validator.isValid( collection, null ) ); } @Test public void testIsValidMap() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForMap.class ); assertTrue( validator.isValid( null, null ) ); Map map = new HashMap(); assertFalse( validator.isValid( map, null ) ); map.put( "key1", "firstItem" ); assertTrue( validator.isValid( map, null ) ); map.put( "key3", "secondItem" ); assertTrue( validator.isValid( map, null ) ); map.put( "key2", "thirdItem" ); assertFalse( validator.isValid( map, null ) ); } @Test public void testIsValiString() throws Exception { ConstraintValidator validator = getValidator( SizeValidatorForString.class ); assertTrue( validator.isValid( null, null ) ); assertFalse( validator.isValid( "", null ) ); assertTrue( validator.isValid( "a", null ) ); assertTrue( validator.isValid( "ab", null ) ); assertFalse( validator.isValid( "abc", null ) ); } private ConstraintValidator getValidator(Class validatorClass) throws Exception { AnnotationDescriptor descriptor = new AnnotationDescriptor( Size.class ); descriptor.setValue( "min", 1 ); descriptor.setValue( "max", 2 ); descriptor.setValue( "message", "{validator.max}" ); Size m = AnnotationFactory.create( descriptor ); @SuppressWarnings("unchecked") ConstraintValidator validator = ( ConstraintValidator ) validatorClass.newInstance(); validator.initialize( m ); return validator; } @SuppressWarnings("unchecked") private void assertSizes(ConstraintValidator validator, Class arrayType) { assertTrue( validator.isValid( null, null ) ); T array = ( T ) Array.newInstance( arrayType.getComponentType(), 0 ); assertFalse( validator.isValid( array, null ) ); array = ( T ) Array.newInstance( arrayType.getComponentType(), 1 ); assertTrue( validator.isValid( array, null ) ); array = ( T ) Array.newInstance( arrayType.getComponentType(), 2 ); assertTrue( validator.isValid( array, null ) ); array = ( T ) Array.newInstance( arrayType.getComponentType(), 3 ); assertFalse( validator.isValid( array, null ) ); } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/MinValidatorForNumberTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000744311262172500033500 0ustar twernertwerner// $Id: MinValidatorForNumberTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Min; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Alaa Nassef * @author Hardy Ferentschik */ public class MinValidatorForNumberTest { @Test public void testIsValidMinValidator() { AnnotationDescriptor descriptor = new AnnotationDescriptor( Min.class ); descriptor.setValue( "value", 15l ); descriptor.setValue( "message", "{validator.min}" ); Min m = AnnotationFactory.create( descriptor ); MinValidatorForNumber constraint = new MinValidatorForNumber(); constraint.initialize( m ); testMinValidator( constraint ); } @Test public void testIsValidDecimalMinValidator() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMin.class ); descriptor.setValue( "value", "1500E-2" ); descriptor.setValue( "message", "{validator.min}" ); DecimalMin m = AnnotationFactory.create( descriptor ); DecimalMinValidatorForNumber constraint = new DecimalMinValidatorForNumber(); constraint.initialize( m ); testMinValidator( constraint ); } @Test public void testInitializeDecimalMaxWithInvalidValue() { AnnotationDescriptor descriptor = new AnnotationDescriptor( DecimalMin.class ); descriptor.setValue( "value", "foobar" ); descriptor.setValue( "message", "{validator.min}" ); DecimalMin m = AnnotationFactory.create( descriptor ); DecimalMinValidatorForNumber constraint = new DecimalMinValidatorForNumber(); try { constraint.initialize( m ); fail(); } catch ( IllegalArgumentException e ) { // success } } private void testMinValidator(ConstraintValidator constraint) { byte b = 1; Byte bWrapper = 127; assertTrue( constraint.isValid( null, null ) ); assertTrue( constraint.isValid( bWrapper, null ) ); assertTrue( constraint.isValid( 20, null ) ); assertTrue( constraint.isValid( 15l, null ) ); assertTrue( constraint.isValid( 15, null ) ); assertTrue( constraint.isValid( 15.0, null ) ); assertTrue( constraint.isValid( BigDecimal.valueOf( 156000000000.0 ), null ) ); assertTrue( constraint.isValid( BigInteger.valueOf( 10000000l ), null ) ); assertFalse( constraint.isValid( b, null ) ); assertFalse( constraint.isValid( BigDecimal.valueOf( -156000000000.0 ), null ) ); assertFalse( constraint.isValid( BigInteger.valueOf( -10000000l ), null ) ); assertFalse( constraint.isValid( 10, null ) ); assertFalse( constraint.isValid( 14.99, null ) ); assertFalse( constraint.isValid( -14.99, null ) ); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/impl/NullValidatorTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000261611262172500033475 0ustar twernertwerner// $Id: NullValidatorTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; /** * @author Alaa Nassef */ public class NullValidatorTest { private static NullValidator constraint; @BeforeClass public static void init() { constraint = new NullValidator(); } @Test public void testIsValid() { assertTrue( constraint.isValid( null, null ) ); assertFalse( constraint.isValid( new Object(), null ) ); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Suburb.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000513711262172500033476 0ustar twernertwerner// $Id: Suburb.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class Suburb { public enum Facility { SHOPPING_MALL, BUS_TERMINAL } @Size(min = 5, max = 10, message = "size must be between {min} and {max}") private String name; @Size(min = 2, max = 2, message = "size must be between {min} and {max}") private Map facilities; @Size(min = 2, message = "size must be between {min} and {max}") private Set streetNames; @Size(min = 4, max = 1000, message = "size must be between {min} and {max}") private Coordinate[] boundingBox; @PostCodeList private Collection includedPostCodes; public void setIncludedPostCodes(Collection includedPostCodes) { this.includedPostCodes = includedPostCodes; } public Collection getIncludedPostcodes() { return includedPostCodes; } public void setName(String name) { this.name = name; } public String getName() { return name; } public Map getFacilities() { return facilities; } public void addFacility(Facility f, Boolean exist) { if ( facilities == null ) { facilities = new HashMap(); } facilities.put( f, exist ); } public Set getStreetNames() { return streetNames; } public void addStreetName(String streetName) { if ( streetNames == null ) { streetNames = new HashSet(); } streetNames.add( streetName ); } public Coordinate[] getBoundingBox() { return boundingBox; } public void setBoundingBox(Coordinate[] boundingBox) { this.boundingBox = boundingBox; } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/invalidvalidators/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000755000175000017500000000000011402110337033462 5ustar twernertwerner././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/SuperTypeArrayValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000245511262172500033476 0ustar twernertwerner// $Id: SuperTypeArrayValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class SuperTypeArrayValidator implements ConstraintValidator { public void initialize(SuperTypeArray annotation) { } public boolean isValid(SuperType[] value, ConstraintValidatorContext constraintValidatorContext) { return true; } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/CloneableConstraintValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000247511262172500033500 0ustar twernertwerner// $Id: CloneableConstraintValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * @author Hardy Ferentschik */ public class CloneableConstraintValidator implements ConstraintValidator { public void initialize(Cloneable annotation) { } public boolean isValid(java.lang.Cloneable value, ConstraintValidatorContext constraintValidatorContext) { return true; } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/ConstraintValidatorContextTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000001342511265613571033510 0ustar twernertwerner// $Id: ConstraintValidatorContextTest.java 17764 2009-10-15 12:37:13Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import org.testng.annotations.Test; import org.hibernate.validator.engine.ConstraintValidatorContextImpl; import org.hibernate.validator.engine.MessageAndPath; import org.hibernate.validator.engine.PathImpl; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertCorrectPropertyPaths; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Hardy Ferentschik */ public class ConstraintValidatorContextTest { /** * HV-198 */ @Test public void testCorrectSubNodePath() { Validator validator = TestUtil.getValidator(); Item item = new Item(); item.interval = new Interval(); item.interval.start = 10; item.interval.end = 5; Set> constraintViolations = validator.validate( item ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "interval.start" ); } /** * HV-208 */ @Test public void testCorrectPath() { Validator validator = TestUtil.getValidator(); Item item = new Item(); Interval interval = new Interval(); item.interval = interval; item.interval.start = 10; item.interval.end = 5; Set> constraintViolations = validator.validate( interval ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectPropertyPaths( constraintViolations, "start" ); } @Test public void testDifferentPaths() { String message = "message"; ConstraintValidatorContextImpl context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message ) .addNode( "foo" ) .addNode( "bar" ).inIterable().atIndex( 3 ) .addConstraintViolation(); List messageAndPathList = context.getMessageAndPathList(); assertMessageAndPath( messageAndPathList.get( 0 ), message, "foo[3].bar" ); context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message ) .addNode( "foo" ) .addNode( null ).inIterable().atKey( "test" ) .addConstraintViolation(); messageAndPathList = context.getMessageAndPathList(); assertMessageAndPath( messageAndPathList.get( 0 ), message, "foo[test]" ); context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message ) .addNode( "foo" ) .addNode( "bar" ).inIterable().atKey( "test" ) .addNode( "fubar" ) .addConstraintViolation(); messageAndPathList = context.getMessageAndPathList(); assertMessageAndPath( messageAndPathList.get( 0 ), message, "foo[test].bar.fubar" ); context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message ) .addNode( "foo" ) .addNode( "bar" ).inIterable().atKey( "test" ) .addNode( "fubar" ).inIterable().atIndex( 10 ) .addConstraintViolation(); messageAndPathList = context.getMessageAndPathList(); assertMessageAndPath( messageAndPathList.get( 0 ), message, "foo[test].bar[10].fubar" ); context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message ) .addNode( "foo" ) .addNode( "bar" ).inIterable().atKey( "test" ) .addNode( "fubar" ).inIterable() .addConstraintViolation(); messageAndPathList = context.getMessageAndPathList(); assertMessageAndPath( messageAndPathList.get( 0 ), message, "foo[test].bar[].fubar" ); } @Test public void testMultipleMessages() { String message1 = "message1"; String message2 = "message2"; ConstraintValidatorContextImpl context = createEmptyConstraintValidatorContextImpl(); context.buildConstraintViolationWithTemplate( message1 ) .addNode( "foo" ) .addNode( "bar" ).inIterable().atKey( "key" ) .addConstraintViolation(); context.buildConstraintViolationWithTemplate( message2 ) .addConstraintViolation(); List messageAndPathList = context.getMessageAndPathList(); assertTrue( messageAndPathList.size() == 2 ); assertMessageAndPath( messageAndPathList.get( 0 ), message1, "foo[key].bar" ); assertMessageAndPath( messageAndPathList.get( 1 ), message2, "" ); } private ConstraintValidatorContextImpl createEmptyConstraintValidatorContextImpl() { ConstraintValidatorContextImpl context = new ConstraintValidatorContextImpl( PathImpl.createNewPath( null ), null ); context.disableDefaultConstraintViolation(); return context; } private void assertMessageAndPath(MessageAndPath messageAndPath, String expectedMessage, String expectedPath) { assertEquals( messageAndPath.getPath(), PathImpl.createPathFromString( expectedPath ), "Wrong path" ); assertEquals( messageAndPath.getMessage(), expectedMessage, "Wrong message" ); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/composition/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000755000175000017500000000000011402110344033460 5ustar twernertwerner././@LongLink0000000000000000000000000000022400000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/composition/CompositeConstraintTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000650311262172500033474 0ustar twernertwerner// $Id: CompositeConstraintTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.composition; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; import static org.hibernate.validator.util.TestUtil.assertCorrectConstraintTypes; import static org.hibernate.validator.util.TestUtil.assertCorrectConstraintViolationMessages; import static org.hibernate.validator.util.TestUtil.assertNumberOfViolations; /** * @author Gerhard Petracek * @author Hardy Ferentschik */ public class CompositeConstraintTest { /** * HV-182 */ @Test public void testCorrectAnnotationTypeForWithReportAsSingleViolation() { Validator currentValidator = TestUtil.getValidator(); for ( int i = 0; i < 100; i++ ) { Set> constraintViolations = currentValidator.validate( new Person( null, "Gerhard" ) ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, ValidNameSingleViolation.class ); assertCorrectConstraintViolationMessages( constraintViolations, "invalid name" ); constraintViolations = currentValidator.validate( new Person( "G", "Gerhard" ) ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, ValidNameSingleViolation.class ); assertCorrectConstraintViolationMessages( constraintViolations, "invalid name" ); } } /** * HV-182 */ @Test public void testCorrectAnnotationTypeReportMultipleViolations() { Validator currentValidator = TestUtil.getValidator(); for ( int i = 0; i < 100; i++ ) { Set> constraintViolations = currentValidator.validate( new Person( "Gerd", null ) ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, NotNull.class ); assertCorrectConstraintViolationMessages( constraintViolations, "may not be null" ); constraintViolations = currentValidator.validate( new Person( "Gerd", "G" ) ); assertNumberOfViolations( constraintViolations, 1 ); assertCorrectConstraintTypes( constraintViolations, Size.class ); assertCorrectConstraintViolationMessages( constraintViolations, "size must be between 2 and 10" ); } } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/composition/Person.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000265111262172500033474 0ustar twernertwerner// $Id: Person.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.composition; /** * Test mode for HV-182. * * @author Gerhard Petracek * @author Hardy Ferentschik */ public class Person { @ValidNameSingleViolation private String nickName; @ValidName private String name; public Person(String nickName, String name) { this.nickName = nickName; this.name = name; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/composition/ValidNameSingleViolation.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000337411262172500033477 0ustar twernertwerner// $Id: ValidNameSingleViolation.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.composition; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** * Test constraint for HV-182. * * @author Gerhard Petracek * @author Hardy Ferentschik */ @NotNull @Size(min = 2, max = 10) @ReportAsSingleViolation @Target({ METHOD, FIELD }) @Retention(RUNTIME) @Constraint(validatedBy = { }) public @interface ValidNameSingleViolation { String message() default "invalid name"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/composition/ValidName.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000330411262172500033470 0ustar twernertwerner// $Id: ValidName.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.composition; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** * Test constraint for HV-182. * * @author Gerhard Petracek * @author Hardy Ferentschik */ @NotNull @Size(min = 2, max = 10) @Target({ METHOD, FIELD }) @Retention(RUNTIME) @Constraint(validatedBy = { }) public @interface ValidName { public abstract String message() default "invalid name"; public abstract Class[] groups() default { }; public abstract Class[] payload() default { }; } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/PostCodeList.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000514211262172500033472 0ustar twernertwerner// $Id: PostCodeList.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import java.lang.annotation.Target; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.TYPE; import java.util.Collection; import javax.validation.Constraint; import javax.validation.Payload; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; /** * A test constraint which can lead to a error when trying to reslove the validator. * * @author Hardy Ferentschik */ @Constraint(validatedBy = { PostCodeList.PostCodeListValidatorForString.class, PostCodeList.PostCodeListValidatorForNumber.class }) @Documented @Target({ METHOD, FIELD, TYPE }) @Retention(RUNTIME) public @interface PostCodeList { public abstract String message() default "foobar"; public abstract Class[] groups() default { }; public abstract Class[] payload() default {}; public class PostCodeListValidatorForNumber implements ConstraintValidator> { public void initialize(PostCodeList constraintAnnotation) { } public boolean isValid(Collection value, ConstraintValidatorContext constraintValidatorContext) { return true; } } public class PostCodeListValidatorForString implements ConstraintValidator> { public void initialize(PostCodeList constraintAnnotation) { } public boolean isValid(Collection value, ConstraintValidatorContext constraintValidatorContext) { if ( value == null ) { return true; } return false; } } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/constraints/Interval.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/const0000644000175000017500000000174611262172500033500 0ustar twernertwerner// $Id: Interval.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; /** * @author Hardy Ferentschik */ @StartLessThanEnd class Interval { int start; int end; } libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/0000755000175000017500000000000011402110331033205 5ustar twernertwerner././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/Properties.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/P0000644000175000017500000000224111265335074033352 0ustar twernertwerner// $Id: Properties.java 17743 2009-10-14 11:47:08Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2008, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; import java.util.List; /** * @author Hardy Ferentschik */ public class Properties { private List listOfString; public List getListOfString() { return listOfString; } public void setListOfString(List listOfString) { this.listOfString = listOfString; } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/MyInterface.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/M0000644000175000017500000000172711272032760033351 0ustar twernertwerner// $Id: MyInterface.java 17861 2009-10-28 12:15:44Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; /** * @author Hardy Ferentschik */ public interface MyInterface { Integer getId(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000000011402110332033363 5ustar twernertwerner././@LongLink0000000000000000000000000000021000000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/ICompetition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000171711274325274033422 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration; public interface ICompetition {} ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/IFixture.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000175611274325274033425 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration; public interface IFixture { ICompetition getCompetition(); } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000000011402110332033363 5ustar twernertwerner././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/GameDetail.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000260611274325274033420 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; import javax.validation.Valid; import javax.validation.constraints.NotNull; public class GameDetail { @NotNull @Valid private Competition competition; public GameDetail() { super(); } public GameDetail(Competition competition) { setCompetition( competition ); } public Competition getCompetition() { return competition; } public void setCompetition(Competition competition) { this.competition = competition; } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/Game.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000274511274325274033424 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; import javax.validation.Valid; import javax.validation.constraints.NotNull; public abstract class Game { @NotNull @Valid private GameDetail detail; private Game(GameDetail detail) { this.detail = detail; } public Game() { this( new GameDetail() ); } public Game(Competition competition) { this( new GameDetail( competition ) ); } public Competition getCompetition() { return detail.getCompetition(); } public void setCompetition(Competition competition) { detail.setCompetition( competition ); } } ././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/PersonCompetition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000214411274325274033415 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; public class PersonCompetition extends Competition { public PersonCompetition() { super(); } public PersonCompetition(String name) { super( name ); } } ././@LongLink0000000000000000000000000000022600000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/TeamCompetition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000213411274325274033414 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; public class TeamCompetition extends Competition { public TeamCompetition() { super(); } public TeamCompetition(String name) { super( name ); } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/Fixture.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000225111274325274033414 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; import org.hibernate.validator.xml.mixedconfiguration.IFixture; public class Fixture extends Game implements IFixture { public Fixture() { super(); } public Fixture(Competition competition) { super( competition ); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/annotation/Competition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000265211274325274033421 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.annotation; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; import org.hibernate.validator.xml.mixedconfiguration.ICompetition; public abstract class Competition implements ICompetition { @NotNull @Size(min = 1) private String name; public Competition() { super(); } public Competition(String name) { setName( name ); } public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/InheritanceMappingsTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000001133211274325274033414 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration; import java.lang.annotation.Annotation; import java.util.Set; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.constraints.NotNull; import static org.testng.AssertJUnit.assertEquals; import static org.testng.FileAssert.fail; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; /** * See HV-265 * * @author Hardy Ferentschik */ public class InheritanceMappingsTest { @Test public void defaultConfigurationNoExplicitAnnotationDefinition1() { validateAnnotatedFixture( new org.hibernate.validator.xml.mixedconfiguration.annotation.PersonCompetition(), configure() ); } @Test public void defaultConfigurationNoExplicitAnnotationDefinition2() { validateAnnotatedFixture( new org.hibernate.validator.xml.mixedconfiguration.annotation.TeamCompetition(), configure() ); } @Test public void customConfigurationNoExplicitAnnotationDefinition1() { validateAnnotatedFixture( new org.hibernate.validator.xml.mixedconfiguration.annotation.PersonCompetition(), configure( "annotation-mappings.xml" ) ); } @Test public void customConfigurationNoExplicitAnnotationDefinition2() { validateAnnotatedFixture( new org.hibernate.validator.xml.mixedconfiguration.annotation.TeamCompetition(), configure( "annotation-mappings.xml" ) ); } @Test public void customConfigurationExplicitXmlDefinition() { validateXmlDefinedFixture( new org.hibernate.validator.xml.mixedconfiguration.xml.PersonCompetition(), configure( "xml-mappings.xml" ) ); } @Test public void customConfigurationNoExplicitXmlDefinition() { validateXmlDefinedFixture( new org.hibernate.validator.xml.mixedconfiguration.xml.TeamCompetition(), configure( "xml-mappings.xml" ) ); } private Validator configure() { return TestUtil.getValidator(); } private Validator configure(String mappingsUrl) { Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( InheritanceMappingsTest.class.getResourceAsStream( mappingsUrl ) ); ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); return validatorFactory.getValidator(); } private void validateFixture(IFixture fixture, Validator validator) { Set> violations = validator.validate( fixture ); for ( ConstraintViolation violation : violations ) { if ( violation.getLeafBean() instanceof ICompetition && "detail.competition.name".equals( violation.getPropertyPath().toString() ) ) { assertEquals( violation.getLeafBean(), fixture.getCompetition() ); Annotation annotation = ( ( Annotation ) violation.getConstraintDescriptor().getAnnotation() ); assertEquals( annotation.annotationType(), NotNull.class ); return; } } fail( "@NotNull constraint violation for 'detail.competition.name' not detected" ); } private void validateAnnotatedFixture(org.hibernate.validator.xml.mixedconfiguration.annotation.Competition competition, Validator validator) { org.hibernate.validator.xml.mixedconfiguration.annotation.Fixture fixture = new org.hibernate.validator.xml.mixedconfiguration.annotation.Fixture(); fixture.setCompetition( competition ); validateFixture( fixture, validator ); } private void validateXmlDefinedFixture(org.hibernate.validator.xml.mixedconfiguration.xml.Competition competition, Validator validator) { org.hibernate.validator.xml.mixedconfiguration.xml.Fixture fixture = new org.hibernate.validator.xml.mixedconfiguration.xml.Fixture(); fixture.setCompetition( competition ); validateFixture( fixture, validator ); } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000000011402110332033363 5ustar twernertwerner././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/GameDetail.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000243311274325274033416 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; public class GameDetail { private Competition competition; public GameDetail() { super(); } public GameDetail(Competition competition) { setCompetition( competition ); } public Competition getCompetition() { return competition; } public void setCompetition(Competition competition) { this.competition = competition; } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/Game.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000257211274325274033422 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; public abstract class Game { private GameDetail detail; private Game(GameDetail detail) { this.detail = detail; } public Game() { this( new GameDetail() ); } public Game(Competition competition) { this( new GameDetail( competition ) ); } public Competition getCompetition() { return detail.getCompetition(); } public void setCompetition(Competition competition) { detail.setCompetition( competition ); } } ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/PersonCompetition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000213511274325274033415 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; public class PersonCompetition extends Competition { public PersonCompetition() { super(); } public PersonCompetition(String name) { super( name ); } } ././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/TeamCompetition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000212711274325274033416 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; public class TeamCompetition extends Competition { public TeamCompetition() { super(); } public TeamCompetition(String name) { super( name ); } } ././@LongLink0000000000000000000000000000020700000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/Fixture.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000242411274325274033416 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; import org.hibernate.validator.xml.mixedconfiguration.IFixture; public class Fixture extends Game implements IFixture { public Fixture() { super(); } public Fixture(Competition competition) { super( competition ); } @Override public void setCompetition(Competition competition) { super.setCompetition( competition ); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/mixedconfiguration/xml/Competition.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/m0000755000175000017500000000245411274325274033421 0ustar twernertwerner// $Id: AnnotationFactoryTest.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml.mixedconfiguration.xml; import org.hibernate.validator.xml.mixedconfiguration.ICompetition; public abstract class Competition implements ICompetition { private String name; public Competition() { super(); } public Competition(String name) { setName( name ); } public String getName() { return name; } public void setName(String name) { this.name = name; } } ././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/Person.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/P0000644000175000017500000000205211262172500033340 0ustar twernertwerner// $Id: Person.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; /** * @author Hardy Ferentschik */ public interface Person { String getFirstName(); String getMiddleName(); String getLastName(); } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/XmlMappingTest.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/X0000644000175000017500000001051111274325274033362 0ustar twernertwerner// $Id: XmlMappingTest.java 17911 2009-11-04 16:24:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.Configuration; import javax.validation.ConstraintViolation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import javax.validation.groups.Default; import static org.testng.Assert.assertEquals; import org.testng.annotations.Test; import org.hibernate.validator.util.TestUtil; /** * @author Hardy Ferentschik */ public class XmlMappingTest { @Test /** * HV-214 */ public void testConstraintInheritanceWithXmlConfiguration() { final Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "mapping.xml" ) ); final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); final Validator validator = validatorFactory.getValidator(); final Set> violations = validator.validate( new Customer(), Default.class ); assertEquals( violations.size(), 1 ); } @Test /** * HV-252 */ public void testListOfString() { final Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "properties-mapping.xml" ) ); final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); final Validator validator = validatorFactory.getValidator(); List listOfString = new ArrayList(); listOfString.add( "one" ); listOfString.add( "two" ); listOfString.add( "three" ); final Set> violations = validator.validateValue( Properties.class, "listOfString", listOfString ); assertEquals( violations.size(), 0 ); } @Test /** * HV-262 */ public void testInterfaceConfiguration() { final Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "my-interface-mapping.xml" ) ); final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); final Validator validator = validatorFactory.getValidator(); final Set> violations = validator.validate( new MyInterfaceImpl() ); assertEquals( violations.size(), 1 ); } @Test /** * HV-262 */ public void testInterfaceImplementationConfiguration() { final Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "my-interface-impl-mapping.xml" ) ); final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); final Validator validator = validatorFactory.getValidator(); final Set> violations = validator.validate( new MyInterfaceImpl() ); assertEquals( violations.size(), 1 ); } @Test /** * HV-263 */ public void testEmptyInterfaceConfiguration() { final Configuration configuration = TestUtil.getConfiguration(); configuration.addMapping( XmlMappingTest.class.getResourceAsStream( "empty-my-interface-mapping.xml" ) ); final ValidatorFactory validatorFactory = configuration.buildValidatorFactory(); final Validator validator = validatorFactory.getValidator(); final Set> violations = validator.validate( new MyInterfaceImpl() ); assertEquals( violations.size(), 0 ); } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/MyInterfaceImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/M0000644000175000017500000000201211272032760033335 0ustar twernertwerner// $Id: MyInterfaceImpl.java 17861 2009-10-28 12:15:44Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; /** * @author Hardy Ferentschik */ public class MyInterfaceImpl implements MyInterface { public Integer getId() { return null; } }././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/Customer.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/java/org/hibernate/validator/xml/C0000644000175000017500000000367211262172500033334 0ustar twernertwerner// $Id: Customer.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; /** * @author Hardy Ferentschik */ public class Customer implements Person { private String firstName; private String middleName; private String lastName; private String customerId; private String password; public String getFirstName() { return this.firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getMiddleName() { return this.middleName; } public void setMiddleName(final String middleName) { this.middleName = middleName; } public String getLastName() { return this.lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } public String getCustomerId() { return this.customerId; } public void setCustomerId(final String customerId) { this.customerId = customerId; } public String getPassword() { return this.password; } public void setPassword(final String password) { this.password = password; } } libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/suite/0000755000175000017500000000000011402110345026105 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/test/suite/unit-tests.xml0000644000175000017500000000224311274325274030767 0ustar twernertwerner libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/0000755000175000017500000000000011402110364024722 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/0000755000175000017500000000000011402110364026734 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/0000755000175000017500000000000011402110364027523 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/0000755000175000017500000000000011402110364031464 5ustar twernertwerner././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/0000755000175000017500000000000011402110364033451 5ustar twernertwerner././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/ValidationMessages.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/0000644000175000017500000000254511274520070033467 0ustar twernertwerner# $Id: ValidationMessages.properties 17927 2009-11-05 09:51:52Z hardy.ferentschik $ javax.validation.constraints.AssertFalse.message=must be false javax.validation.constraints.AssertTrue.message=must be true javax.validation.constraints.DecimalMax.message=must be less than or equal to {value} javax.validation.constraints.DecimalMin.message=must be greater than or equal to {value} javax.validation.constraints.Digits.message=numeric value out of bounds (<{integer} digits>.<{fraction} digits> expected) javax.validation.constraints.Future.message=must be in the future javax.validation.constraints.Max.message=must be less than or equal to {value} javax.validation.constraints.Min.message=must be greater than or equal to {value} javax.validation.constraints.NotNull.message=may not be null javax.validation.constraints.Null.message=must be null javax.validation.constraints.Past.message=must be in the past javax.validation.constraints.Pattern.message=must match "{regexp}" javax.validation.constraints.Size.message=size must be between {min} and {max} org.hibernate.validator.constraints.Email.message=not a well-formed email address org.hibernate.validator.constraints.Length.message=length must be between {min} and {max} org.hibernate.validator.constraints.NotEmpty.message=may not be empty org.hibernate.validator.constraints.Range.message=must be between {min} and {max} ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/ValidationMessages_fr.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/0000644000175000017500000000266211274520070033467 0ustar twernertwerner# $Id: ValidationMessages_fr.properties 17927 2009-11-05 09:51:52Z hardy.ferentschik $ javax.validation.constraints.NotNull.message=ne peut pas \u00EAtre nul javax.validation.constraints.Size.message=la taille doit \u00EAtre entre {min} et {max} org.hibernate.validator.constraints.Length.message=length must be between {min} and {max} org.hibernate.validator.constraints.NotEmpty.message=ne peut pas \u00EAtre vide javax.validation.constraints.Pattern.message=doit suivre "{regexp}" javax.validation.constraints.Min.message=doit \u00EAtre plus grand que {value} javax.validation.constraints.Max.message=doit \u00EAtre plus petit que {value} javax.validation.constraints.Null.message=doit \u00EAtre nul javax.validation.constraints.Past.message=doit \u00EAtre dans le pass\u00E9 javax.validation.constraints.Future.message=doit \u00EAtre dans le futur javax.validation.constraints.AssertTrue.message=doit \u00EAtre vrai javax.validation.constraints.AssertFalse.message=doit \u00EAtre faux javax.validation.constraints.Digits.message=Valeur num\u00E9rique hors limite (<{integer} chiffres>.<{fraction} chiffres> attendus) javax.validation.constraints.DecimalMin.message=doit \u00EAtre plus grand que {value} javax.validation.constraints.DecimalMax.message=doit \u00EAtre plus petit que {value} org.hibernate.validator.constraints.Email.message=Address email mal form\u00E9e org.hibernate.validator.constraints.Range.message=doit \u00EAtre entre {min} et {max}././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/ValidationMessages_de.propertieslibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/org/hibernate/validator/0000644000175000017500000000264511274520070033470 0ustar twernertwerner# $Id: ValidationMessages_de.properties 17927 2009-11-05 09:51:52Z hardy.ferentschik $ javax.validation.constraints.NotNull.message=kann nicht null sein javax.validation.constraints.Size.message=muss zwischen {min} und {max} liegen org.hibernate.validator.constraints.Length.message=muss zwischen {min} und {max} liegen org.hibernate.validator.constraints.NotEmpty.message=kann nicht leer sein javax.validation.constraints.Pattern.message=muss auf Ausdruck "{regexp}" passen javax.validation.constraints.Min.message=muss gr\u00F6ssergleich {value} sein javax.validation.constraints.Max.message=muss kleinergleich {value} sein javax.validation.constraints.Null.message=muss null sein javax.validation.constraints.Past.message=muss in der Vergangenheit liegen javax.validation.constraints.Future.message=muss in der Zukunft liegen javax.validation.constraints.AssertTrue.message=muss wahr sein javax.validation.constraints.AssertFalse.message=muss falsch sein javax.validation.constraints.Digits.message=numerischer Wert au\u00DFerhalb erlaubten Wertebereichs (<{integer} Ziffern>.<{fraction} Ziffern> erwarted) javax.validation.constraints.DecimalMin.message=muss gr\u00F6ssergleich {value} sein javax.validation.constraints.DecimalMax.message=muss kleinergleich {value} sein org.hibernate.validator.constraints.Email.message=keine g\u00FCltige E-Mail-Adresse org.hibernate.validator.constraints.Range.message=muss zwischen {min} und {max} liegenlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/META-INF/0000755000175000017500000000000011402110364030074 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/META-INF/MANIFEST.MF0000644000175000017500000000050611077114573031545 0ustar twernertwernerManifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven Built-By: ${user.name} Build-Jdk: ${java.version} Implementation-Title: ${pom.artifactId} Implementation-Vendor: ${pom.groupId} Implementation-Vendor-Id: ${pom.groupId} Implementation-Version: ${pom.version} Specification-Title: Bean Validation libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/META-INF/services/0000755000175000017500000000000011402110364031717 5ustar twernertwerner././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/META-INF/services/javax.validation.spi.ValidationProviderlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/resources/META-INF/services/javax.0000644000175000017500000000005211245224703033036 0ustar twernertwernerorg.hibernate.validator.HibernateValidatorlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xjb/0000755000175000017500000000000011402110364025505 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xjb/binding-customization.xjb0000644000175000017500000000127111245471114032543 0ustar twernertwerner libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/0000755000175000017500000000000011402110353025641 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/0000755000175000017500000000000011402110353026430 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/0000755000175000017500000000000011402110353030371 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/0000755000175000017500000000000011402110362032356 5ustar twernertwerner././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/HibernateValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/Hiber0000755000175000017500000000373311262172500033351 0ustar twernertwerner// $Id: HibernateValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator; import javax.validation.Configuration; import javax.validation.ValidatorFactory; import javax.validation.spi.BootstrapState; import javax.validation.spi.ConfigurationState; import javax.validation.spi.ValidationProvider; import org.hibernate.validator.engine.ConfigurationImpl; import org.hibernate.validator.HibernateValidatorConfiguration; import org.hibernate.validator.engine.ValidatorFactoryImpl; /** * Default implementation of ValidationProvider within Hibernate validator. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class HibernateValidator implements ValidationProvider { public HibernateValidatorConfiguration createSpecializedConfiguration(BootstrapState state) { return HibernateValidatorConfiguration.class.cast( new ConfigurationImpl( this ) ); } public Configuration createGenericConfiguration(BootstrapState state) { return new ConfigurationImpl( state ); } public ValidatorFactory buildValidatorFactory(ConfigurationState configurationState) { return new ValidatorFactoryImpl( configurationState ); } } ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000755000175000017500000000000011402110357033403 5ustar twernertwerner././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/NodeImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000622411265426106033422 0ustar twernertwerner// $Id: NodeImpl.java 17748 2009-10-14 19:53:42Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.io.Serializable; import javax.validation.Path; /** * @author Hardy Ferentschik */ public class NodeImpl implements Path.Node, Serializable { private static final long serialVersionUID = 2075466571633860499L; private static final String INDEX_OPEN = "["; private static final String INDEX_CLOSE = "]"; private final String name; private boolean isInIterable; private Integer index; private Object key; public NodeImpl(String name) { this.name = name; } NodeImpl(Path.Node node) { this.name = node.getName(); this.isInIterable = node.isInIterable(); this.index = node.getIndex(); this.key = node.getKey(); } public String getName() { return name; } public boolean isInIterable() { return isInIterable; } public void setInIterable(boolean inIterable) { isInIterable = inIterable; } public Integer getIndex() { return index; } public void setIndex(Integer index) { isInIterable = true; this.index = index; } public Object getKey() { return key; } public void setKey(Object key) { isInIterable = true; this.key = key; } @Override public String toString() { StringBuilder builder = new StringBuilder( name == null ? "" : name ); if ( isInIterable ) { builder.append( INDEX_OPEN ); if ( getIndex() != null ) { builder.append( getIndex() ); } else if ( getKey() != null ) { builder.append( getKey() ); } builder.append( INDEX_CLOSE ); } return builder.toString(); } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } NodeImpl node = ( NodeImpl ) o; if ( isInIterable != node.isInIterable ) { return false; } if ( index != null ? !index.equals( node.index ) : node.index != null ) { return false; } if ( key != null ? !key.equals( node.key ) : node.key != null ) { return false; } if ( name != null ? !name.equals( node.name ) : node.name != null ) { return false; } return true; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + ( isInIterable ? 1 : 0 ); result = 31 * result + ( index != null ? index.hashCode() : 0 ); result = 31 * result + ( key != null ? key.hashCode() : 0 ); return result; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000007501211272032647033424 0ustar twernertwerner// $Id: ValidatorImpl.java 17860 2009-10-28 12:14:31Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.ConstraintViolation; import javax.validation.MessageInterpolator; import javax.validation.Path; import javax.validation.TraversableResolver; import javax.validation.ValidationException; import javax.validation.Validator; import javax.validation.groups.Default; import javax.validation.metadata.BeanDescriptor; import com.googlecode.jtype.TypeUtils; import org.hibernate.validator.engine.groups.Group; import org.hibernate.validator.engine.groups.GroupChain; import org.hibernate.validator.engine.groups.GroupChainGenerator; import org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver; import org.hibernate.validator.metadata.BeanMetaData; import org.hibernate.validator.metadata.BeanMetaDataCache; import org.hibernate.validator.metadata.BeanMetaDataImpl; import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.MetaConstraint; import org.hibernate.validator.util.ReflectionHelper; /** * The main Bean Validation class. This is the core processing class of Hibernate Validator. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ValidatorImpl implements Validator { /** * The default group array used in case any of the validate methods is called without a group. */ private static final Class[] DEFAULT_GROUP_ARRAY = new Class[] { Default.class }; /** * Used to resolve the group execution order for a validate call. */ private final transient GroupChainGenerator groupChainGenerator; private final ConstraintValidatorFactory constraintValidatorFactory; /** * {@link MessageInterpolator} as passed to the constructor of this instance. */ private final MessageInterpolator messageInterpolator; /** * {@link TraversableResolver} as passed to the constructor of this instance. * Never use it directly, always use {@link #getCachingTraversableResolver()} to retrieved the single threaded caching wrapper. */ private final TraversableResolver traversableResolver; /** * Passed at creation time of this validator instance. */ private final ConstraintHelper constraintHelper; /** * Used to get access to the bean meta data. Used to avoid to parsing the constraint configuration for each call * of a given entity. */ private final BeanMetaDataCache beanMetaDataCache; public ValidatorImpl(ConstraintValidatorFactory constraintValidatorFactory, MessageInterpolator messageInterpolator, TraversableResolver traversableResolver, ConstraintHelper constraintHelper, BeanMetaDataCache beanMetaDataCache) { this.constraintValidatorFactory = constraintValidatorFactory; this.messageInterpolator = messageInterpolator; this.traversableResolver = traversableResolver; this.constraintHelper = constraintHelper; this.beanMetaDataCache = beanMetaDataCache; groupChainGenerator = new GroupChainGenerator(); } public Set> validate(T object, Class... groups) { if ( object == null ) { throw new IllegalArgumentException( "Validation of a null object" ); } GroupChain groupChain = determineGroupExecutionOrder( groups ); GlobalExecutionContext context = GlobalExecutionContext.getContextForValidate( object, messageInterpolator, constraintValidatorFactory, getCachingTraversableResolver() ); List> list = validateInContext( object, context, groupChain, null ); return new HashSet>( list ); } public Set> validateProperty(T object, String propertyName, Class... groups) { if ( object == null ) { throw new IllegalArgumentException( "Validated object cannot be null." ); } sanityCheckPropertyPath( propertyName ); GroupChain groupChain = determineGroupExecutionOrder( groups ); List> failingConstraintViolations = new ArrayList>(); validateProperty( object, PathImpl.createPathFromString( propertyName ), failingConstraintViolations, groupChain ); return new HashSet>( failingConstraintViolations ); } public Set> validateValue(Class beanType, String propertyName, Object value, Class... groups) { if ( beanType == null ) { throw new IllegalArgumentException( "The bean type cannot be null." ); } sanityCheckPropertyPath( propertyName ); GroupChain groupChain = determineGroupExecutionOrder( groups ); List> failingConstraintViolations = new ArrayList>(); validateValue( beanType, value, PathImpl.createPathFromString( propertyName ), failingConstraintViolations, groupChain ); return new HashSet>( failingConstraintViolations ); } /** * {@inheritDoc} */ public BeanDescriptor getConstraintsForClass(Class clazz) { return getBeanMetaData( clazz ).getBeanDescriptor(); } public T unwrap(Class type) { throw new ValidationException( "Type " + type + " not supported" ); } private void sanityCheckPropertyPath(String propertyName) { if ( propertyName == null || propertyName.length() == 0 ) { throw new IllegalArgumentException( "Invalid property path." ); } } private GroupChain determineGroupExecutionOrder(Class[] groups) { if ( groups == null ) { throw new IllegalArgumentException( "null passed as group name" ); } // if no groups is specified use the default if ( groups.length == 0 ) { groups = DEFAULT_GROUP_ARRAY; } return groupChainGenerator.getGroupChainFor( Arrays.asList( groups ) ); } /** * Validates the given object using the available context information. * * @param value The value to validate. * @param context Global context. Used amongst others to collect all failing constraints. * @param groupChain Contains the information which and in which order groups have to be executed * @param path The current path of the validation. * @param The root bean type. * @param The type of the current object on the validation stack. * * @return List of constraint violations or the empty set if there were no violations. */ private List> validateInContext(U value, GlobalExecutionContext context, GroupChain groupChain, PathImpl path) { if ( value == null ) { return Collections.emptyList(); } path = PathImpl.createShallowCopy( path ); LocalExecutionContext localExecutionContext = LocalExecutionContext.getLocalExecutionContext( value ); BeanMetaData beanMetaData = getBeanMetaData( localExecutionContext.getCurrentBeanType() ); if ( beanMetaData.defaultGroupSequenceIsRedefined() ) { groupChain.assertDefaultGroupSequenceIsExpandable( beanMetaData.getDefaultGroupSequence() ); } // process first single groups. For these we can skip some object traversal, by first running all validations on the current bean // before traversing the object. Iterator groupIterator = groupChain.getGroupIterator(); while ( groupIterator.hasNext() ) { Group group = groupIterator.next(); localExecutionContext.setCurrentGroup( group.getGroup() ); validateConstraintsForCurrentGroup( context, localExecutionContext, path ); } groupIterator = groupChain.getGroupIterator(); while ( groupIterator.hasNext() ) { Group group = groupIterator.next(); localExecutionContext.setCurrentGroup( group.getGroup() ); validateCascadedConstraints( context, localExecutionContext, path ); } // now we process sequences. For sequences I have to traverse the object graph since I have to stop processing when an error occurs. Iterator> sequenceIterator = groupChain.getSequenceIterator(); while ( sequenceIterator.hasNext() ) { List sequence = sequenceIterator.next(); for ( Group group : sequence ) { int numberOfViolations = context.getFailingConstraints().size(); localExecutionContext.setCurrentGroup( group.getGroup() ); validateConstraintsForCurrentGroup( context, localExecutionContext, path ); validateCascadedConstraints( context, localExecutionContext, path ); if ( context.getFailingConstraints().size() > numberOfViolations ) { break; } } } return context.getFailingConstraints(); } private void validateConstraintsForCurrentGroup(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, PathImpl path) { BeanMetaData beanMetaData = getBeanMetaData( localExecutionContext.getCurrentBeanType() ); boolean validatingDefault = localExecutionContext.validatingDefault(); boolean validatedBeanRedefinesDefault = beanMetaData.defaultGroupSequenceIsRedefined(); // if we are not validating the default group there is nothing special to consider if ( !validatingDefault ) { validateConstraintsForNonDefaultGroup( globalExecutionContext, localExecutionContext, path ); return; } // if we are validating the default group we have to distinguish between the case where the main entity type redefines the default group and // where not if ( validatedBeanRedefinesDefault ) { validateConstraintsForRedefinedDefaultGroupOnMainEntity( globalExecutionContext, localExecutionContext, path, beanMetaData ); } else { validateConstraintsForRedefinedDefaultGroup( globalExecutionContext, localExecutionContext, path, beanMetaData ); } } private void validateConstraintsForRedefinedDefaultGroup(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, PathImpl path, BeanMetaData beanMetaData) { // in the case where the main entity does not redefine the default group we have to check whether the entity which defines the constraint does for ( Map.Entry, List>> entry : beanMetaData.getMetaConstraintsAsMap() .entrySet() ) { Class hostingBeanClass = entry.getKey(); List> constraints = entry.getValue(); List> defaultGroupSequence = getBeanMetaData( hostingBeanClass ).getDefaultGroupSequence(); for ( Class defaultSequenceMember : defaultGroupSequence ) { localExecutionContext.setCurrentGroup( defaultSequenceMember ); boolean validationSuccessful = true; for ( MetaConstraint metaConstraint : constraints ) { boolean tmp = validateConstraint( globalExecutionContext, localExecutionContext, metaConstraint, path ); validationSuccessful = validationSuccessful && tmp; } if ( !validationSuccessful ) { break; } } } } private void validateConstraintsForRedefinedDefaultGroupOnMainEntity(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, PathImpl path, BeanMetaData beanMetaData) { // in the case where the main entity redefines the default group we can iterate over all constraints independent of the bean they are // defined in. The redefined group sequence applies for all constraints. List> defaultGroupSequence = beanMetaData.getDefaultGroupSequence(); for ( Class defaultSequenceMember : defaultGroupSequence ) { localExecutionContext.setCurrentGroup( defaultSequenceMember ); boolean validationSuccessful = true; for ( MetaConstraint metaConstraint : beanMetaData.getMetaConstraintsAsList() ) { boolean tmp = validateConstraint( globalExecutionContext, localExecutionContext, metaConstraint, path ); validationSuccessful = validationSuccessful && tmp; } if ( !validationSuccessful ) { break; } } } private void validateConstraintsForNonDefaultGroup(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, PathImpl path) { BeanMetaData beanMetaData = getBeanMetaData( localExecutionContext.getCurrentBeanType() ); for ( MetaConstraint metaConstraint : beanMetaData.getMetaConstraintsAsList() ) { validateConstraint( globalExecutionContext, localExecutionContext, metaConstraint, path ); } } private boolean validateConstraint(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, MetaConstraint metaConstraint, PathImpl path) { boolean validationSuccessful = true; PathImpl newPath; if ( path == null ) { newPath = PathImpl.createNewPath( metaConstraint.getPropertyName() ); } else { newPath = PathImpl.createShallowCopy( path ); if ( metaConstraint.getElementType() != ElementType.TYPE ) { newPath.addNode( new NodeImpl( metaConstraint.getPropertyName() ) ); } } localExecutionContext.setPropertyPath( newPath ); if ( isValidationRequired( globalExecutionContext, localExecutionContext, metaConstraint ) ) { Object valueToValidate = metaConstraint.getValue( localExecutionContext.getCurrentBean() ); localExecutionContext.setCurrentValidatedValue( ( V ) valueToValidate ); validationSuccessful = metaConstraint.validateConstraint( globalExecutionContext, localExecutionContext ); } globalExecutionContext.markProcessed( localExecutionContext.getCurrentBean(), localExecutionContext.getCurrentGroup(), localExecutionContext.getPropertyPath() ); return validationSuccessful; } /** * Validates all cascaded constraints for the given bean using the current group set in the execution context. * This method must always be called after validateConstraints for the same context. * * @param globalExecutionContext The execution context * @param localExecutionContext Collected information for single validation * @param path The current path of the validation. */ private void validateCascadedConstraints(GlobalExecutionContext globalExecutionContext, LocalExecutionContext localExecutionContext, PathImpl path) { List cascadedMembers = getBeanMetaData( localExecutionContext.getCurrentBeanType() ) .getCascadedMembers(); for ( Member member : cascadedMembers ) { Type type = ReflectionHelper.typeOf( member ); PathImpl newPath; if ( path == null ) { newPath = PathImpl.createNewPath( ReflectionHelper.getPropertyName( member ) ); } else { newPath = PathImpl.createShallowCopy( path ); newPath.addNode( new NodeImpl( ReflectionHelper.getPropertyName( member ) ) ); } localExecutionContext.setPropertyPath( newPath ); if ( isCascadeRequired( globalExecutionContext, localExecutionContext, member ) ) { Object value = ReflectionHelper.getValue( member, localExecutionContext.getCurrentBean() ); if ( value != null ) { Iterator iter = createIteratorForCascadedValue( localExecutionContext, type, value ); boolean isIndexable = isIndexable( type ); validateCascadedConstraint( globalExecutionContext, iter, isIndexable, localExecutionContext.getCurrentGroup(), localExecutionContext.getPropertyPath() ); } } } } /** * Called when processing cascaded constraints. This methods inspects the type of the cascaded constraints and in case * of a list or array creates an iterator in order to validate each element. * * @param context the validation context. * @param type the type of the cascaded field or property. * @param value the actual value. * * @return An iterator over the value of a cascaded property. */ private Iterator createIteratorForCascadedValue(LocalExecutionContext context, Type type, Object value) { Iterator iter; if ( ReflectionHelper.isIterable( type ) ) { iter = ( ( Iterable ) value ).iterator(); context.markCurrentPropertyAsIterable(); } else if ( ReflectionHelper.isMap( type ) ) { Map map = ( Map ) value; iter = map.entrySet().iterator(); context.markCurrentPropertyAsIterable(); } else if ( TypeUtils.isArray( type ) ) { List arrayList = Arrays.asList( ( Object[] ) value ); iter = arrayList.iterator(); context.markCurrentPropertyAsIterable(); } else { List list = new ArrayList(); list.add( value ); iter = list.iterator(); } return iter; } /** * Called when processing cascaded constraints. This methods inspects the type of the cascaded constraints and in case * of a list or array creates an iterator in order to validate each element. * * @param type the type of the cascaded field or property. * * @return An iterator over the value of a cascaded property. */ private boolean isIndexable(Type type) { boolean isIndexable = false; if ( ReflectionHelper.isList( type ) ) { isIndexable = true; } else if ( ReflectionHelper.isMap( type ) ) { isIndexable = true; } else if ( TypeUtils.isArray( type ) ) { isIndexable = true; } return isIndexable; } @SuppressWarnings("RedundantArrayCreation") private void validateCascadedConstraint(GlobalExecutionContext context, Iterator iter, boolean isIndexable, Class currentGroup, PathImpl currentPath) { Object value; Integer index; Object mapKey; int i = 0; while ( iter.hasNext() ) { value = iter.next(); index = i; if ( value instanceof Map.Entry ) { mapKey = ( ( Map.Entry ) value ).getKey(); value = ( ( Map.Entry ) value ).getValue(); currentPath.getLeafNode().setKey( mapKey ); } else if ( isIndexable ) { currentPath.getLeafNode().setIndex( index ); } if ( !context.isAlreadyValidated( value, currentGroup, currentPath ) ) { GroupChain groupChain = groupChainGenerator.getGroupChainFor( Arrays.asList( new Class[] { currentGroup } ) ); validateInContext( value, context, groupChain, currentPath ); } i++; } } private void validateProperty(T object, PathImpl propertyPath, List> failingConstraintViolations, GroupChain groupChain) { @SuppressWarnings("unchecked") final Class beanType = ( Class ) object.getClass(); Set> metaConstraints = new HashSet>(); Object hostingBeanInstance = collectMetaConstraintsForPath( beanType, object, propertyPath.iterator(), metaConstraints ); if ( hostingBeanInstance == null ) { throw new IllegalArgumentException( "Invalid property path." ); } if ( metaConstraints.size() == 0 ) { return; } //this method is at the root of validateProperty calls, share the same cachedTR TraversableResolver cachedResolver = getCachingTraversableResolver(); Iterator groupIterator = groupChain.getGroupIterator(); while ( groupIterator.hasNext() ) { Group group = groupIterator.next(); validatePropertyForGroup( object, propertyPath, failingConstraintViolations, metaConstraints, hostingBeanInstance, group, cachedResolver ); } Iterator> sequenceIterator = groupChain.getSequenceIterator(); while ( sequenceIterator.hasNext() ) { List sequence = sequenceIterator.next(); int numberOfConstraintViolationsBefore = failingConstraintViolations.size(); for ( Group group : sequence ) { validatePropertyForGroup( object, propertyPath, failingConstraintViolations, metaConstraints, hostingBeanInstance, group, cachedResolver ); if ( failingConstraintViolations.size() > numberOfConstraintViolationsBefore ) { break; } } } } private void validatePropertyForGroup( T object, PathImpl path, List> failingConstraintViolations, Set> metaConstraints, U hostingBeanInstance, Group group, TraversableResolver cachedTraversableResolver) { int numberOfConstraintViolationsBefore = failingConstraintViolations.size(); BeanMetaData beanMetaData = getBeanMetaData( metaConstraints.iterator().next().getBeanClass() ); List> groupList; if ( group.isDefaultGroup() ) { groupList = beanMetaData.getDefaultGroupSequence(); } else { groupList = new ArrayList>(); groupList.add( group.getGroup() ); } for ( Class groupClass : groupList ) { for ( MetaConstraint metaConstraint : metaConstraints ) { GlobalExecutionContext context = GlobalExecutionContext.getContextForValidateProperty( object, messageInterpolator, constraintValidatorFactory, cachedTraversableResolver ); LocalExecutionContext localContext = LocalExecutionContext.getLocalExecutionContext( hostingBeanInstance ); localContext.setPropertyPath( path ); localContext.setCurrentGroup( groupClass ); if ( isValidationRequired( context, localContext, metaConstraint ) ) { Object valueToValidate = metaConstraint.getValue( localContext.getCurrentBean() ); localContext.setCurrentValidatedValue( ( V ) valueToValidate ); metaConstraint.validateConstraint( context, localContext ); failingConstraintViolations.addAll( context.getFailingConstraints() ); } } if ( failingConstraintViolations.size() > numberOfConstraintViolationsBefore ) { break; } } } @SuppressWarnings("unchecked") private void validateValue(Class beanType, Object value, PathImpl propertyPath, List> failingConstraintViolations, GroupChain groupChain) { Set> metaConstraints = new HashSet>(); collectMetaConstraintsForPath( beanType, null, propertyPath.iterator(), metaConstraints ); if ( metaConstraints.size() == 0 ) { return; } //root of validateValue calls, share the same cached TraversableResolver TraversableResolver cachedTraversableResolver = getCachingTraversableResolver(); // process groups Iterator groupIterator = groupChain.getGroupIterator(); while ( groupIterator.hasNext() ) { Group group = groupIterator.next(); validateValueForGroup( beanType, value, propertyPath, failingConstraintViolations, metaConstraints, group, cachedTraversableResolver ); } // process sequences Iterator> sequenceIterator = groupChain.getSequenceIterator(); while ( sequenceIterator.hasNext() ) { List sequence = sequenceIterator.next(); int numberOfConstraintViolations = failingConstraintViolations.size(); for ( Group group : sequence ) { validateValueForGroup( beanType, value, propertyPath, failingConstraintViolations, metaConstraints, group, cachedTraversableResolver ); if ( failingConstraintViolations.size() > numberOfConstraintViolations ) { break; } } } } private void validateValueForGroup( Class beanType, V value, PathImpl path, List> failingConstraintViolations, Set> metaConstraints, Group group, TraversableResolver cachedTraversableResolver) { int numberOfConstraintViolations = failingConstraintViolations.size(); BeanMetaData beanMetaData = getBeanMetaData( metaConstraints.iterator().next().getBeanClass() ); List> groupList; if ( group.isDefaultGroup() ) { groupList = beanMetaData.getDefaultGroupSequence(); } else { groupList = new ArrayList>(); groupList.add( group.getGroup() ); } for ( Class groupClass : groupList ) { for ( MetaConstraint metaConstraint : metaConstraints ) { GlobalExecutionContext context = GlobalExecutionContext.getContextForValidateValue( beanType, messageInterpolator, constraintValidatorFactory, cachedTraversableResolver ); LocalExecutionContext localContext = LocalExecutionContext.getLocalExecutionContext( beanType ); localContext.setPropertyPath( path ); localContext.setCurrentGroup( groupClass ); localContext.setCurrentValidatedValue( value ); if ( isValidationRequired( context, localContext, metaConstraint ) ) { metaConstraint.validateConstraint( context, localContext ); failingConstraintViolations.addAll( context.getFailingConstraints() ); } } if ( failingConstraintViolations.size() > numberOfConstraintViolations ) { break; } } } /** * Collects all MetaConstraints which match the given path relative to the specified root class. *

* This method is called recursively. *

* * @param clazz the class type to check for constraints. * @param value While resolving the property path this instance points to the current object. Might be null. * @param propertyIter an instance of PropertyIterator in order to iterate the items of the original property path. * @param metaConstraints Set of MetaConstraints to collect all matching constraints. * * @return Returns the bean hosting the constraints which match the specified property path. */ private Object collectMetaConstraintsForPath(Class clazz, Object value, Iterator propertyIter, Set> metaConstraints) { Path.Node elem = propertyIter.next(); final BeanMetaData metaData = getBeanMetaData( clazz ); //use precomputed method list as ReflectionHelper#containsMember is slow if ( !metaData.isPropertyPresent( elem.getName() ) ) { throw new IllegalArgumentException( "Invalid property path. There is no property " + elem.getName() + " in entity " + metaData.getBeanClass() .getName() ); } if ( !propertyIter.hasNext() ) { List> metaConstraintList = metaData.getMetaConstraintsAsList(); for ( MetaConstraint metaConstraint : metaConstraintList ) { if ( elem.getName() != null && elem.getName().equals( metaConstraint.getPropertyName() ) ) { metaConstraints.add( metaConstraint ); } } } else { List cascadedMembers = metaData.getCascadedMembers(); for ( Member m : cascadedMembers ) { if ( ReflectionHelper.getPropertyName( m ).equals( elem.getName() ) ) { Type type = ReflectionHelper.typeOf( m ); value = value == null ? null : ReflectionHelper.getValue( m, value ); if ( elem.isInIterable() ) { if ( value != null && elem.getIndex() != null ) { value = ReflectionHelper.getIndexedValue( value, elem.getIndex() ); } else if ( value != null && elem.getKey() != null ) { value = ReflectionHelper.getMappedValue( value, elem.getKey() ); } else if ( value != null ) { throw new IllegalArgumentException( "Property path must provide index or map key" ); } type = ReflectionHelper.getIndexedType( type ); } @SuppressWarnings("unchecked") Class valueClass = ( Class ) ( value == null ? type : value.getClass() ); return collectMetaConstraintsForPath( valueClass, value, propertyIter, metaConstraints ); } } } return value; } private BeanMetaData getBeanMetaData(Class beanClass) { BeanMetaDataImpl beanMetaData = beanMetaDataCache.getBeanMetaData( beanClass ); if ( beanMetaData == null ) { beanMetaData = new BeanMetaDataImpl( beanClass, constraintHelper, beanMetaDataCache ); beanMetaDataCache.addBeanMetaData( beanClass, beanMetaData ); } return beanMetaData; } /** * Must be called and stored for the duration of the stack call * A new instance is returned each time * * @return The resolver for the duration of a full validation. */ private TraversableResolver getCachingTraversableResolver() { return new SingleThreadCachedTraversableResolver( traversableResolver ); } private boolean isValidationRequired(GlobalExecutionContext globalContext, LocalExecutionContext localContext, MetaConstraint metaConstraint) { if ( !metaConstraint.getGroupList().contains( localContext.getCurrentGroup() ) ) { return false; } boolean isReachable; Path pathToObject = localContext.getPropertyPath().getPathWithoutLeafNode(); if ( pathToObject == null ) { pathToObject = PathImpl.createNewPath( null ); } try { isReachable = globalContext.getTraversableResolver().isReachable( localContext.getCurrentBean(), localContext.getPropertyPath().getLeafNode(), globalContext.getRootBeanClass(), pathToObject, metaConstraint.getElementType() ); } catch ( RuntimeException e ) { throw new ValidationException( "Call to TraversableResolver.isReachable() threw an exception", e ); } return isReachable; } private boolean isCascadeRequired(GlobalExecutionContext globalContext, LocalExecutionContext localContext, Member member) { final ElementType type = member instanceof Field ? ElementType.FIELD : ElementType.METHOD; boolean isReachable; boolean isCascadable; Path pathToObject = localContext.getPropertyPath().getPathWithoutLeafNode(); if ( pathToObject == null ) { pathToObject = PathImpl.createNewPath( null ); } try { isReachable = globalContext.getTraversableResolver().isReachable( localContext.getCurrentBean(), localContext.getPropertyPath().getLeafNode(), globalContext.getRootBeanClass(), pathToObject, type ); } catch ( RuntimeException e ) { throw new ValidationException( "Call to TraversableResolver.isReachable() threw an exception", e ); } try { isCascadable = globalContext.getTraversableResolver().isCascadable( localContext.getCurrentBean(), localContext.getPropertyPath().getLeafNode(), globalContext.getRootBeanClass(), pathToObject, type ); } catch ( RuntimeException e ) { throw new ValidationException( "Call to TraversableResolver.isCascadable() threw an exception", e ); } return isReachable && isCascadable; } } ././@LongLink0000000000000000000000000000020200000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/GlobalExecutionContext.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000002273111262172500033414 0ustar twernertwerner// $Id: GlobalExecutionContext.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.ConstraintViolation; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.metadata.ConstraintDescriptor; import org.hibernate.validator.util.IdentitySet; /** * Context object keeping track of all important data for a top level {@link javax.validation.Validator#validate(Object, Class[])} }, * {@link javax.validation.Validator#validateValue(Class, String, Object, Class[])} } or {@link javax.validation.Validator#validateProperty(Object, String, Class[])} call. *

* we use this object to collect all failing constraints, but also to cache the caching traversable resolver for a full stack call. * * @author Hardy Ferentschik * @author Emmanuel Bernard */ public class GlobalExecutionContext { /** * The root bean of the validation. */ private final T rootBean; /** * The root bean class of the validation. */ private final Class rootBeanClass; /** * Maps a group to an identity set to keep track of already validated objects. We have to make sure * that each object gets only validated once per group and property path. */ private final Map, IdentitySet> processedObjects; /** * Maps an object to a list of paths in which it has been invalidated. */ private final Map> processedPaths; /** * A list of all failing constraints so far. */ private final List> failingConstraintViolations; /** * Flag indicating whether an object can only be validated once per group or once per group AND validation path. * * @todo Make this boolean a configurable item. */ private boolean allowOneValidationPerPath = true; /** * The message resolver which should be used in this context. */ private final MessageInterpolator messageInterpolator; /** * The constraint factory which should be used in this context. */ private final ConstraintValidatorFactory constraintValidatorFactory; /** * Allows a JPA provider to decide whether a property should be validated. */ private final TraversableResolver traversableResolver; public static GlobalExecutionContext getContextForValidate(T object, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) { @SuppressWarnings("unchecked") Class rootBeanClass = ( Class ) object.getClass(); return new GlobalExecutionContext( rootBeanClass, object, messageInterpolator, constraintValidatorFactory, traversableResolver ); } public static GlobalExecutionContext getContextForValidateProperty(T rootBean, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) { @SuppressWarnings("unchecked") Class rootBeanClass = ( Class ) rootBean.getClass(); return new GlobalExecutionContext( rootBeanClass, rootBean, messageInterpolator, constraintValidatorFactory, traversableResolver ); } public static GlobalExecutionContext getContextForValidateValue(Class rootBeanClass, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) { return new GlobalExecutionContext( rootBeanClass, null, messageInterpolator, constraintValidatorFactory, traversableResolver ); } private GlobalExecutionContext(Class rootBeanClass, T rootBean, MessageInterpolator messageInterpolator, ConstraintValidatorFactory constraintValidatorFactory, TraversableResolver traversableResolver) { this.rootBean = rootBean; this.rootBeanClass = rootBeanClass; this.messageInterpolator = messageInterpolator; this.constraintValidatorFactory = constraintValidatorFactory; this.traversableResolver = traversableResolver; processedObjects = new HashMap, IdentitySet>(); processedPaths = new IdentityHashMap>(); failingConstraintViolations = new ArrayList>(); } public T getRootBean() { return rootBean; } public Class getRootBeanClass() { return rootBeanClass; } public TraversableResolver getTraversableResolver() { return traversableResolver; } public MessageInterpolator getMessageInterpolator() { return messageInterpolator; } public ConstraintViolationImpl createConstraintViolation(LocalExecutionContext localContext, MessageAndPath messageAndPath, ConstraintDescriptor descriptor) { String messageTemplate = messageAndPath.getMessage(); String interpolatedMessage = messageInterpolator.interpolate( messageTemplate, new MessageInterpolatorContext( descriptor, localContext.getCurrentBean() ) ); return new ConstraintViolationImpl( messageTemplate, interpolatedMessage, getRootBeanClass(), getRootBean(), localContext.getCurrentBean(), localContext.getCurrentValidatedValue(), messageAndPath.getPath(), descriptor, localContext.getElementType() ); } public List> createConstraintViolations(LocalExecutionContext localContext, ConstraintValidatorContextImpl constraintValidatorContext) { List> constraintViolations = new ArrayList>(); for ( MessageAndPath messageAndPath : constraintValidatorContext.getMessageAndPathList() ) { ConstraintViolationImpl violation = createConstraintViolation( localContext, messageAndPath, constraintValidatorContext.getConstraintDescriptor() ); constraintViolations.add( violation ); } return constraintViolations; } public ConstraintValidatorFactory getConstraintValidatorFactory() { return constraintValidatorFactory; } public boolean isAlreadyValidated(Object value, Class group, PathImpl path) { boolean alreadyValidated; alreadyValidated = isAlreadyValidatedForCurrentGroup( value, group ); if ( alreadyValidated && allowOneValidationPerPath ) { alreadyValidated = isAlreadyValidatedForPath( value, path ); } return alreadyValidated; } public void markProcessed(Object value, Class group, PathImpl path) { markProcessForCurrentGroup( value, group ); if ( allowOneValidationPerPath ) { markProcessedForCurrentPath( value, path ); } } private void addConstraintFailure(ConstraintViolation failingConstraintViolation) { // NOTE: we are relying on the fact that ConstraintViolation.equals() is implemented correctly. int i = failingConstraintViolations.indexOf( failingConstraintViolation ); if ( i == -1 ) { failingConstraintViolations.add( failingConstraintViolation ); } } public void addConstraintFailures(List> failingConstraintViolations) { for ( ConstraintViolation violation : failingConstraintViolations ) { addConstraintFailure( violation ); } } public List> getFailingConstraints() { return failingConstraintViolations; } private boolean isAlreadyValidatedForPath(Object value, PathImpl path) { Set pathSet = processedPaths.get( value ); if ( pathSet == null ) { return false; } for ( PathImpl p : pathSet ) { if ( p.isRootPath() || path.isRootPath() || p.isSubPathOf( path ) || path.isSubPathOf( p ) ) { return true; } } return false; } private boolean isAlreadyValidatedForCurrentGroup(Object value, Class group) { final IdentitySet objectsProcessedInCurrentGroups = processedObjects.get( group ); return objectsProcessedInCurrentGroups != null && objectsProcessedInCurrentGroups.contains( value ); } private void markProcessedForCurrentPath(Object value, PathImpl path) { // hmm - not sure if the current definiton of Path and Node are consistent. Shouldn't a simple property // of a entity have a parent node? PathImpl parentPath = path.getPathWithoutLeafNode(); if ( parentPath == null ) { parentPath = PathImpl.createNewPath( null ); } if ( processedPaths.containsKey( value ) ) { processedPaths.get( value ).add( parentPath ); } else { Set set = new HashSet(); set.add( parentPath ); processedPaths.put( value, set ); } } private void markProcessForCurrentGroup(Object value, Class group) { if ( processedObjects.containsKey( group ) ) { processedObjects.get( group ).add( value ); } else { IdentitySet set = new IdentitySet(); set.add( value ); processedObjects.put( group, set ); } } } ././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000755000175000017500000000000011402110355033401 5ustar twernertwerner././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/GroupChainGenerator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000763111262172500033416 0ustar twernertwerner// $Id: GroupChainGenerator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.validation.GroupDefinitionException; import javax.validation.GroupSequence; import javax.validation.ValidationException; /** * Used to determine the execution order. * * @author Hardy Ferentschik */ public class GroupChainGenerator { private final Map, List> resolvedSequences = new HashMap, List>(); public GroupChain getGroupChainFor(Collection> groups) { if ( groups == null || groups.size() == 0 ) { throw new IllegalArgumentException( "At least one groups has to be specified." ); } for ( Class clazz : groups ) { if ( !clazz.isInterface() ) { throw new ValidationException( "A group has to be an interface. " + clazz.getName() + " is not." ); } } GroupChain chain = new GroupChain(); for ( Class clazz : groups ) { if ( clazz.getAnnotation( GroupSequence.class ) == null ) { Group group = new Group( clazz ); chain.insertGroup( group ); insertInheritedGroups( clazz, chain ); } else { insertSequence( clazz, chain ); } } return chain; } private void insertInheritedGroups(Class clazz, GroupChain chain) { for ( Class extendedInterface : clazz.getInterfaces() ) { Group group = new Group( extendedInterface ); chain.insertGroup( group ); insertInheritedGroups( extendedInterface, chain ); } } private void insertSequence(Class clazz, GroupChain chain) { List sequence; if ( resolvedSequences.containsKey( clazz ) ) { sequence = resolvedSequences.get( clazz ); } else { sequence = resolveSequence( clazz, new ArrayList>() ); } chain.insertSequence( sequence ); } private List resolveSequence(Class group, List> processedSequences) { if ( processedSequences.contains( group ) ) { throw new GroupDefinitionException( "Cyclic dependency in groups definition" ); } else { processedSequences.add( group ); } List resolvedGroupSequence = new ArrayList(); GroupSequence sequenceAnnotation = group.getAnnotation( GroupSequence.class ); Class[] sequenceArray = sequenceAnnotation.value(); for ( Class clazz : sequenceArray ) { if ( clazz.getAnnotation( GroupSequence.class ) == null ) { resolvedGroupSequence.add( new Group( clazz, group ) ); } else { List tmpSequence = resolveSequence( clazz, processedSequences ); addTmpSequence( resolvedGroupSequence, tmpSequence ); } } resolvedSequences.put( group, resolvedGroupSequence ); return resolvedGroupSequence; } private void addTmpSequence(List resolvedGroupSequence, List tmpSequence) { for ( Group tmpGroup : tmpSequence ) { if ( resolvedGroupSequence.contains( tmpGroup ) && resolvedGroupSequence.indexOf( tmpGroup ) < resolvedGroupSequence.size() - 1 ) { throw new GroupDefinitionException( "Unable to expand group sequence." ); } resolvedGroupSequence.add( tmpGroup ); } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/Group.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000411311262172500033406 0ustar twernertwerner// $Id: Group.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import javax.validation.groups.Default; /** * Encapsulates a single group. * * @author Hardy Ferentschik */ public class Group { /** * The actual group. */ private Class group; /** * The sequence the group is part of ({@code null}, if this group is not part of a sequence). */ private Class sequence; public Group(Class group) { this( group, null ); } public Group(Class group, Class sequence) { this.group = group; this.sequence = sequence; } public Class getGroup() { return group; } public Class getSequence() { return sequence; } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } Group group1 = ( Group ) o; if ( group != null ? !group.equals( group1.group ) : group1.group != null ) { return false; } return true; } public boolean isDefaultGroup() { return getGroup().getName().equals( Default.class.getName() ); } @Override public int hashCode() { return group != null ? group.hashCode() : 0; } @Override public String toString() { return "Group{" + "groups=" + group + ", sequence=" + sequence + '}'; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000176111262172500033414 0ustar twernertwerner This package contains helper classes for the processing of groups. ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/groups/GroupChain.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001047611262172500033417 0ustar twernertwerner// $Id: GroupChain.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.groups; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.validation.GroupDefinitionException; import javax.validation.groups.Default; /** * An instance of {@code GroupChain} defines the group order during one full validation call. * * @author Hardy Ferentschik */ public class GroupChain { /** * The list of single groups to be used this validation. */ private List groupList = new ArrayList(); /** * The different sequences for this validation. The map contains the list of groups mapped to their sequence * name. */ private Map, List> sequenceMap = new HashMap, List>(); public Iterator getGroupIterator() { return groupList.iterator(); } public Iterator> getSequenceIterator() { return sequenceMap.values().iterator(); } void insertGroup(Group group) { if ( !groupList.contains( group ) ) { groupList.add( group ); } } void insertSequence(List groups) { if ( groups == null || groups.size() == 0 ) { return; } if ( !sequenceMap.containsValue( groups ) ) { sequenceMap.put( groups.get( 0 ).getSequence(), groups ); } } @Override public String toString() { return "GroupChain{" + "groupList=" + groupList + ", sequenceMap=" + sequenceMap + '}'; } public void assertDefaultGroupSequenceIsExpandable(List> defaultGroupSequence) { for ( Map.Entry, List> entry : sequenceMap.entrySet() ) { Class sequence = entry.getKey(); List groupList = entry.getValue(); List defaultGroupList = buildTempGroupList( defaultGroupSequence, sequence ); int defaultGroupIndex = containsDefaultGroupAtIndex( sequence, groupList ); if ( defaultGroupIndex != -1 ) { ensureDefaultGroupSequenceIsExpandable( groupList, defaultGroupList, defaultGroupIndex ); } } } private void ensureDefaultGroupSequenceIsExpandable(List groupList, List defaultGroupList, int defaultGroupIndex) { for ( int i = 0; i < defaultGroupList.size(); i++ ) { Group group = defaultGroupList.get( i ); if ( group.getGroup().equals( Default.class ) ) { continue; // we don't have to consider the default group since it is the one we want to replace } int index = groupList.indexOf( group ); // check whether the sequence contains group of the default group sequence if ( index == -1 ) { continue; // if the group is not in the sequence we can continue } if ( ( i == 0 && index == defaultGroupIndex - 1 ) || ( i == defaultGroupList.size() - 1 && index == defaultGroupIndex + 1 ) ) { // if we are at the beginning or end of he defaultGroupSequence and the matches are either directly before resp after we can continue as well, // since we basically have two groups continue; } throw new GroupDefinitionException( "Unable to expand default group list" + defaultGroupList + " into sequence " + groupList ); } } private int containsDefaultGroupAtIndex(Class sequence, List groupList) { Group defaultGroup = new Group( Default.class, sequence ); return groupList.indexOf( defaultGroup ); } private List buildTempGroupList(List> defaultGroupSequence, Class sequence) { List groupList = new ArrayList(); for ( Class clazz : defaultGroupSequence ) { Group g = new Group( clazz, sequence ); groupList.add( g ); } return groupList; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ConstraintViolationImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001123011262172500033404 0ustar twernertwerner// $Id: ConstraintViolationImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.lang.annotation.ElementType; import javax.validation.ConstraintViolation; import javax.validation.Path; import javax.validation.metadata.ConstraintDescriptor; /** * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ConstraintViolationImpl implements ConstraintViolation, java.io.Serializable { private final String interpolatedMessage; private final T rootBean; private final Object value; private final Path propertyPath; private final Object leafBeanInstance; private final ConstraintDescriptor constraintDescriptor; private final String messageTemplate; private final Class rootBeanClass; private final ElementType elementType; public ConstraintViolationImpl(String messageTemplate, String interpolatedMessage, Class rootBeanClass, T rootBean, Object leafBeanInstance, Object value, Path propertyPath, ConstraintDescriptor constraintDescriptor, ElementType elementType) { this.messageTemplate = messageTemplate; this.interpolatedMessage = interpolatedMessage; this.rootBean = rootBean; this.value = value; this.propertyPath = propertyPath; this.leafBeanInstance = leafBeanInstance; this.constraintDescriptor = constraintDescriptor; this.rootBeanClass = rootBeanClass; this.elementType = elementType; } public String getMessage() { return interpolatedMessage; } public String getMessageTemplate() { return messageTemplate; } public T getRootBean() { return rootBean; } public Class getRootBeanClass() { return rootBeanClass; } public Object getLeafBean() { return leafBeanInstance; } public Object getInvalidValue() { return value; } public Path getPropertyPath() { return propertyPath; } public ConstraintDescriptor getConstraintDescriptor() { return this.constraintDescriptor; } @Override @SuppressWarnings("SimplifiableIfStatement") public boolean equals(Object o) { if ( this == o ) { return true; } if ( !( o instanceof ConstraintViolationImpl ) ) { return false; } ConstraintViolationImpl that = ( ConstraintViolationImpl ) o; if ( interpolatedMessage != null ? !interpolatedMessage.equals( that.interpolatedMessage ) : that.interpolatedMessage != null ) { return false; } if ( propertyPath != null ? !propertyPath.equals( that.propertyPath ) : that.propertyPath != null ) { return false; } if ( rootBean != null ? !rootBean.equals( that.rootBean ) : that.rootBean != null ) { return false; } if ( leafBeanInstance != null ? !leafBeanInstance.equals( that.leafBeanInstance ) : that.leafBeanInstance != null ) { return false; } if ( elementType != null ? !elementType.equals( that.elementType ) : that.elementType != null ) { return false; } if ( value != null ? !value.equals( that.value ) : that.value != null ) { return false; } return true; } @Override public int hashCode() { int result = interpolatedMessage != null ? interpolatedMessage.hashCode() : 0; result = 31 * result + ( propertyPath != null ? propertyPath.hashCode() : 0 ); result = 31 * result + ( rootBean != null ? rootBean.hashCode() : 0 ); result = 31 * result + ( leafBeanInstance != null ? leafBeanInstance.hashCode() : 0 ); result = 31 * result + ( value != null ? value.hashCode() : 0 ); result = 31 * result + ( elementType != null ? elementType.hashCode() : 0 ); return result; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "ConstraintViolationImpl" ); sb.append( "{interpolatedMessage='" ).append( interpolatedMessage ).append( '\'' ); sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", rootBeanClass=" ).append( rootBeanClass ); sb.append( ", messageTemplate='" ).append( messageTemplate ).append( '\'' ); sb.append( '}' ); return sb.toString(); } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/PathImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001363111265361201033414 0ustar twernertwerner// $Id: PathImpl.java 17744 2009-10-14 14:38:57Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.io.Serializable; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.validation.Path; /** * @author Hardy Ferentschik */ public class PathImpl implements Path, Serializable { private static final long serialVersionUID = 7564511574909882392L; /** * Regular expression used to split a string path into its elements. * * @see Regular expression tester */ private static final Pattern pathPattern = Pattern.compile( "(\\w+)(\\[(\\w*)\\])?(\\.(.*))*" ); private static final String PROPERTY_PATH_SEPERATOR = "."; private final List nodeList; /** * Returns a {@code Path} instance representing the path described by the given string. To create a root node the empty string should be passed. * * @param propertyPath the path as string representation. * * @return a {@code Path} instance representing the path described by the given string. * * @throws IllegalArgumentException in case {@code property == null} or {@code property} cannot be parsed. */ public static PathImpl createPathFromString(String propertyPath) { if ( propertyPath == null ) { throw new IllegalArgumentException( "null is not allowed as property path." ); } if ( propertyPath.length() == 0 ) { return createNewPath( null ); } return parseProperty( propertyPath ); } public static PathImpl createNewPath(String name) { PathImpl path = new PathImpl(); NodeImpl node = new NodeImpl( name ); path.addNode( node ); return path; } public static PathImpl createShallowCopy(Path path) { return path == null ? null : new PathImpl( path ); } private PathImpl(Path path) { this.nodeList = new ArrayList(); for ( Object aPath : path ) { nodeList.add( new NodeImpl( ( Node ) aPath ) ); } } private PathImpl() { nodeList = new ArrayList(); } private PathImpl(List nodeList) { this.nodeList = new ArrayList(); for ( Node node : nodeList ) { this.nodeList.add( new NodeImpl( node ) ); } } public boolean isRootPath() { return nodeList.size() == 1 && nodeList.get( 0 ).getName() == null; } public PathImpl getPathWithoutLeafNode() { List nodes = new ArrayList( nodeList ); PathImpl path = null; if ( nodes.size() > 1 ) { nodes.remove( nodes.size() - 1 ); path = new PathImpl( nodes ); } return path; } public void addNode(Node node) { nodeList.add( node ); } public Node removeLeafNode() { if ( nodeList.size() == 0 ) { throw new IllegalStateException( "No nodes in path!" ); } if ( nodeList.size() == 1 ) { throw new IllegalStateException( "Root node cannot be removed!" ); } return nodeList.remove( nodeList.size() - 1 ); } public NodeImpl getLeafNode() { if ( nodeList.size() == 0 ) { throw new IllegalStateException( "No nodes in path!" ); } return ( NodeImpl ) nodeList.get( nodeList.size() - 1 ); } public Iterator iterator() { return nodeList.iterator(); } public boolean isSubPathOf(Path path) { Iterator pathIter = path.iterator(); Iterator thisIter = iterator(); while ( pathIter.hasNext() ) { Node pathNode = pathIter.next(); if ( !thisIter.hasNext() ) { return false; } Node thisNode = thisIter.next(); if ( !thisNode.equals( pathNode ) ) { return false; } } return true; } @Override public String toString() { StringBuilder builder = new StringBuilder(); Iterator iter = iterator(); while ( iter.hasNext() ) { Node node = iter.next(); builder.append( node.toString() ); if ( iter.hasNext() ) { builder.append( PROPERTY_PATH_SEPERATOR ); } } return builder.toString(); } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } PathImpl path = ( PathImpl ) o; if ( nodeList != null && !nodeList.equals( path.nodeList ) ) { return false; } if ( nodeList == null && path.nodeList != null ) { return false; } return true; } @Override public int hashCode() { return nodeList != null ? nodeList.hashCode() : 0; } private static PathImpl parseProperty(String property) { PathImpl path = new PathImpl(); String tmp = property; do { Matcher matcher = pathPattern.matcher( tmp ); if ( matcher.matches() ) { String value = matcher.group( 1 ); String indexed = matcher.group( 2 ); String index = matcher.group( 3 ); NodeImpl node = new NodeImpl( value ); if ( indexed != null ) { node.setInIterable( true ); } if ( index != null && index.length() > 0 ) { try { Integer i = Integer.parseInt( index ); node.setIndex( i ); } catch ( NumberFormatException e ) { node.setKey( index ); } } path.addNode( node ); tmp = matcher.group( 5 ); } else { throw new IllegalArgumentException( "Unable to parse property path " + property ); } } while ( tmp != null ); return path; } } ././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000755000175000017500000000000011402110356033402 5ustar twernertwerner././@LongLink0000000000000000000000000000021700000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/DefaultTraversableResolver.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001033111262172500033405 0ustar twernertwerner// $Id: DefaultTraversableResolver.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.resolver; import java.lang.annotation.ElementType; import java.security.AccessController; import javax.validation.Path; import javax.validation.TraversableResolver; import javax.validation.ValidationException; import org.slf4j.Logger; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.NewInstance; import org.hibernate.validator.util.LoadClass; /** * A JPA 2 aware TraversableResolver. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class DefaultTraversableResolver implements TraversableResolver { private static final Logger log = LoggerFactory.make(); /** * Class to load to check whether JPA 2 is on the classpath. */ private static final String PERSISTENCE_UTIL_CLASS_NAME = "javax.persistence.PersistenceUtil"; /** * Class to instantiate in case JPA 2 is on the classpath. */ private static final String JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME = "org.hibernate.validator.engine.resolver.JPATraversableResolver"; /** * A JPA 2 aware traversable resolver. */ private TraversableResolver jpaTraversableResolver; public DefaultTraversableResolver() { detectJPA(); } /** * Tries to load detect and load JPA. */ private void detectJPA() { try { loadClass( PERSISTENCE_UTIL_CLASS_NAME, this.getClass() ); log.debug( "Found {} on classpath.", PERSISTENCE_UTIL_CLASS_NAME ); } catch ( ValidationException e ) { log.debug( "Cannot find {} on classpath. All properties will per default be traversable.", PERSISTENCE_UTIL_CLASS_NAME ); return; } try { @SuppressWarnings( "unchecked" ) Class jpaAwareResolverClass = (Class) loadClass(JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME, this.getClass() ); NewInstance newInstance = NewInstance.action( jpaAwareResolverClass, "" ); if ( System.getSecurityManager() != null ) { jpaTraversableResolver = AccessController.doPrivileged( newInstance ); } else { jpaTraversableResolver = newInstance.run(); } log.info( "Instantiated an instance of {}.", JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME ); } catch ( ValidationException e ) { log.info( "Unable to load or instanciate JPA aware resolver {}. All properties will per default be traversable.", JPA_AWARE_TRAVERSABLE_RESOLVER_CLASS_NAME ); } } private Class loadClass(String className, Class caller) { LoadClass action = LoadClass.action( className, caller ); if (System.getSecurityManager() != null) { return AccessController.doPrivileged( action ); } else { return action.run(); } } public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return jpaTraversableResolver == null || jpaTraversableResolver.isReachable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return jpaTraversableResolver == null || jpaTraversableResolver.isCascadable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000200411262172500033403 0ustar twernertwerner This package contains different implementations of the TraversableResolver interface. ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/JPATraversableResolver.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000337511262172500033417 0ustar twernertwerner// $Id: JPATraversableResolver.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.resolver; import java.lang.annotation.ElementType; import javax.persistence.Persistence; import javax.validation.TraversableResolver; import javax.validation.Path; /** * @author Hardy Ferentschik * @author Emmanuel Bernard */ public class JPATraversableResolver implements TraversableResolver { // TODO Check the call to PersistenceUtil. traversableProperty.getName() is this correct? public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return traversableObject == null || Persistence.getPersistenceUtil().isLoaded( traversableObject, traversableProperty.getName() ); } public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { return true; } } ././@LongLink0000000000000000000000000000023200000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/resolver/SingleThreadCachedTraversableResolver.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001250111262172500033406 0ustar twernertwerner// $Id: SingleThreadCachedTraversableResolver.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine.resolver; import java.lang.annotation.ElementType; import java.util.HashMap; import java.util.Map; import javax.validation.Path; import javax.validation.TraversableResolver; /** * Cache results of a delegated traversable resovler to optimize calls * It works only for a single validate* call and should not be used if * the TraversableResolver is accessed concurrently * * @author Emmanuel Bernard */ public class SingleThreadCachedTraversableResolver implements TraversableResolver { private TraversableResolver delegate; private Map traversables = new HashMap(); public SingleThreadCachedTraversableResolver(TraversableResolver delegate) { this.delegate = delegate; } public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { TraversableHolder currentLH = new TraversableHolder( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); TraversableHolder cachedLH = traversables.get( currentLH ); if ( cachedLH == null ) { currentLH.isReachable = delegate.isReachable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); traversables.put( currentLH, currentLH ); cachedLH = currentLH; } else if ( cachedLH.isReachable == null ) { cachedLH.isReachable = delegate.isReachable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } return cachedLH.isReachable; } public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { TraversableHolder currentLH = new TraversableHolder( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); TraversableHolder cachedLH = traversables.get( currentLH ); if ( cachedLH == null ) { currentLH.isCascadable = delegate.isCascadable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); traversables.put( currentLH, currentLH ); cachedLH = currentLH; } else if ( cachedLH.isCascadable == null ) { cachedLH.isCascadable = delegate.isCascadable( traversableObject, traversableProperty, rootBeanType, pathToTraversableObject, elementType ); } return cachedLH.isCascadable; } private static class TraversableHolder { private final Object traversableObject; private final Path.Node traversableProperty; private final Class rootBeanType; private final Path pathToTraversableObject; private final ElementType elementType; private final int hashCode; private Boolean isReachable; private Boolean isCascadable; private TraversableHolder(Object traversableObject, Path.Node traversableProperty, Class rootBeanType, Path pathToTraversableObject, ElementType elementType) { this.traversableObject = traversableObject; this.traversableProperty = traversableProperty; this.rootBeanType = rootBeanType; this.pathToTraversableObject = pathToTraversableObject; this.elementType = elementType; this.hashCode = buildHashCode(); } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } TraversableHolder that = ( TraversableHolder ) o; if ( elementType != that.elementType ) { return false; } if ( !pathToTraversableObject.equals( that.pathToTraversableObject ) ) { return false; } if ( !rootBeanType.equals( that.rootBeanType ) ) { return false; } if ( traversableObject != null ? !traversableObject.equals( that.traversableObject ) : that.traversableObject != null ) { return false; } if ( !traversableProperty.equals( that.traversableProperty ) ) { return false; } return true; } @Override public int hashCode() { return hashCode; } public int buildHashCode() { int result = traversableObject != null ? traversableObject.hashCode() : 0; result = 31 * result + traversableProperty.hashCode(); result = 31 * result + rootBeanType.hashCode(); result = 31 * result + pathToTraversableObject.hashCode(); result = 31 * result + elementType.hashCode(); return result; } } } ././@LongLink0000000000000000000000000000020100000000000011556 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/LocalExecutionContext.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000742211262172500033414 0ustar twernertwerner// $Id: LocalExecutionContext.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.lang.annotation.ElementType; import javax.validation.groups.Default; /** * An instance of this class is used to collect all the relevant information for validating a single entity/bean. * * @author Hardy Ferentschik */ public class LocalExecutionContext { /** * The current bean which gets validated. This is the bean hosting the constraints which get validated. */ private final T currentBean; /** * The class of the current bean. */ private final Class currentBeanType; /** * The current property path we are validating. */ private PathImpl propertyPath; /** * The current group we are validating. */ private Class currentGroup; /** * The value which gets currently evaluated. */ private V currentValue; /** * The {@code ElementType} the constraint was defined on */ private ElementType elementType; public static LocalExecutionContext getLocalExecutionContext(T value) { @SuppressWarnings("unchecked") Class rootBeanClass = ( Class ) value.getClass(); return new LocalExecutionContext( value, rootBeanClass ); } public static LocalExecutionContext getLocalExecutionContext(Class type) { return new LocalExecutionContext( null, type ); } public LocalExecutionContext(T currentBean, Class currentBeanType) { this.currentBean = currentBean; this.currentBeanType = currentBeanType; } public PathImpl getPropertyPath() { return propertyPath; } public Class getCurrentGroup() { return currentGroup; } public T getCurrentBean() { return currentBean; } public Class getCurrentBeanType() { return currentBeanType; } public V getCurrentValidatedValue() { return currentValue; } public void setPropertyPath(PathImpl propertyPath) { this.propertyPath = propertyPath; } public void setCurrentGroup(Class currentGroup) { this.currentGroup = currentGroup; } public void setCurrentValidatedValue(V currentValue) { this.currentValue = currentValue; } public void markCurrentPropertyAsIterable() { propertyPath.getLeafNode().setInIterable( true ); } public boolean validatingDefault() { return getCurrentGroup() != null && getCurrentGroup().getName().equals( Default.class.getName() ); } public ElementType getElementType() { return elementType; } public void setElementType(ElementType elementType) { this.elementType = elementType; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "LocalExecutionContext" ); sb.append( "{currentBean=" ).append( currentBean ); sb.append( ", currentBeanType=" ).append( currentBeanType ); sb.append( ", propertyPath=" ).append( propertyPath ); sb.append( ", currentGroup=" ).append( currentGroup ); sb.append( ", currentValue=" ).append( currentValue ); sb.append( ", elementType=" ).append( elementType ); sb.append( '}' ); return sb.toString(); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000200111262172500033400 0ustar twernertwerner This package contains the implementing classes for the core interfaces of JSR-303. ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/MessageAndPath.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000240611262172500033411 0ustar twernertwerner// $Id: MessageAndPath.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import javax.validation.Path; /** * @author Hardy Ferentschik */ public class MessageAndPath { private final String message; private final Path propertyPath; public MessageAndPath(String message, Path property) { this.message = message; this.propertyPath = property; } public String getMessage() { return message; } public Path getPath() { return propertyPath; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ConstraintValidatorFactoryImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000313211262172500033406 0ustar twernertwerner// $Id: ConstraintValidatorFactoryImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.security.AccessController; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorFactory; import org.hibernate.validator.util.NewInstance; /** * Default ConstraintValidatorFactory using a no-arg constructor. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ConstraintValidatorFactoryImpl implements ConstraintValidatorFactory { public > T getInstance(Class key) { NewInstance newInstance = NewInstance.action( key, "" ); if ( System.getSecurityManager() != null ) { return AccessController.doPrivileged( newInstance ); } else { return newInstance.run(); } } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/MessageInterpolatorContext.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000315311262172500033411 0ustar twernertwerner// $Id: MessageInterpolatorContext.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.MessageInterpolator; /** * Takes mandatory elements in the constructor * * @author Emmanuel Bernard */ public class MessageInterpolatorContext implements MessageInterpolator.Context { private final ConstraintDescriptor constraintDescriptor; private final Object validatedValue; public MessageInterpolatorContext(ConstraintDescriptor constraintDescriptor, Object validatedValue) { this.constraintDescriptor = constraintDescriptor; this.validatedValue = validatedValue; } public ConstraintDescriptor getConstraintDescriptor() { return constraintDescriptor; } public Object getValidatedValue() { return validatedValue; } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorFactoryImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000755000175000017500000001354011272032647033425 0ustar twernertwerner// $Id: ValidatorFactoryImpl.java 17860 2009-10-28 12:14:31Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.ValidationException; import javax.validation.Validator; import javax.validation.ValidatorContext; import javax.validation.ValidatorFactory; import javax.validation.spi.ConfigurationState; import org.hibernate.validator.metadata.AnnotationIgnores; import org.hibernate.validator.metadata.BeanMetaDataCache; import org.hibernate.validator.metadata.BeanMetaDataImpl; import org.hibernate.validator.metadata.ConstraintDescriptorImpl; import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.ConstraintOrigin; import org.hibernate.validator.metadata.MetaConstraint; import org.hibernate.validator.util.ReflectionHelper; import org.hibernate.validator.xml.XmlMappingParser; /** * Factory returning initialized Validator instances. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ValidatorFactoryImpl implements ValidatorFactory { private final MessageInterpolator messageInterpolator; private final TraversableResolver traversableResolver; private final ConstraintValidatorFactory constraintValidatorFactory; private final ConstraintHelper constraintHelper; private final BeanMetaDataCache beanMetaDataCache; public ValidatorFactoryImpl(ConfigurationState configurationState) { this.messageInterpolator = configurationState.getMessageInterpolator(); this.constraintValidatorFactory = configurationState.getConstraintValidatorFactory(); this.traversableResolver = configurationState.getTraversableResolver(); this.constraintHelper = new ConstraintHelper(); this.beanMetaDataCache = new BeanMetaDataCache(); initBeanMetaData( configurationState.getMappingStreams() ); } public Validator getValidator() { return usingContext().getValidator(); } public MessageInterpolator getMessageInterpolator() { return messageInterpolator; } public TraversableResolver getTraversableResolver() { return traversableResolver; } public ConstraintValidatorFactory getConstraintValidatorFactory() { return constraintValidatorFactory; } public T unwrap(Class type) { throw new ValidationException( "Type " + type + " not supported" ); } public ValidatorContext usingContext() { return new ValidatorContextImpl( constraintValidatorFactory, messageInterpolator, traversableResolver, constraintHelper, beanMetaDataCache ); } private void initBeanMetaData(Set mappingStreams) { XmlMappingParser mappingParser = new XmlMappingParser( constraintHelper ); mappingParser.parse( mappingStreams ); Set> processedClasses = mappingParser.getProcessedClasses(); AnnotationIgnores annotationIgnores = mappingParser.getAnnotationIgnores(); for ( Class clazz : processedClasses ) { @SuppressWarnings("unchecked") Class beanClass = ( Class ) clazz; BeanMetaDataImpl metaData = new BeanMetaDataImpl( beanClass, constraintHelper, annotationIgnores, beanMetaDataCache ); List> classes = new ArrayList>(); ReflectionHelper.computeClassHierarchy( beanClass, classes ); for ( Class classInHierarchy : classes ) { if ( processedClasses.contains( classInHierarchy ) ) { addXmlConfiguredConstraintToMetaData( mappingParser, beanClass, classInHierarchy, metaData ); } } if ( !mappingParser.getDefaultSequenceForClass( beanClass ).isEmpty() ) { metaData.setDefaultGroupSequence( mappingParser.getDefaultSequenceForClass( beanClass ) ); } beanMetaDataCache.addBeanMetaData( beanClass, metaData ); } } @SuppressWarnings("unchecked") private void addXmlConfiguredConstraintToMetaData(XmlMappingParser mappingParser, Class rootClass, Class hierarchyClass, BeanMetaDataImpl metaData) { for ( MetaConstraint constraint : mappingParser.getConstraintsForClass( hierarchyClass ) ) { ConstraintOrigin definedIn = definedIn( rootClass, hierarchyClass ); ConstraintDescriptorImpl descriptor = new ConstraintDescriptorImpl( ( A ) constraint.getDescriptor().getAnnotation(), constraintHelper, constraint.getElementType(), definedIn ); MetaConstraint newMetaConstraint = new MetaConstraint( rootClass, constraint.getMember(), descriptor ); metaData.addMetaConstraint( hierarchyClass, newMetaConstraint ); } for ( Member m : mappingParser.getCascadedMembersForClass( hierarchyClass ) ) { metaData.addCascadedMember( m ); } } private ConstraintOrigin definedIn(Class rootClass, Class hierarchyClass) { if ( hierarchyClass.equals( rootClass ) ) { return ConstraintOrigin.DEFINED_LOCALLY; } else { return ConstraintOrigin.DEFINED_IN_HIERARCHY; } } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ResourceBundleMessageInterpolator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000002660011262172500033413 0ustar twernertwerner// $Id: ResourceBundleMessageInterpolator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.security.AccessController; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.validation.MessageInterpolator; import org.slf4j.Logger; import org.hibernate.validator.util.GetClassLoader; import org.hibernate.validator.util.LoggerFactory; /** * Resource bundle backed message interpolator. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ResourceBundleMessageInterpolator implements MessageInterpolator { private static final String DEFAULT_VALIDATION_MESSAGES = "org.hibernate.validator.ValidationMessages"; private static final String USER_VALIDATION_MESSAGES = "ValidationMessages"; private static final Logger log = LoggerFactory.make(); /** * Regular expression used to do message interpolation. */ private static final Pattern messageParameterPattern = Pattern.compile( "(\\{[^\\}]+?\\})" ); /** * The default locale for the current user. */ private final Locale defaultLocale; /** * User specified resource bundles hashed against their locale. */ private final Map userBundlesMap = new ConcurrentHashMap(); /** * Built-in resource bundles hashed against there locale. */ private final Map defaultBundlesMap = new ConcurrentHashMap(); /** * Step 1-3 of message interpolation can be cached. We do this in this map. */ private final Map resolvedMessages = new WeakHashMap(); public ResourceBundleMessageInterpolator() { this( null ); } public ResourceBundleMessageInterpolator(ResourceBundle resourceBundle) { defaultLocale = Locale.getDefault(); if ( resourceBundle == null ) { ResourceBundle bundle = getFileBasedResourceBundle( defaultLocale ); if ( bundle != null ) { userBundlesMap.put( defaultLocale, bundle ); } } else { userBundlesMap.put( defaultLocale, resourceBundle ); } defaultBundlesMap.put( defaultLocale, ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES, defaultLocale ) ); } public String interpolate(String message, Context context) { // probably no need for caching, but it could be done by parameters since the map // is immutable and uniquely built per Validation definition, the comparison has to be based on == and not equals though return interpolateMessage( message, context.getConstraintDescriptor().getAttributes(), defaultLocale ); } public String interpolate(String message, Context context, Locale locale) { return interpolateMessage( message, context.getConstraintDescriptor().getAttributes(), locale ); } /** * Runs the message interpolation according to algorithm specified in JSR 303. *
* Note: *
* Look-ups in user bundles is recursive whereas look-ups in default bundle are not! * * @param message the message to interpolate * @param annotationParameters the parameters of the annotation for which to interpolate this message * @param locale the Locale to use for the resource bundle. * * @return the interpolated message. */ private String interpolateMessage(String message, Map annotationParameters, Locale locale) { LocalisedMessage localisedMessage = new LocalisedMessage( message, locale ); String resolvedMessage = resolvedMessages.get( localisedMessage ); // if the message is not already in the cache we have to run step 1-3 of the message resolution if ( resolvedMessage == null ) { ResourceBundle userResourceBundle = findUserResourceBundle( locale ); ResourceBundle defaultResourceBundle = findDefaultResourceBundle( locale ); String userBundleResolvedMessage; resolvedMessage = message; boolean evaluatedDefaultBundleOnce = false; do { // search the user bundle recursive (step1) userBundleResolvedMessage = replaceVariables( resolvedMessage, userResourceBundle, locale, true ); // exit condition - we have at least tried to validate against the default bundle and there was no // further replacements if ( evaluatedDefaultBundleOnce && !hasReplacementTakenPlace( userBundleResolvedMessage, resolvedMessage ) ) { break; } // search the default bundle non recursive (step2) resolvedMessage = replaceVariables( userBundleResolvedMessage, defaultResourceBundle, locale, false ); evaluatedDefaultBundleOnce = true; resolvedMessages.put( localisedMessage, resolvedMessage ); } while ( true ); } // resolve annotation attributes (step 4) resolvedMessage = replaceAnnotationAttributes( resolvedMessage, annotationParameters ); // last but not least we have to take care of escaped literals resolvedMessage = resolvedMessage.replace( "\\{", "{" ); resolvedMessage = resolvedMessage.replace( "\\}", "}" ); resolvedMessage = resolvedMessage.replace( "\\\\", "\\" ); return resolvedMessage; } private boolean hasReplacementTakenPlace(String origMessage, String newMessage) { return !origMessage.equals( newMessage ); } /** * Search current thread classloader for the resource bundle. If not found, search validator (this) classloader. * * @param locale The locale of the bundle to load. * * @return the resource bundle or null if none is found. */ private ResourceBundle getFileBasedResourceBundle(Locale locale) { ResourceBundle rb = null; boolean isSecured = System.getSecurityManager() != null; GetClassLoader action = GetClassLoader.fromContext(); ClassLoader classLoader = isSecured ? AccessController.doPrivileged( action ) : action.run(); if ( classLoader != null ) { rb = loadBundle( classLoader, locale, USER_VALIDATION_MESSAGES + " not found by thread local classloader" ); } if ( rb == null ) { action = GetClassLoader.fromClass( ResourceBundleMessageInterpolator.class ); classLoader = isSecured ? AccessController.doPrivileged( action ) : action.run(); rb = loadBundle( classLoader, locale, USER_VALIDATION_MESSAGES + " not found by validator classloader" ); } if ( log.isDebugEnabled() ) { if ( rb != null ) { log.debug( USER_VALIDATION_MESSAGES + " found" ); } else { log.debug( USER_VALIDATION_MESSAGES + " not found. Delegating to " + DEFAULT_VALIDATION_MESSAGES ); } } return rb; } private ResourceBundle loadBundle(ClassLoader classLoader, Locale locale, String message) { ResourceBundle rb = null; try { rb = ResourceBundle.getBundle( USER_VALIDATION_MESSAGES, locale, classLoader ); } catch ( MissingResourceException e ) { log.trace( message ); } return rb; } private String replaceVariables(String message, ResourceBundle bundle, Locale locale, boolean recurse) { Matcher matcher = messageParameterPattern.matcher( message ); StringBuffer sb = new StringBuffer(); String resolvedParameterValue; while ( matcher.find() ) { String parameter = matcher.group( 1 ); resolvedParameterValue = resolveParameter( parameter, bundle, locale, recurse ); matcher.appendReplacement( sb, escapeMetaCharacters( resolvedParameterValue ) ); } matcher.appendTail( sb ); return sb.toString(); } private String replaceAnnotationAttributes(String message, Map annotationParameters) { Matcher matcher = messageParameterPattern.matcher( message ); StringBuffer sb = new StringBuffer(); while ( matcher.find() ) { String resolvedParameterValue; String parameter = matcher.group( 1 ); Object variable = annotationParameters.get( removeCurlyBrace( parameter ) ); if ( variable != null ) { resolvedParameterValue = escapeMetaCharacters( variable.toString() ); } else { resolvedParameterValue = parameter; } matcher.appendReplacement( sb, resolvedParameterValue ); } matcher.appendTail( sb ); return sb.toString(); } private String resolveParameter(String parameterName, ResourceBundle bundle, Locale locale, boolean recurse) { String parameterValue; try { if ( bundle != null ) { parameterValue = bundle.getString( removeCurlyBrace( parameterName ) ); if ( recurse ) { parameterValue = replaceVariables( parameterValue, bundle, locale, recurse ); } } else { parameterValue = parameterName; } } catch ( MissingResourceException e ) { // return parameter itself parameterValue = parameterName; } return parameterValue; } private String removeCurlyBrace(String parameter) { return parameter.substring( 1, parameter.length() - 1 ); } private ResourceBundle findDefaultResourceBundle(Locale locale) { if ( defaultBundlesMap.containsKey( locale ) ) { return defaultBundlesMap.get( locale ); } ResourceBundle bundle = ResourceBundle.getBundle( DEFAULT_VALIDATION_MESSAGES, locale ); defaultBundlesMap.put( locale, bundle ); return bundle; } private ResourceBundle findUserResourceBundle(Locale locale) { if ( userBundlesMap.containsKey( locale ) ) { return userBundlesMap.get( locale ); } ResourceBundle bundle = getFileBasedResourceBundle( locale ); if ( bundle != null ) { userBundlesMap.put( locale, bundle ); } return bundle; } /** * @param s The string in which to replace the meta characters '$' and '\'. * * @return A string where meta characters relevant for {@link Matcher#appendReplacement} are escaped. */ private String escapeMetaCharacters(String s) { String escapedString = s.replace( "\\", "\\\\" ); escapedString = escapedString.replace( "$", "\\$" ); return escapedString; } private static class LocalisedMessage { private final String message; private final Locale locale; LocalisedMessage(String message, Locale locale) { this.message = message; this.locale = locale; } public String getMessage() { return message; } public Locale getLocale() { return locale; } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } LocalisedMessage that = ( LocalisedMessage ) o; if ( locale != null ? !locale.equals( that.locale ) : that.locale != null ) { return false; } if ( message != null ? !message.equals( that.message ) : that.message != null ) { return false; } return true; } @Override public int hashCode() { int result = message != null ? message.hashCode() : 0; result = 31 * result + ( locale != null ? locale.hashCode() : 0 ); return result; } } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ConfigurationImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000755000175000017500000002143711262172500033421 0ustar twernertwerner// $Id: ConfigurationImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.ValidationException; import javax.validation.ValidationProviderResolver; import javax.validation.ValidatorFactory; import javax.validation.spi.BootstrapState; import javax.validation.spi.ConfigurationState; import javax.validation.spi.ValidationProvider; import org.slf4j.Logger; import org.hibernate.validator.engine.resolver.DefaultTraversableResolver; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.Version; import org.hibernate.validator.xml.ValidationBootstrapParameters; import org.hibernate.validator.xml.ValidationXmlParser; import org.hibernate.validator.HibernateValidatorConfiguration; /** * Hibernate specific Configuration implementation. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ConfigurationImpl implements HibernateValidatorConfiguration, ConfigurationState { static { Version.touch(); } private static final Logger log = LoggerFactory.make(); private final MessageInterpolator defaultMessageInterpolator = new ResourceBundleMessageInterpolator(); private final TraversableResolver defaultTraversableResolver = new DefaultTraversableResolver(); private final ConstraintValidatorFactory defaultConstraintValidatorFactory = new ConstraintValidatorFactoryImpl(); private final ValidationProviderResolver providerResolver; private ValidationBootstrapParameters validationBootstrapParameters; private boolean ignoreXmlConfiguration = false; public ConfigurationImpl(BootstrapState state) { if ( state.getValidationProviderResolver() == null ) { this.providerResolver = state.getDefaultValidationProviderResolver(); } else { this.providerResolver = state.getValidationProviderResolver(); } validationBootstrapParameters = new ValidationBootstrapParameters(); } public ConfigurationImpl(ValidationProvider provider) { if ( provider == null ) { throw new ValidationException( "Assertion error: inconsistent ConfigurationImpl construction" ); } this.providerResolver = null; validationBootstrapParameters = new ValidationBootstrapParameters(); validationBootstrapParameters.provider = provider; } public HibernateValidatorConfiguration ignoreXmlConfiguration() { ignoreXmlConfiguration = true; return this; } public ConfigurationImpl messageInterpolator(MessageInterpolator interpolator) { this.validationBootstrapParameters.messageInterpolator = interpolator; return this; } public ConfigurationImpl traversableResolver(TraversableResolver resolver) { this.validationBootstrapParameters.traversableResolver = resolver; return this; } public ConfigurationImpl constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) { this.validationBootstrapParameters.constraintValidatorFactory = constraintValidatorFactory; return this; } public HibernateValidatorConfiguration addMapping(InputStream stream) { validationBootstrapParameters.mappings.add( stream ); return this; } public HibernateValidatorConfiguration addProperty(String name, String value) { if ( value != null ) { validationBootstrapParameters.configProperties.put( name, value ); } return this; } public ValidatorFactory buildValidatorFactory() { parseValidationXml(); ValidatorFactory factory = null; if ( isSpecificProvider() ) { factory = validationBootstrapParameters.provider.buildValidatorFactory( this ); } else { final Class> providerClass = validationBootstrapParameters.providerClass; if ( providerClass != null ) { for ( ValidationProvider provider : providerResolver.getValidationProviders() ) { if ( providerClass.isAssignableFrom( provider.getClass() ) ) { factory = provider.buildValidatorFactory( this ); break; } } if ( factory == null ) { throw new ValidationException( "Unable to find provider: " + providerClass ); } } else { List> providers = providerResolver.getValidationProviders(); assert providers.size() != 0; // I run therefore I am factory = providers.get( 0 ).buildValidatorFactory( this ); } } // reset the param holder validationBootstrapParameters = new ValidationBootstrapParameters(); return factory; } public boolean isIgnoreXmlConfiguration() { return ignoreXmlConfiguration; } public MessageInterpolator getMessageInterpolator() { return validationBootstrapParameters.messageInterpolator; } public Set getMappingStreams() { return validationBootstrapParameters.mappings; } public ConstraintValidatorFactory getConstraintValidatorFactory() { return validationBootstrapParameters.constraintValidatorFactory; } public TraversableResolver getTraversableResolver() { return validationBootstrapParameters.traversableResolver; } public Map getProperties() { return validationBootstrapParameters.configProperties; } public MessageInterpolator getDefaultMessageInterpolator() { return defaultMessageInterpolator; } public TraversableResolver getDefaultTraversableResolver() { return defaultTraversableResolver; } public ConstraintValidatorFactory getDefaultConstraintValidatorFactory() { return defaultConstraintValidatorFactory; } private boolean isSpecificProvider() { return validationBootstrapParameters.provider != null; } /** * Tries to check whether a validation.xml file exists and parses it using JAXB */ private void parseValidationXml() { if ( ignoreXmlConfiguration ) { log.info( "Ignoring XML configuration." ); // make sure we use the defaults in case they haven't been provided yet if ( validationBootstrapParameters.messageInterpolator == null ) { validationBootstrapParameters.messageInterpolator = defaultMessageInterpolator; } if ( validationBootstrapParameters.traversableResolver == null ) { validationBootstrapParameters.traversableResolver = defaultTraversableResolver; } if ( validationBootstrapParameters.constraintValidatorFactory == null ) { validationBootstrapParameters.constraintValidatorFactory = defaultConstraintValidatorFactory; } } else { ValidationBootstrapParameters xmlParameters = new ValidationXmlParser().parseValidationXml(); applyXmlSettings( xmlParameters ); } } private void applyXmlSettings(ValidationBootstrapParameters xmlParameters) { validationBootstrapParameters.providerClass = xmlParameters.providerClass; if ( validationBootstrapParameters.messageInterpolator == null ) { if ( xmlParameters.messageInterpolator != null ) { validationBootstrapParameters.messageInterpolator = xmlParameters.messageInterpolator; } else { validationBootstrapParameters.messageInterpolator = defaultMessageInterpolator; } } if ( validationBootstrapParameters.traversableResolver == null ) { if ( xmlParameters.traversableResolver != null ) { validationBootstrapParameters.traversableResolver = xmlParameters.traversableResolver; } else { validationBootstrapParameters.traversableResolver = defaultTraversableResolver; } } if ( validationBootstrapParameters.constraintValidatorFactory == null ) { if ( xmlParameters.constraintValidatorFactory != null ) { validationBootstrapParameters.constraintValidatorFactory = xmlParameters.constraintValidatorFactory; } else { validationBootstrapParameters.constraintValidatorFactory = defaultConstraintValidatorFactory; } } validationBootstrapParameters.mappings.addAll( xmlParameters.mappings ); for ( Map.Entry entry : xmlParameters.configProperties.entrySet() ) { if ( validationBootstrapParameters.configProperties.get( entry.getKey() ) == null ) { validationBootstrapParameters.configProperties.put( entry.getKey(), entry.getValue() ); } } } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ConstraintValidatorContextImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000001526211265402306033420 0ustar twernertwerner// $Id: ConstraintValidatorContextImpl.java 17746 2009-10-14 17:05:10Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.util.ArrayList; import java.util.List; import javax.validation.ConstraintValidatorContext; import javax.validation.ValidationException; import javax.validation.metadata.ConstraintDescriptor; /** * @author Hardy Ferentschik */ public class ConstraintValidatorContextImpl implements ConstraintValidatorContext { private final List messageAndPaths = new ArrayList( 3 ); private final PathImpl propertyPath; private final ConstraintDescriptor constraintDescriptor; private boolean defaultDisabled; public ConstraintValidatorContextImpl(PathImpl propertyPath, ConstraintDescriptor constraintDescriptor) { this.propertyPath = propertyPath; this.constraintDescriptor = constraintDescriptor; } public void disableDefaultConstraintViolation() { defaultDisabled = true; } public String getDefaultConstraintMessageTemplate() { return ( String ) constraintDescriptor.getAttributes().get( "message" ); } public ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate) { return new ErrorBuilderImpl( messageTemplate, propertyPath ); } public ConstraintDescriptor getConstraintDescriptor() { return constraintDescriptor; } public List getMessageAndPathList() { if ( defaultDisabled && messageAndPaths.size() == 0 ) { throw new ValidationException( "At least one custom message must be created if the default error message gets disabled." ); } List returnedMessageAndPaths = new ArrayList( messageAndPaths ); if ( !defaultDisabled ) { returnedMessageAndPaths.add( new MessageAndPath( getDefaultConstraintMessageTemplate(), propertyPath ) ); } return returnedMessageAndPaths; } class ErrorBuilderImpl implements ConstraintViolationBuilder { String messageTemplate; PathImpl propertyPath; ErrorBuilderImpl(String template, PathImpl path) { messageTemplate = template; propertyPath = path; } public NodeBuilderDefinedContext addNode(String name) { PathImpl path; if ( propertyPath.isRootPath() ) { path = PathImpl.createNewPath( name ); } else { path = PathImpl.createShallowCopy( propertyPath ); path.addNode( new NodeImpl( name ) ); } return new NodeBuilderImpl( messageTemplate, path ); } public ConstraintValidatorContext addConstraintViolation() { messageAndPaths.add( new MessageAndPath( messageTemplate, propertyPath ) ); return ConstraintValidatorContextImpl.this; } } class NodeBuilderImpl implements ConstraintViolationBuilder.NodeBuilderDefinedContext { String messageTemplate; PathImpl propertyPath; NodeBuilderImpl(String template, PathImpl path) { messageTemplate = template; propertyPath = path; } public ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) { // we need to defer the adding of the new node, since we don't know yet whether the new node will be iterable return new InIterableNodeBuilderImpl( messageTemplate, propertyPath, name ); } public ConstraintValidatorContext addConstraintViolation() { messageAndPaths.add( new MessageAndPath( messageTemplate, propertyPath ) ); return ConstraintValidatorContextImpl.this; } } class InIterableNodeBuilderImpl implements ConstraintViolationBuilder.NodeBuilderCustomizableContext { String messageTemplate; PathImpl propertyPath; String deferredNodeName; InIterableNodeBuilderImpl(String template, PathImpl path, String deferredNodeName) { this.messageTemplate = template; this.propertyPath = path; this.deferredNodeName = deferredNodeName; } public ConstraintViolationBuilder.NodeContextBuilder inIterable() { this.propertyPath.getLeafNode().setInIterable( true ); return new InIterablePropertiesBuilderImpl( messageTemplate, propertyPath, deferredNodeName ); } public ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) { addDeferredNode(); // now that we add another node we can add the deferred parent node deferredNodeName = name; return this; } public ConstraintValidatorContext addConstraintViolation() { addDeferredNode(); messageAndPaths.add( new MessageAndPath( messageTemplate, propertyPath ) ); return ConstraintValidatorContextImpl.this; } private void addDeferredNode() { if ( deferredNodeName != null ) { NodeImpl node = new NodeImpl( deferredNodeName ); propertyPath.addNode( node ); } } } class InIterablePropertiesBuilderImpl implements ConstraintViolationBuilder.NodeContextBuilder { String messageTemplate; PathImpl propertyPath; String deferredNodeName; InIterablePropertiesBuilderImpl(String template, PathImpl path, String deferredNodeName) { this.messageTemplate = template; this.propertyPath = path; this.deferredNodeName = deferredNodeName; } public ConstraintViolationBuilder.NodeBuilderDefinedContext atKey(Object key) { propertyPath.getLeafNode().setKey( key ); addDeferredNode(); return new NodeBuilderImpl( messageTemplate, propertyPath ); } public ConstraintViolationBuilder.NodeBuilderDefinedContext atIndex(Integer index) { propertyPath.getLeafNode().setIndex( index ); addDeferredNode(); return new NodeBuilderImpl( messageTemplate, propertyPath ); } public ConstraintViolationBuilder.NodeBuilderCustomizableContext addNode(String name) { addDeferredNode(); return new InIterableNodeBuilderImpl( messageTemplate, propertyPath, name ); } public ConstraintValidatorContext addConstraintViolation() { addDeferredNode(); messageAndPaths.add( new MessageAndPath( messageTemplate, propertyPath ) ); return ConstraintValidatorContextImpl.this; } private void addDeferredNode() { if ( deferredNodeName != null ) { NodeImpl node = new NodeImpl( deferredNodeName ); propertyPath.addNode( node ); } } } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ValidatorContextImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000000705311262172500033414 0ustar twernertwerner// $Id: ValidatorContextImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.Validator; import javax.validation.ValidatorContext; import org.hibernate.validator.metadata.BeanMetaDataCache; import org.hibernate.validator.metadata.ConstraintHelper; /** * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ValidatorContextImpl implements ValidatorContext { private MessageInterpolator messageInterpolator; private TraversableResolver traversableResolver; private ConstraintValidatorFactory constraintValidatorFactory; private final MessageInterpolator factoryMessageInterpolator; private final TraversableResolver factoryTraversableResolver; private final ConstraintValidatorFactory factoryConstraintValidatorFactory; private final ConstraintHelper constraintHelper; private final BeanMetaDataCache beanMetaDataCache; public ValidatorContextImpl(ConstraintValidatorFactory constraintValidatorFactory, MessageInterpolator factoryMessageInterpolator, TraversableResolver factoryTraversableResolver, ConstraintHelper constraintHelper, BeanMetaDataCache beanMetaDataCache) { this.factoryConstraintValidatorFactory = constraintValidatorFactory; this.factoryMessageInterpolator = factoryMessageInterpolator; this.factoryTraversableResolver = factoryTraversableResolver; this.constraintHelper = constraintHelper; this.beanMetaDataCache = beanMetaDataCache; messageInterpolator( factoryMessageInterpolator ); traversableResolver( factoryTraversableResolver ); constraintValidatorFactory( factoryConstraintValidatorFactory ); } public ValidatorContext messageInterpolator(MessageInterpolator messageInterpolator) { if ( messageInterpolator == null ) { this.messageInterpolator = factoryMessageInterpolator; } else { this.messageInterpolator = messageInterpolator; } return this; } public ValidatorContext traversableResolver(TraversableResolver traversableResolver) { if ( traversableResolver == null ) { this.traversableResolver = factoryTraversableResolver; } else { this.traversableResolver = traversableResolver; } return this; } public ValidatorContext constraintValidatorFactory(ConstraintValidatorFactory factory) { if ( constraintValidatorFactory == null ) { this.constraintValidatorFactory = factoryConstraintValidatorFactory; } else { this.constraintValidatorFactory = factory; } return this; } public Validator getValidator() { return new ValidatorImpl( constraintValidatorFactory, messageInterpolator, traversableResolver, constraintHelper, beanMetaDataCache ); } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engine/ConstraintTree.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/engin0000644000175000017500000003166111262172500033416 0ustar twernertwerner// $Id: ConstraintTree.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.engine; import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorFactory; import javax.validation.ConstraintViolation; import javax.validation.UnexpectedTypeException; import javax.validation.ValidationException; import javax.validation.metadata.ConstraintDescriptor; import com.googlecode.jtype.TypeUtils; import org.slf4j.Logger; import org.hibernate.validator.metadata.ConstraintDescriptorImpl; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.ValidatorTypeHelper; /** * Due to constraint composition a single constraint annotation can lead to a whole constraint tree being validated. * This class encapsulates such a tree. * * @author Hardy Ferentschik */ public class ConstraintTree
{ private static final Logger log = LoggerFactory.make(); private final ConstraintTree parent; private final List> children; private final ConstraintDescriptorImpl descriptor; private final Map> constraintValidatorCache; public ConstraintTree(ConstraintDescriptorImpl descriptor) { this( descriptor, null ); } private ConstraintTree(ConstraintDescriptorImpl descriptor, ConstraintTree parent) { this.parent = parent; this.descriptor = descriptor; this.constraintValidatorCache = new ConcurrentHashMap>(); final Set> composingConstraints = new HashSet>(); for ( ConstraintDescriptor composingConstraint : descriptor.getComposingConstraints() ) { composingConstraints.add( ( ConstraintDescriptorImpl ) composingConstraint ); } children = new ArrayList>( composingConstraints.size() ); for ( ConstraintDescriptorImpl composingDescriptor : composingConstraints ) { ConstraintTree treeNode = createConstraintTree( composingDescriptor ); children.add( treeNode ); } } private ConstraintTree createConstraintTree(ConstraintDescriptorImpl composingDescriptor) { return new ConstraintTree( composingDescriptor, this ); } public List> getChildren() { return children; } public ConstraintDescriptorImpl getDescriptor() { return descriptor; } public void validateConstraints(Type type, GlobalExecutionContext executionContext, LocalExecutionContext localExecutionContext, List> constraintViolations) { // first validate composing constraints for ( ConstraintTree tree : getChildren() ) { List> tmpViolations = new ArrayList>(); tree.validateConstraints( type, executionContext, localExecutionContext, tmpViolations ); constraintViolations.addAll( tmpViolations ); } ConstraintValidatorContextImpl constraintValidatorContext = new ConstraintValidatorContextImpl( localExecutionContext.getPropertyPath(), descriptor ); // we could have a composing constraint which does not need its own validator. if ( !descriptor.getConstraintValidatorClasses().isEmpty() ) { if ( log.isTraceEnabled() ) { log.trace( "Validating value {} against constraint defined by {}", localExecutionContext.getCurrentValidatedValue(), descriptor ); } ConstraintValidator validator = getInitializedValidator( type, executionContext.getConstraintValidatorFactory() ); validateSingleConstraint( executionContext, localExecutionContext, constraintViolations, constraintValidatorContext, validator ); } if ( reportAsSingleViolation() && constraintViolations.size() > 0 ) { constraintViolations.clear(); final String message = ( String ) getDescriptor().getAttributes().get( "message" ); MessageAndPath messageAndPath = new MessageAndPath( message, localExecutionContext.getPropertyPath() ); ConstraintViolation violation = executionContext.createConstraintViolation( localExecutionContext, messageAndPath, descriptor ); constraintViolations.add( violation ); } } private void validateSingleConstraint(GlobalExecutionContext executionContext, LocalExecutionContext localExecutionContext, List> constraintViolations, ConstraintValidatorContextImpl constraintValidatorContext, ConstraintValidator validator) { boolean isValid; try { isValid = validator.isValid( localExecutionContext.getCurrentValidatedValue(), constraintValidatorContext ); } catch ( RuntimeException e ) { throw new ValidationException( "Unexpected exception during isValid call", e ); } if ( !isValid ) { constraintViolations.addAll( executionContext.createConstraintViolations( localExecutionContext, constraintValidatorContext ) ); } } private boolean reportAsSingleViolation() { return getDescriptor().isReportAsSingleViolation(); } /** * @param type The type of the value to be validated (the type of the member/class the constraint was placed on). * @param constraintFactory constraint factory used to instantiate the constraint validator. * * @return A initialized constraint validator matching the type of the value to be validated. */ @SuppressWarnings("unchecked") private ConstraintValidator getInitializedValidator(Type type, ConstraintValidatorFactory constraintFactory) { Class> validatorClass = findMatchingValidatorClass( type ); // check if we have the default validator factory. If not we don't use caching (see HV-242) if ( !( constraintFactory instanceof ConstraintValidatorFactoryImpl ) ) { return createAndInitializeValidator( constraintFactory, validatorClass ); } ConstraintValidator constraintValidator; ValidatorCacheKey key = new ValidatorCacheKey( constraintFactory, validatorClass ); if ( !constraintValidatorCache.containsKey( key ) ) { constraintValidator = createAndInitializeValidator( constraintFactory, validatorClass ); constraintValidatorCache.put( key, constraintValidator ); } else { if ( log.isTraceEnabled() ) { log.trace( "Constraint validator {} found in cache" ); } constraintValidator = ( ConstraintValidator ) constraintValidatorCache.get( key ); } return constraintValidator; } @SuppressWarnings("unchecked") private ConstraintValidator createAndInitializeValidator(ConstraintValidatorFactory constraintFactory, Class> validatorClass) { ConstraintValidator constraintValidator; constraintValidator = ( ConstraintValidator ) constraintFactory.getInstance( validatorClass ); if ( constraintValidator == null ) { throw new ValidationException( "Constraint factory returned null when trying to create instance of " + validatorClass.getName() ); } initializeConstraint( descriptor, constraintValidator ); return constraintValidator; } /** * Runs the validator resolution algorithm. * * @param type The type of the value to be validated (the type of the member/class the constraint was placed on). * * @return The class of a matching validator. */ private Class> findMatchingValidatorClass(Type type) { Map>> validatorTypes = ValidatorTypeHelper.getValidatorsTypes( descriptor.getConstraintValidatorClasses() ); List suitableTypes = new ArrayList(); findSuitableValidatorTypes( type, validatorTypes, suitableTypes ); resolveAssignableTypes( suitableTypes ); verifyResolveWasUnique( type, suitableTypes ); return validatorTypes.get( suitableTypes.get( 0 ) ); } private void verifyResolveWasUnique(Type valueClass, List assignableClasses) { if ( assignableClasses.size() == 0 ) { String className = valueClass.toString(); if ( valueClass instanceof Class ) { Class clazz = ( Class ) valueClass; if ( clazz.isArray() ) { className = clazz.getComponentType().toString() + "[]"; } else { className = clazz.getName(); } } throw new UnexpectedTypeException( "No validator could be found for type: " + className ); } else if ( assignableClasses.size() > 1 ) { StringBuilder builder = new StringBuilder(); builder.append( "There are multiple validator classes which could validate the type " ); builder.append( valueClass ); builder.append( ". The validator classes are: " ); for ( Type clazz : assignableClasses ) { builder.append( clazz ); builder.append( ", " ); } builder.delete( builder.length() - 2, builder.length() ); throw new UnexpectedTypeException( builder.toString() ); } } private void findSuitableValidatorTypes(Type type, Map>> validatorsTypes, List suitableTypes) { for ( Type validatorType : validatorsTypes.keySet() ) { if ( TypeUtils.isAssignable( validatorType, type ) && !suitableTypes.contains( validatorType ) ) { suitableTypes.add( validatorType ); } } } /** * Tries to reduce all assignable classes down to a single class. * * @param assignableTypes The set of all classes which are assignable to the class of the value to be validated and * which are handled by at least one of the validators for the specified constraint. */ private void resolveAssignableTypes(List assignableTypes) { if ( assignableTypes.size() == 0 || assignableTypes.size() == 1 ) { return; } List typesToRemove = new ArrayList(); do { typesToRemove.clear(); Type type = assignableTypes.get( 0 ); for ( int i = 1; i < assignableTypes.size(); i++ ) { if ( TypeUtils.isAssignable( type, assignableTypes.get( i ) ) ) { typesToRemove.add( type ); } else if ( TypeUtils.isAssignable( assignableTypes.get( i ), type ) ) { typesToRemove.add( assignableTypes.get( i ) ); } } assignableTypes.removeAll( typesToRemove ); } while ( typesToRemove.size() > 0 ); } private void initializeConstraint (ConstraintDescriptor descriptor, ConstraintValidator constraintValidator) { try { constraintValidator.initialize( descriptor.getAnnotation() ); } catch ( RuntimeException e ) { throw new ValidationException( "Unable to initialize " + constraintValidator.getClass().getName(), e ); } } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "ConstraintTree" ); sb.append( "{ descriptor=" ).append( descriptor ); sb.append( ", isRoot=" ).append( parent == null ); sb.append( ", constraintValidatorCache=" ).append( constraintValidatorCache ); sb.append( '}' ); return sb.toString(); } private static class ValidatorCacheKey { private ConstraintValidatorFactory constraintValidatorFactory; private Class> validatorType; private ValidatorCacheKey(ConstraintValidatorFactory constraintValidatorFactory, Class> validatorType) { this.constraintValidatorFactory = constraintValidatorFactory; this.validatorType = validatorType; } @Override public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } ValidatorCacheKey that = ( ValidatorCacheKey ) o; if ( constraintValidatorFactory != null ? !constraintValidatorFactory.equals( that.constraintValidatorFactory ) : that.constraintValidatorFactory != null ) { return false; } if ( validatorType != null ? !validatorType.equals( that.validatorType ) : that.validatorType != null ) { return false; } return true; } @Override public int hashCode() { int result = constraintValidatorFactory != null ? constraintValidatorFactory.hashCode() : 0; result = 31 * result + ( validatorType != null ? validatorType.hashCode() : 0 ); return result; } } } ././@LongLink0000000000000000000000000000014500000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000755000175000017500000000000011402110364033335 5ustar twernertwerner././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/NewInstance.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000340511262172500033345 0ustar twernertwerner// $Id: NewInstance.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; import javax.validation.ValidationException; /** * @author Emmanuel Bernard */ public class NewInstance implements PrivilegedAction { private final Class clazz; private final String message; public static NewInstance action(Class clazz, String message) { return new NewInstance( clazz, message ); } private NewInstance(Class clazz, String message) { this.clazz = clazz; this.message = message; } public T run() { try { return clazz.newInstance(); } catch ( InstantiationException e ) { throw new ValidationException( "Unable to instantiate " + message + ": " + clazz, e ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to instantiate " + clazz, e ); } catch ( RuntimeException e ) { throw new ValidationException( "Unable to instantiate " + clazz, e ); } } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetConstructor.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000301311262172500033340 0ustar twernertwerner// $Id: GetConstructor.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Constructor; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetConstructor implements PrivilegedAction> { private final Class clazz; private final Class[] params; public static GetConstructor action(Class clazz, Class... params) { return new GetConstructor( clazz, params ); } private GetConstructor(Class clazz, Class... params) { this.clazz = clazz; this.params = params; } public Constructor run() { try { return clazz.getConstructor(params); } catch ( NoSuchMethodException e ) { return null; } } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000755000175000017500000000000011402110363033334 5ustar twernertwerner././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000175411262172500033352 0ustar twernertwerner Classes in this package allow to generate annotation proxies. ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/AnnotationDescriptor.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000446011262172500033347 0ustar twernertwerner// $Id: AnnotationDescriptor.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util.annotationfactory; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.Map; /** * Encapsulates the data you need to create an annotation. In * particular, it stores the type of an Annotation instance * and the values of its elements. * The "elements" we're talking about are the annotation attributes, * not its targets (the term "element" is used ambiguously * in Java's annotations documentation). * * @author Paolo Perrotta * @author Davide Marchignoli * @author Hardy Ferentschik */ public class AnnotationDescriptor { private final Class type; private final Map elements = new HashMap(); public AnnotationDescriptor(Class annotationType) { this.type = annotationType; } public AnnotationDescriptor(Class annotationType, Map elements) { this.type = annotationType; for (Map.Entry entry : elements.entrySet()) { this.elements.put( entry.getKey(), entry.getValue() ); } } public void setValue(String elementName, Object value) { elements.put( elementName, value ); } public Object valueOf(String elementName) { return elements.get( elementName ); } public boolean containsElement(String elementName) { return elements.containsKey( elementName ); } public int numberOfElements() { return elements.size(); } public Class type() { return type; } } ././@LongLink0000000000000000000000000000021500000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/AnnotationFactory.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000543111262172500033346 0ustar twernertwerner// $Id: AnnotationFactory.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util.annotationfactory; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Proxy; import java.security.AccessController; import org.hibernate.validator.util.GetConstructor; import org.hibernate.validator.util.GetClassLoader; /** * Creates live annotations (actually AnnotationProxies) from AnnotationDescriptors. * * @author Paolo Perrotta * @author Davide Marchignoli * @see AnnotationProxy */ public class AnnotationFactory { @SuppressWarnings("unchecked") public static T create(AnnotationDescriptor descriptor) { boolean isSecured = System.getSecurityManager() != null; GetClassLoader action = GetClassLoader.fromContext(); ClassLoader classLoader = isSecured ? AccessController.doPrivileged( action ) : action.run(); //TODO round 34ms to generate the proxy, hug! is Javassist Faster? Class proxyClass = (Class) Proxy.getProxyClass( classLoader, descriptor.type() ); InvocationHandler handler = new AnnotationProxy( descriptor ); try { return getProxyInstance( proxyClass, handler ); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException( e ); } } private static T getProxyInstance(Class proxyClass, InvocationHandler handler) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException { GetConstructor action = GetConstructor.action( proxyClass, InvocationHandler.class ); final Constructor constructor; if ( System.getSecurityManager() != null ) { constructor = AccessController.doPrivileged( action ); } else { constructor = action.run(); } return constructor.newInstance( handler ); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/annotationfactory/AnnotationProxy.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000001225611262172500033351 0ustar twernertwerner// $Id: AnnotationProxy.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util.annotationfactory; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.security.AccessController; import org.hibernate.validator.util.GetDeclaredMethods; /** * A concrete implementation of Annotation that pretends it is a * "real" source code annotation. It's also an InvocationHandler. *

* When you create an AnnotationProxy, you must initialize it * with an AnnotationDescriptor. * The adapter checks that the provided elements are the same elements defined * in the annotation interface. However, it does not check that their * values are the right type. If you omit an element, the adapter will use the * default value for that element from the annotation interface, if it exists. * If no default exists, it will throw an exception. *

* Warning: this class does not implement hashCode() and * equals() - it just uses the ones it inherits from Object. * This means that an AnnotationProxy does not follow the * recommendations of the Annotation javadoc about these two * methods. That's why you should never mix AnnotationProxies * with "real" annotations. For example, don't put them into the same * Collection. * * @author Paolo Perrotta * @author Davide Marchignoli * @see java.lang.annotation.Annotation */ public class AnnotationProxy implements Annotation, InvocationHandler { private final Class annotationType; //FIXME it's probably better to use String as a key rather than Method // to speed up and avoid any fancy permsize/GC issue // I'd better check the litterature on the subject private final Map values; public AnnotationProxy(AnnotationDescriptor descriptor) { this.annotationType = descriptor.type(); values = getAnnotationValues( descriptor ); } private Map getAnnotationValues(AnnotationDescriptor descriptor) { Map result = new HashMap(); int processedValuesFromDescriptor = 0; GetDeclaredMethods action = GetDeclaredMethods.action( annotationType ); final Method[] declaredMethods; if ( System.getSecurityManager() != null ) { declaredMethods = AccessController.doPrivileged( action ); } else { declaredMethods = action.run(); } for ( Method m : declaredMethods ) { if ( descriptor.containsElement( m.getName() ) ) { result.put( m, descriptor.valueOf( m.getName() ) ); processedValuesFromDescriptor++; } else if ( m.getDefaultValue() != null ) { result.put( m, m.getDefaultValue() ); } else { throw new IllegalArgumentException( "No value provided for " + m.getName() ); } } if ( processedValuesFromDescriptor != descriptor.numberOfElements() ) { throw new RuntimeException( "Trying to instanciate " + annotationType + " with unknown paramters." ); } return result; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ( values.containsKey( method ) ) { return values.get( method ); } return method.invoke( this, args ); } public Class annotationType() { return annotationType; } public String toString() { StringBuilder result = new StringBuilder(); result.append( '@' ).append( annotationType().getName() ).append( '(' ); for ( Method m : getRegisteredMethodsInAlphabeticalOrder() ) { result.append( m.getName() ).append( '=' ).append( values.get( m ) ).append( ", " ); } // remove last separator: if ( values.size() > 0 ) { result.delete( result.length() - 2, result.length() ); result.append( ")" ); } else { result.delete( result.length() - 1, result.length() ); } return result.toString(); } private SortedSet getRegisteredMethodsInAlphabeticalOrder() { SortedSet result = new TreeSet( new Comparator() { public int compare(Method o1, Method o2) { return o1.getName().compareTo( o2.getName() ); } } ); //List result = new LinkedList(); result.addAll( values.keySet() ); return result; } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/ReflectionHelper.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000003453311271345076033365 0ustar twernertwerner// $Id: ReflectionHelper.java 17838 2009-10-26 16:11:42Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.beans.Introspector; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.validation.ValidationException; import com.googlecode.jtype.TypeUtils; /** * Some reflection utility methods. * * @author Hardy Ferentschik */ public class ReflectionHelper { /** * Private constructor in order to avoid instantiation. */ private ReflectionHelper() { } //run client in privileged block @SuppressWarnings("unchecked") static T getAnnotationParameter(Annotation annotation, String parameterName, Class type) { try { Method m = annotation.getClass().getMethod( parameterName ); Object o = m.invoke( annotation ); if ( o.getClass().getName().equals( type.getName() ) ) { return ( T ) o; } else { String msg = "Wrong parameter type. Expected: " + type.getName() + " Actual: " + o.getClass().getName(); throw new ValidationException( msg ); } } catch ( NoSuchMethodException e ) { String msg = "The specified annotation defines no parameter '" + parameterName + "'."; throw new ValidationException( msg, e ); } catch ( IllegalAccessException e ) { String msg = "Unable to get '" + parameterName + "' from " + annotation.getClass().getName(); throw new ValidationException( msg, e ); } catch ( InvocationTargetException e ) { String msg = "Unable to get '" + parameterName + "' from " + annotation.getClass().getName(); throw new ValidationException( msg, e ); } } /** * Process bean properties getter by applying the JavaBean naming conventions. * * @param member the member for which to get the property name. * * @return The bean method name with the "is" or "get" prefix stripped off, null * the method name id not according to the JavaBeans standard. */ public static String getPropertyName(Member member) { String name = null; if ( member instanceof Field ) { name = member.getName(); } if ( member instanceof Method ) { String methodName = member.getName(); if ( methodName.startsWith( "is" ) ) { name = Introspector.decapitalize( methodName.substring( 2 ) ); } else if ( methodName.startsWith( "has" ) ) { name = Introspector.decapitalize( methodName.substring( 3 ) ); } else if ( methodName.startsWith( "get" ) ) { name = Introspector.decapitalize( methodName.substring( 3 ) ); } } return name; } /** * Returns the type of the field of return type of a method. * * @param member the member for which to get the type. * * @return Returns the type of the field of return type of a method. */ public static Class getType(Member member) { Class type = null; if ( member instanceof Field ) { type = ( ( Field ) member ).getType(); } if ( member instanceof Method ) { type = ( ( Method ) member ).getReturnType(); } return type; } /** * @param member The Member instance for which to retrieve the type. * * @return Returns the Type of the given Field or Method. * * @throws IllegalArgumentException in case member is not a Field or Method. */ public static Type typeOf(Member member) { Type type; if ( member instanceof Field ) { type = ( ( Field ) member ).getGenericType(); } else if ( member instanceof Method ) { type = ( ( Method ) member ).getGenericReturnType(); } else { throw new IllegalArgumentException( "Member " + member + " is neither a field nor a method" ); } if ( type instanceof TypeVariable ) { type = TypeUtils.getErasedType( type ); } return type; } public static Object getValue(Member member, Object object) { Object value = null; if ( member instanceof Method ) { Method method = ( Method ) member; try { value = method.invoke( object ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to access " + method.getName(), e ); } catch ( InvocationTargetException e ) { throw new ValidationException( "Unable to access " + method.getName(), e ); } } else if ( member instanceof Field ) { Field field = ( Field ) member; try { value = field.get( object ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to access " + field.getName(), e ); } } return value; } static void setAccessibility(Member member) { // HV-257 // Also set accessibility in case of public abstract members. If you proxy an interface using java.lang.reflect.Proxy // per default you will get a IllegalAccessException since you are not allowed to access public abstract methods. // Seems odd. One could argue that the proxy 'is' the implementation for the interface method and hence they // should be accessible. Maybe this is a JVM bug !? if ( !Modifier.isPublic( member.getModifiers() ) || ( Modifier.isPublic( member.getModifiers() ) && Modifier.isAbstract( member.getModifiers() ) ) ) { ( ( AccessibleObject ) member ).setAccessible( true ); } } /** * Determines the type of elements of an Iterable, array or the value of a Map. * * @param type the type to inspect * * @return Returns the type of elements of an Iterable, array or the value of a Map. * null is returned in case the type is not indexable (in the context of JSR 303). */ public static Type getIndexedType(Type type) { Type indexedType = null; if ( isIterable( type ) && type instanceof ParameterizedType ) { ParameterizedType paramType = ( ParameterizedType ) type; indexedType = paramType.getActualTypeArguments()[0]; } else if ( isMap( type ) && type instanceof ParameterizedType ) { ParameterizedType paramType = ( ParameterizedType ) type; indexedType = paramType.getActualTypeArguments()[1]; } else if ( TypeUtils.isArray( type ) ) { indexedType = TypeUtils.getComponentType( type ); } return indexedType; } /** * @param type the type to check. * * @return Returns true if type is a iterable type, false otherwise. */ public static boolean isIterable(Type type) { if ( type instanceof Class && extendsOrImplements( ( Class ) type, Iterable.class ) ) { return true; } if ( type instanceof ParameterizedType ) { return isIterable( ( ( ParameterizedType ) type ).getRawType() ); } if ( type instanceof WildcardType ) { Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds(); return upperBounds.length != 0 && isIterable( upperBounds[0] ); } return false; } /** * @param type the type to check. * * @return Returns true if type is implementing Map, false otherwise. */ public static boolean isMap(Type type) { if ( type instanceof Class && extendsOrImplements( ( Class ) type, Map.class ) ) { return true; } if ( type instanceof ParameterizedType ) { return isMap( ( ( ParameterizedType ) type ).getRawType() ); } if ( type instanceof WildcardType ) { Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds(); return upperBounds.length != 0 && isMap( upperBounds[0] ); } return false; } /** * @param type the type to check. * * @return Returns true if type is implementing List, false otherwise. */ public static boolean isList(Type type) { if ( type instanceof Class && extendsOrImplements( ( Class ) type, List.class ) ) { return true; } if ( type instanceof ParameterizedType ) { return isList( ( ( ParameterizedType ) type ).getRawType() ); } if ( type instanceof WildcardType ) { Type[] upperBounds = ( ( WildcardType ) type ).getUpperBounds(); return upperBounds.length != 0 && isList( upperBounds[0] ); } return false; } /** * Tries to retrieve the indexed value from the specified object. * * @param value The object from which to retrieve the indexed value. The object has to be non null and * either a collection or array. * @param index The index. The index does not have to be numerical. value could also be a map in which * case the index could also be a string key. * * @return The indexed value or null if value is null or not a collection or array. * null is also returned in case the index does not exist. */ public static Object getIndexedValue(Object value, Integer index) { if ( value == null ) { return null; } Iterator iter; Type type = value.getClass(); if ( isIterable( type ) ) { iter = ( ( Iterable ) value ).iterator(); } else if ( TypeUtils.isArray( type ) ) { List arrayList = Arrays.asList( ( Object ) value ); iter = arrayList.iterator(); } else { return null; } int i = 0; Object o; while ( iter.hasNext() ) { o = iter.next(); if ( i == index ) { return o; } i++; } return null; } /** * Tries to retrieve the mapped value from the specified object. * * @param value The object from which to retrieve the mapped value. The object has to be non {@code null} and * must implement the @{code Map} interface. * @param key The map key. index. * * @return The mapped value or {@code null} if {@code value} is {@code null} or not implementing @{code Map}. */ public static Object getMappedValue(Object value, Object key) { if ( value == null || !( value instanceof Map ) ) { return null; } Map map = ( Map ) value; //noinspection SuspiciousMethodCalls return map.get( key ); } /** * Returns the method with the specified name or null if it does not exist. * * @param clazz The class to check. * @param methodName The method name. * * @return Returns the method with the specified name or null if it does not exist. */ //run client in privileged block static Method getMethod(Class clazz, String methodName) { try { char string[] = methodName.toCharArray(); string[0] = Character.toUpperCase( string[0] ); methodName = new String( string ); try { return clazz.getMethod( "get" + methodName ); } catch ( NoSuchMethodException e ) { return clazz.getMethod( "is" + methodName ); } } catch ( NoSuchMethodException e ) { return null; } } /** * Returns the autoboxed type of a primitive type. * * @param primitiveType the primitive type * * @return the autoboxed type of a primitive type. * * @throws IllegalArgumentException in case the parameter {@code primitiveType} does not represent a primitive type. */ public static Class boxedType(Type primitiveType) { if ( !( primitiveType instanceof Class ) && !( ( Class ) primitiveType ).isPrimitive() ) { throw new IllegalArgumentException( primitiveType.getClass() + "has to be a primitive type" ); } if ( primitiveType == boolean.class ) { return Boolean.class; } else if ( primitiveType == char.class ) { return Character.class; } else if ( primitiveType == double.class ) { return Double.class; } else if ( primitiveType == float.class ) { return Float.class; } else if ( primitiveType == long.class ) { return Long.class; } else if ( primitiveType == int.class ) { return Integer.class; } else if ( primitiveType == short.class ) { return Short.class; } else if ( primitiveType == byte.class ) { return Byte.class; } else { throw new RuntimeException( "Unhandled primitive type." ); } } /** * Get all superclasses and interfaces recursively. * * @param clazz The class to start the search with. * @param classes List of classes to which to add all found super classes and interfaces. */ public static void computeClassHierarchy(Class clazz, List> classes) { for ( Class current = clazz; current != null; current = current.getSuperclass() ) { if ( classes.contains( current ) ) { return; } classes.add( current ); for ( Class currentInterface : current.getInterfaces() ) { computeClassHierarchy( currentInterface, classes ); } } } /** * Checks whether the specified {@code clazz} extends or inherits the specified super class or interface. * * @param clazz @{code Class} to check. * @param superClassOrInterface The super class/interface {@code clazz}. * * @return {@code true} if {@code clazz} extends or implements {@code superClassOrInterface}, {@code false} otherwise. */ private static boolean extendsOrImplements(Class clazz, Class superClassOrInterface) { List> classes = new ArrayList>(); computeClassHierarchy( clazz, classes ); return classes.contains( superClassOrInterface ); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/LoadClass.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000346011262172500033346 0ustar twernertwerner// $Id: LoadClass.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; import javax.validation.ValidationException; /** * @author Emmanuel Bernard */ public class LoadClass implements PrivilegedAction> { private final String className; private final Class caller; public static LoadClass action(String className, Class caller) { return new LoadClass( className, caller ); } private LoadClass(String className, Class caller) { this.className = className; this.caller = caller; } public Class run() { try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if ( contextClassLoader != null ) { return contextClassLoader.loadClass( className ); } } catch ( Throwable e ) { // ignore } try { return Class.forName( className, true, caller.getClassLoader() ); } catch ( ClassNotFoundException e ) { throw new ValidationException("Unable to load class: " + className, e); } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000174011262172500033345 0ustar twernertwerner This package contains independend helper classes. ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetDeclaredField.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000310711262172500033344 0ustar twernertwerner// $Id: GetDeclaredField.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Field; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetDeclaredField implements PrivilegedAction { private final Class clazz; private final String fieldName; public static GetDeclaredField action(Class clazz, String fieldName) { return new GetDeclaredField( clazz, fieldName ); } private GetDeclaredField(Class clazz, String fieldName) { this.clazz = clazz; this.fieldName = fieldName; } public Field run() { try { final Field field = clazz.getDeclaredField( fieldName ); ReflectionHelper.setAccessibility( field ); return field; } catch ( NoSuchFieldException e ) { return null; } } } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/Version.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000412511262172500033345 0ustar twernertwerner// $Id: Version.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.net.URL; import java.util.jar.Attributes; import java.util.jar.Manifest; import org.slf4j.Logger; /** * @author Hardy Ferentschik */ public class Version { private static final Logger log = org.hibernate.validator.util.LoggerFactory.make(); static { Class clazz = Version.class; String classFileName = clazz.getSimpleName() + ".class"; String classFilePath = clazz.getCanonicalName().replace( '.', '/' ) + ".class"; String pathToThisClass = clazz.getResource( classFileName ).toString(); String pathToManifest = pathToThisClass.substring( 0, pathToThisClass.indexOf( classFilePath ) - 1 ) + "/META-INF/MANIFEST.MF"; log.trace( "Manifest file {}", pathToManifest ); Manifest manifest = null; String version; try { manifest = new Manifest( new URL( pathToManifest ).openStream() ); } catch ( Exception e ) { log.warn( "Unable to determine version of Hibernate Validator" ); } if ( manifest == null ) { version = "?"; } else { version = manifest.getMainAttributes().getValue( Attributes.Name.IMPLEMENTATION_VERSION ); } log.info( "Hibernate Validator {}", version ); } public static void touch() { } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/IdentitySet.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000512611262172500033347 0ustar twernertwerner// $Id: IdentitySet.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.util.Collection; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Set that compares object by identity rather than equality. Wraps around a IdentityHashMap * * @author Emmanuel Bernard */ public class IdentitySet implements Set { private Map map; private Object CONTAINS = new Object(); public IdentitySet() { this( 10 ); } public IdentitySet(int size) { this.map = new IdentityHashMap( size ); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey( o ); } public Iterator iterator() { return map.keySet().iterator(); } public Object[] toArray() { return map.keySet().toArray(); } public boolean add(Object o) { return map.put( o, CONTAINS ) == null; } public boolean remove(Object o) { return map.remove( o ) == CONTAINS; } public boolean addAll(Collection c) { boolean doThing = false; for ( Object o : c ) { doThing = doThing || add( o ); } return doThing; } public void clear() { map.clear(); } public boolean removeAll(Collection c) { boolean remove = false; for ( Object o : c ) { remove = remove || remove( o ); } return remove; } public boolean retainAll(Collection c) { throw new UnsupportedOperationException(); } public boolean containsAll(Collection c) { for ( Object o : c ) { if ( !contains( o ) ) { return false; } } return true; } public Object[] toArray(Object[] a) { return map.keySet().toArray( a ); } @Override public String toString() { return "IdentitySet{" + "map=" + map + '}'; } } ././@LongLink0000000000000000000000000000017300000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetDeclaredFields.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000250511262172500033345 0ustar twernertwerner// $Id: GetDeclaredFields.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; import java.lang.reflect.Field; /** * @author Emmanuel Bernard */ public class GetDeclaredFields implements PrivilegedAction { private final Class clazz; public static GetDeclaredFields action(Class clazz) { return new GetDeclaredFields( clazz ); } private GetDeclaredFields(Class clazz) { this.clazz = clazz; } public Field[] run() { return clazz.getDeclaredFields(); } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/ValidatorTypeHelper.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000001173211262172500033347 0ustar twernertwerner// $Id: ValidatorTypeHelper.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.annotation.Annotation; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.validation.ConstraintValidator; import javax.validation.ValidationException; import com.googlecode.jtype.TypeUtils; /** * Helper methods around ConstraintValidator types. * * @author Emmanuel Bernanrd * @author Hardy Ferentschik */ public class ValidatorTypeHelper { private static final int VALIDATOR_TYPE_INDEX = 1; /** * @param validators List of constraint validator classes (for a given constraint). * * @return Return a Map<Class, Class<? extends ConstraintValidator>> where the map * key is the type the validator accepts and value the validator class itself. */ public static Map>> getValidatorsTypes( List>> validators) { if ( validators == null || validators.size() == 0 ) { throw new ValidationException( "No ConstraintValidators associated to @Constraint" ); } else { Map>> validatorsTypes = new HashMap>>(); for ( Class> validator : validators ) { validatorsTypes.put( extractType( validator ), validator ); } return validatorsTypes; } } private static Type extractType(Class> validator) { Map resolvedTypes = new HashMap(); Type constraintValidatorType = resolveTypes( resolvedTypes, validator ); //we now have all bind from a type to its resolution at one level Type validatorType = ( ( ParameterizedType ) constraintValidatorType ).getActualTypeArguments()[VALIDATOR_TYPE_INDEX]; if ( validatorType == null ) { throw new ValidationException( "null is an invalid type for a constraint validator." ); } else if ( validatorType instanceof GenericArrayType ) { validatorType = TypeUtils.getArrayType( TypeUtils.getComponentType( validatorType ) ); } while ( resolvedTypes.containsKey( validatorType ) ) { validatorType = resolvedTypes.get( validatorType ); } //FIXME raise an exception if validatorType is not a class return validatorType; } private static Type resolveTypes(Map resolvedTypes, Type type) { if ( type == null ) { return null; } else if ( type instanceof Class ) { Class clazz = ( Class ) type; final Type returnedType = resolveTypeForClassAndHierarchy( resolvedTypes, clazz ); if ( returnedType != null ) { return returnedType; } } else if ( type instanceof ParameterizedType ) { ParameterizedType paramType = ( ParameterizedType ) type; if ( !( paramType.getRawType() instanceof Class ) ) { return null; //don't know what to do here } Class rawType = ( Class ) paramType.getRawType(); TypeVariable[] originalTypes = rawType.getTypeParameters(); Type[] partiallyResolvedTypes = paramType.getActualTypeArguments(); int nbrOfParams = originalTypes.length; for ( int i = 0; i < nbrOfParams; i++ ) { resolvedTypes.put( originalTypes[i], partiallyResolvedTypes[i] ); } if ( rawType.equals( ConstraintValidator.class ) ) { //we found our baby return type; } else { Type returnedType = resolveTypeForClassAndHierarchy( resolvedTypes, rawType ); if ( returnedType != null ) { return returnedType; } } } //else we don't care I think return null; } private static Type resolveTypeForClassAndHierarchy(Map resolvedTypes, Class clazz) { Type returnedType = resolveTypes( resolvedTypes, clazz.getGenericSuperclass() ); if ( returnedType != null ) { return returnedType; } for ( Type genericInterface : clazz.getGenericInterfaces() ) { returnedType = resolveTypes( resolvedTypes, genericInterface ); if ( returnedType != null ) { return returnedType; } } return null; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/ContainsMethod.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000263211262172500033346 0ustar twernertwerner// $Id: ContainsMethod.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class ContainsMethod implements PrivilegedAction { private final Class clazz; private final String property; public static ContainsMethod action(Class clazz, String property) { return new ContainsMethod( clazz, property ); } private ContainsMethod(Class clazz, String property) { this.clazz = clazz; this.property = property; } public Boolean run() { return ReflectionHelper.getMethod( clazz, property ) != null; } } ././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetClassLoader.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000304411262172500033344 0ustar twernertwerner// $Id: GetClassLoader.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetClassLoader implements PrivilegedAction { private final Class clazz; public static GetClassLoader fromContext() { return new GetClassLoader( null ); } public static GetClassLoader fromClass(Class clazz) { if ( clazz == null ) throw new IllegalArgumentException("Class is null"); return new GetClassLoader( clazz ); } private GetClassLoader(Class clazz) { this.clazz = clazz; } public ClassLoader run() { if (clazz != null) { return clazz.getClassLoader(); } else { return Thread.currentThread().getContextClassLoader(); } } } ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/SetAccessibility.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000253311262172500033346 0ustar twernertwerner// $Id: SetAccessibility.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Member; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class SetAccessibility implements PrivilegedAction { private final Member member; public static SetAccessibility action(Member member) { return new SetAccessibility( member ); } private SetAccessibility(Member member) { this.member = member; } public Object run() { ReflectionHelper.setAccessibility( member ); return member; } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetDeclaredMethods.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000251611262172500033347 0ustar twernertwerner// $Id: GetDeclaredMethods.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; import java.lang.reflect.Method; /** * @author Emmanuel Bernard */ public class GetDeclaredMethods implements PrivilegedAction { private final Class clazz; public static GetDeclaredMethods action(Class clazz) { return new GetDeclaredMethods( clazz ); } private GetDeclaredMethods(Class clazz) { this.clazz = clazz; } public Method[] run() { return clazz.getDeclaredMethods(); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/ContainsField.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000272211262172500033346 0ustar twernertwerner// $Id: ContainsField.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class ContainsField implements PrivilegedAction { private final Class clazz; private final String property; public static ContainsField action(Class clazz, String property) { return new ContainsField( clazz, property ); } private ContainsField(Class clazz, String property) { this.clazz = clazz; this.property = property; } public Boolean run() { try { clazz.getDeclaredField( property ); return true; } catch ( NoSuchFieldException e ) { return false; } } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetAnnotationParameter.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000323111262172500033342 0ustar twernertwerner// $Id: GetAnnotationParameter.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.annotation.Annotation; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetAnnotationParameter implements PrivilegedAction { private final Annotation annotation; private final String parameterName; private final Class type; public static GetAnnotationParameter action(Annotation annotation, String parameterName, Class type) { return new GetAnnotationParameter( annotation, parameterName, type ); } private GetAnnotationParameter(Annotation annotation, String parameterName, Class type) { this.annotation = annotation; this.parameterName = parameterName; this.type = type; } public T run() { return ReflectionHelper.getAnnotationParameter( annotation, parameterName, type ); } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetMethodFromPropertyName.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000275111262172500033350 0ustar twernertwerner// $Id: GetMethodFromPropertyName.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Method; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetMethodFromPropertyName implements PrivilegedAction { private final Class clazz; private final String property; public static GetMethodFromPropertyName action(Class clazz, String property) { return new GetMethodFromPropertyName( clazz, property ); } private GetMethodFromPropertyName(Class clazz, String property) { this.clazz = clazz; this.property = property; } public Method run() { return ReflectionHelper.getMethod( clazz, property ); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/LazyValidatorFactory.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000600311262172500033342 0ustar twernertwerner// $Id: LazyValidatorFactory.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import javax.validation.ValidatorFactory; import javax.validation.Validator; import javax.validation.ValidatorContext; import javax.validation.MessageInterpolator; import javax.validation.Configuration; import javax.validation.Validation; import javax.validation.TraversableResolver; import javax.validation.ConstraintValidatorFactory; /** * This class lazily initialize the ValidatorFactory on the first usage * One benefit is that no domain class is loaded until the * ValidatorFactory is really needed. * Useful to avoid loading classes before JPA is initialized * and has enhanced its classes. * * Experimental, not considered a public API * @author Emmanuel Bernard */ public class LazyValidatorFactory implements ValidatorFactory { private final Configuration configuration; private volatile ValidatorFactory delegate; //use as a barrier /** * Use the default ValidatorFactory creation routine */ public LazyValidatorFactory() { this(null); } public LazyValidatorFactory(Configuration configuration) { this.configuration = configuration; } private ValidatorFactory getDelegate() { ValidatorFactory result = delegate; if (result == null) { synchronized ( this ) { result = delegate; if (result == null) { delegate = result = initFactory(); } } } return result; } public Validator getValidator() { return getDelegate().getValidator(); } //we can initialize several times that's ok private ValidatorFactory initFactory() { if ( configuration == null ) { return Validation.buildDefaultValidatorFactory(); } else { return configuration.buildValidatorFactory(); } } public ValidatorContext usingContext() { return getDelegate().usingContext(); } public MessageInterpolator getMessageInterpolator() { return getDelegate().getMessageInterpolator(); } public TraversableResolver getTraversableResolver() { return getDelegate().getTraversableResolver(); } public ConstraintValidatorFactory getConstraintValidatorFactory() { return getDelegate().getConstraintValidatorFactory(); } public T unwrap(Class clazz) { return getDelegate().unwrap( clazz ); } } ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/LoggerFactory.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000214411262172500033344 0ustar twernertwerner// :$ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import org.slf4j.Logger; /** * @author Hardy Ferentschik */ public class LoggerFactory { public static Logger make() { Throwable t = new Throwable(); StackTraceElement directCaller = t.getStackTrace()[1]; return org.slf4j.LoggerFactory.getLogger( directCaller.getClassName() ); } } ././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetMethod.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000273111262172500033346 0ustar twernertwerner// $Id: GetMethod.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.lang.reflect.Method; import java.security.PrivilegedAction; /** * @author Emmanuel Bernard */ public class GetMethod implements PrivilegedAction { private final Class clazz; private final String methodName; public static GetMethod action(Class clazz, String methodName) { return new GetMethod( clazz, methodName ); } private GetMethod(Class clazz, String methodName) { this.clazz = clazz; this.methodName = methodName; } public Method run() { try { return clazz.getMethod(methodName); } catch ( NoSuchMethodException e ) { return null; } } } ././@LongLink0000000000000000000000000000016400000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/GetMethods.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/util/0000644000175000017500000000243611262172500033350 0ustar twernertwerner// $Id: GetMethods.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.util; import java.security.PrivilegedAction; import java.lang.reflect.Method; /** * @author Emmanuel Bernard */ public class GetMethods implements PrivilegedAction { private final Class clazz; public static GetMethods action(Class clazz) { return new GetMethods( clazz ); } private GetMethods(Class clazz) { this.clazz = clazz; } public Method[] run() { return clazz.getMethods(); } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/HibernateValidatorConfiguration.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/Hiber0000644000175000017500000000233111262172500033337 0ustar twernertwerner// $Id: HibernateValidatorConfiguration.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator; import javax.validation.Configuration; /** * Uniquely identify Hibernate Validator in the Bean Validation bootstrap strategy * Also contains Hibernate Validator specific configurations * * @author Emmanuel Bernard */ public interface HibernateValidatorConfiguration extends Configuration { } ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000755000175000017500000000000011402110355033373 5ustar twernertwerner././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000004701411272253663033422 0ustar twernertwerner// $Id: BeanMetaDataImpl.java 17876 2009-10-29 08:52:03Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.GroupDefinitionException; import javax.validation.GroupSequence; import javax.validation.Valid; import javax.validation.groups.Default; import javax.validation.metadata.BeanDescriptor; import javax.validation.metadata.PropertyDescriptor; import org.slf4j.Logger; import org.hibernate.validator.util.GetDeclaredFields; import org.hibernate.validator.util.GetDeclaredMethods; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.ReflectionHelper; import org.hibernate.validator.util.SetAccessibility; /** * This class encapsulates all meta data needed for validation. Implementations of {@code Validator} interface can * instantiate an instance of this class and delegate the metadata extraction to it. * * @author Hardy Ferentschik */ public class BeanMetaDataImpl implements BeanMetaData { private static final Logger log = LoggerFactory.make(); /** * The root bean class for this meta data. */ private final Class beanClass; /** * The main element descriptor for beanClass. */ private BeanDescriptorImpl beanDescriptor; /** * Map of all direct constraints which belong to the entity {@code beanClass}. The constraints are mapped to the class * (eg super class or interface) in which they are defined. */ private Map, List>> metaConstraints = new HashMap, List>>(); /** * List of cascaded members. */ private List cascadedMembers = new ArrayList(); /** * Maps field and method names to their ElementDescriptorImpl. */ private Map propertyDescriptors = new HashMap(); /** * Maps group sequences to the list of group/sequences. */ private List> defaultGroupSequence = new ArrayList>(); /** * Object keeping track of all constraints. */ private final ConstraintHelper constraintHelper; /** * A list of all property names in the class (constraint and un-constraint). */ // Used to avoid ReflectionHelper#containsMembe which is slow private final Set propertyNames = new HashSet( 30 ); public BeanMetaDataImpl(Class beanClass, ConstraintHelper constraintHelper, BeanMetaDataCache beanMetaDataCache) { this( beanClass, constraintHelper, new AnnotationIgnores(), beanMetaDataCache ); } public BeanMetaDataImpl(Class beanClass, ConstraintHelper constraintHelper, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { this.beanClass = beanClass; this.constraintHelper = constraintHelper; createMetaData( annotationIgnores, beanMetaDataCache ); } public Class getBeanClass() { return beanClass; } public BeanDescriptor getBeanDescriptor() { return beanDescriptor; } public List getCascadedMembers() { return Collections.unmodifiableList( cascadedMembers ); } public Map, List>> getMetaConstraintsAsMap() { return Collections.unmodifiableMap( metaConstraints ); } public List> getMetaConstraintsAsList() { List> constraintList = new ArrayList>(); for ( List> list : metaConstraints.values() ) { constraintList.addAll( list ); } return Collections.unmodifiableList( constraintList ); } public void addMetaConstraint(Class clazz, MetaConstraint metaConstraint) { // first we add the meta constraint to our meta constraint map List> constraintList; if ( !metaConstraints.containsKey( clazz ) ) { constraintList = new ArrayList>(); metaConstraints.put( clazz, constraintList ); } else { constraintList = metaConstraints.get( clazz ); } constraintList.add( metaConstraint ); // but we also have to update the descriptors exposing the BV metadata API if ( metaConstraint.getElementType() == ElementType.TYPE ) { beanDescriptor.addConstraintDescriptor( metaConstraint.getDescriptor() ); } else { PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get( metaConstraint.getPropertyName() ); if ( propertyDescriptor == null ) { Member member = metaConstraint.getMember(); propertyDescriptor = addPropertyDescriptorForMember( member, isValidAnnotationPresent( member ) ); } propertyDescriptor.addConstraintDescriptor( metaConstraint.getDescriptor() ); } } public void addCascadedMember(Member member) { setAccessibility( member ); cascadedMembers.add( member ); addPropertyDescriptorForMember( member, true ); } public PropertyDescriptor getPropertyDescriptor(String property) { return propertyDescriptors.get( property ); } public boolean isPropertyPresent(String name) { return propertyNames.contains( name ); } public List> getDefaultGroupSequence() { return Collections.unmodifiableList( defaultGroupSequence ); } public boolean defaultGroupSequenceIsRedefined() { return defaultGroupSequence.size() > 1; } public void setDefaultGroupSequence(List> groupSequence) { defaultGroupSequence = new ArrayList>(); boolean groupSequenceContainsDefault = false; for ( Class group : groupSequence ) { if ( group.getName().equals( beanClass.getName() ) ) { defaultGroupSequence.add( Default.class ); groupSequenceContainsDefault = true; } else if ( group.getName().equals( Default.class.getName() ) ) { throw new GroupDefinitionException( "'Default.class' cannot appear in default group sequence list." ); } else { defaultGroupSequence.add( group ); } } if ( !groupSequenceContainsDefault ) { throw new GroupDefinitionException( beanClass.getName() + " must be part of the redefined default group sequence." ); } if ( log.isTraceEnabled() ) { log.trace( "Members of the default group sequence for bean {} are: {}", beanClass.getName(), defaultGroupSequence ); } } public Set getConstrainedProperties() { return Collections.unmodifiableSet( new HashSet( propertyDescriptors.values() ) ); } /** * Create bean descriptor, find all classes/subclasses/interfaces which have to be taken in consideration * for this validator and create meta data. * * @param annotationIgnores Data structure keeping track on which annotation should be ignored * @param beanMetaDataCache The bean meta data cache */ private void createMetaData(AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { beanDescriptor = new BeanDescriptorImpl( this ); initDefaultGroupSequence(); List> classes = new ArrayList>(); ReflectionHelper.computeClassHierarchy( beanClass, classes ); for ( Class current : classes ) { initClass( current, annotationIgnores, beanMetaDataCache ); } } private void initClass(Class clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { initClassConstraints( clazz, annotationIgnores, beanMetaDataCache ); initMethodConstraints( clazz, annotationIgnores, beanMetaDataCache ); initFieldConstraints( clazz, annotationIgnores, beanMetaDataCache ); } /** * Checks whether there is a default group sequence defined for this class. * See HV-113. */ private void initDefaultGroupSequence() { List> groupSequence = new ArrayList>(); GroupSequence groupSequenceAnnotation = beanClass.getAnnotation( GroupSequence.class ); if ( groupSequenceAnnotation == null ) { groupSequence.add( beanClass ); } else { groupSequence.addAll( Arrays.asList( groupSequenceAnnotation.value() ) ); } setDefaultGroupSequence( groupSequence ); } private void initFieldConstraints(Class clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { GetDeclaredFields action = GetDeclaredFields.action( clazz ); final Field[] fields; if ( System.getSecurityManager() != null ) { fields = AccessController.doPrivileged( action ); } else { fields = action.run(); } for ( Field field : fields ) { addToPropertyNameList( field ); // HV-172 if ( Modifier.isStatic( field.getModifiers() ) ) { continue; } if ( annotationIgnores.isIgnoreAnnotations( field ) ) { continue; } // HV-262 BeanMetaDataImpl cachedMetaData = beanMetaDataCache.getBeanMetaData( clazz ); List> fieldMetaData; boolean cachedFieldIsCascaded = false; if ( cachedMetaData != null && cachedMetaData.getMetaConstraintsAsMap().get( clazz ) != null ) { fieldMetaData = new ArrayList>(); cachedFieldIsCascaded = cachedMetaData.getCascadedMembers().contains( field ); for ( MetaConstraint metaConstraint : cachedMetaData.getMetaConstraintsAsMap().get( clazz ) ) { ConstraintDescriptorImpl descriptor = metaConstraint.getDescriptor(); if ( descriptor.getElementType() == ElementType.FIELD && metaConstraint.getPropertyName().equals( ReflectionHelper.getPropertyName( field ) ) ) { fieldMetaData.add( descriptor ); } } } else { fieldMetaData = findConstraints( field, ElementType.FIELD ); } for ( ConstraintDescriptorImpl constraintDescription : fieldMetaData ) { setAccessibility( field ); MetaConstraint metaConstraint = createMetaConstraint( field, constraintDescription ); addMetaConstraint( clazz, metaConstraint ); } if ( cachedFieldIsCascaded || field.isAnnotationPresent( Valid.class ) ) { addCascadedMember( field ); } } } private void addToPropertyNameList(Member member) { String name = ReflectionHelper.getPropertyName( member ); if ( name != null ) { propertyNames.add( name ); } } private void setAccessibility(Member member) { SetAccessibility action = SetAccessibility.action( member ); if ( System.getSecurityManager() != null ) { AccessController.doPrivileged( action ); } else { action.run(); } } private void initMethodConstraints(Class clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { GetDeclaredMethods action = GetDeclaredMethods.action( clazz ); final Method[] declaredMethods; if ( System.getSecurityManager() != null ) { declaredMethods = AccessController.doPrivileged( action ); } else { declaredMethods = action.run(); } for ( Method method : declaredMethods ) { addToPropertyNameList( method ); // HV-172 if ( Modifier.isStatic( method.getModifiers() ) ) { continue; } if ( annotationIgnores.isIgnoreAnnotations( method ) ) { continue; } // HV-262 BeanMetaDataImpl cachedMetaData = beanMetaDataCache.getBeanMetaData( clazz ); List> methodMetaData; boolean cachedMethodIsCascaded = false; if ( cachedMetaData != null && cachedMetaData.getMetaConstraintsAsMap().get( clazz ) != null ) { cachedMethodIsCascaded = cachedMetaData.getCascadedMembers().contains( method ); methodMetaData = new ArrayList>(); for ( MetaConstraint metaConstraint : cachedMetaData.getMetaConstraintsAsMap().get( clazz ) ) { ConstraintDescriptorImpl descriptor = metaConstraint.getDescriptor(); if ( descriptor.getElementType() == ElementType.METHOD && metaConstraint.getPropertyName().equals( ReflectionHelper.getPropertyName( method ) ) ) { methodMetaData.add( descriptor ); } } } else { methodMetaData = findConstraints( method, ElementType.METHOD ); } for ( ConstraintDescriptorImpl constraintDescription : methodMetaData ) { setAccessibility( method ); MetaConstraint metaConstraint = createMetaConstraint( method, constraintDescription ); addMetaConstraint( clazz, metaConstraint ); } if ( cachedMethodIsCascaded || method.isAnnotationPresent( Valid.class ) ) { addCascadedMember( method ); } } } private PropertyDescriptorImpl addPropertyDescriptorForMember(Member member, boolean isCascaded) { String name = ReflectionHelper.getPropertyName( member ); PropertyDescriptorImpl propertyDescriptor = ( PropertyDescriptorImpl ) propertyDescriptors.get( name ); if ( propertyDescriptor == null ) { propertyDescriptor = new PropertyDescriptorImpl( ReflectionHelper.getType( member ), isCascaded, name, this ); propertyDescriptors.put( name, propertyDescriptor ); } return propertyDescriptor; } private boolean isValidAnnotationPresent(Member member) { return ( ( AnnotatedElement ) member ).isAnnotationPresent( Valid.class ); } private void initClassConstraints(Class clazz, AnnotationIgnores annotationIgnores, BeanMetaDataCache beanMetaDataCache) { if ( annotationIgnores.isIgnoreAnnotations( clazz ) ) { return; } // HV-262 BeanMetaDataImpl cachedMetaData = beanMetaDataCache.getBeanMetaData( clazz ); List> classMetaData; if ( cachedMetaData != null && cachedMetaData.getMetaConstraintsAsMap().get( clazz ) != null ) { classMetaData = new ArrayList>(); for ( MetaConstraint metaConstraint : cachedMetaData.getMetaConstraintsAsMap().get( clazz ) ) { ConstraintDescriptorImpl descriptor = metaConstraint.getDescriptor(); if ( descriptor.getElementType() == ElementType.TYPE ) { classMetaData.add( descriptor ); } } } else { classMetaData = findClassLevelConstraints( clazz ); } for ( ConstraintDescriptorImpl constraintDescription : classMetaData ) { MetaConstraint metaConstraint = createMetaConstraint( null, constraintDescription ); addMetaConstraint( clazz, metaConstraint ); } } private MetaConstraint createMetaConstraint(Member m, ConstraintDescriptorImpl descriptor) { return new MetaConstraint( beanClass, m, descriptor ); } /** * Examines the given annotation to see whether it is a single- or multi-valued constraint annotation. * * @param clazz the class we are currently processing * @param annotation The annotation to examine * @param type the element type on which the annotation/constraint is placed on * * @return A list of constraint descriptors or the empty list in case annotation is neither a * single nor multi-valued annotation. */ private List> findConstraintAnnotations(Class clazz, A annotation, ElementType type) { List> constraintDescriptors = new ArrayList>(); List constraints = new ArrayList(); if ( constraintHelper.isConstraintAnnotation( annotation ) || constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) { constraints.add( annotation ); } // check if we have a multi-valued constraint constraints.addAll( constraintHelper.getMultiValueConstraints( annotation ) ); for ( Annotation constraint : constraints ) { final ConstraintDescriptorImpl constraintDescriptor = buildConstraintDescriptor( clazz, constraint, type ); constraintDescriptors.add( constraintDescriptor ); } return constraintDescriptors; } @SuppressWarnings("unchecked") private ConstraintDescriptorImpl buildConstraintDescriptor(Class clazz, A annotation, ElementType type) { ConstraintDescriptorImpl constraintDescriptor; ConstraintOrigin definedIn = determineOrigin( clazz ); if ( clazz.isInterface() && !clazz.equals( beanClass ) ) { constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, clazz, type, definedIn ); } else { constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, type, definedIn ); } return constraintDescriptor; } /** * Finds all constraint annotations defined for the given class and returns them in a list of * constraint descriptors. * * @param beanClass The class to check for constraints annotations. * * @return A list of constraint descriptors for all constraint specified on the given class. */ private List> findClassLevelConstraints(Class beanClass) { List> metaData = new ArrayList>(); for ( Annotation annotation : beanClass.getAnnotations() ) { metaData.addAll( findConstraintAnnotations( beanClass, annotation, ElementType.TYPE ) ); } return metaData; } /** * Finds all constraint annotations defined for the given field/method and returns them in a list of * constraint descriptors. * * @param member The fields or method to check for constraints annotations. * @param type The element type the constraint/annotation is placed on. * * @return A list of constraint descriptors for all constraint specified for the given field or method. */ private List> findConstraints(Member member, ElementType type) { assert member instanceof Field || member instanceof Method; List> metaData = new ArrayList>(); for ( Annotation annotation : ( ( AnnotatedElement ) member ).getAnnotations() ) { metaData.addAll( findConstraintAnnotations( member.getDeclaringClass(), annotation, type ) ); } return metaData; } private ConstraintOrigin determineOrigin(Class clazz) { if ( clazz.equals( beanClass ) ) { return ConstraintOrigin.DEFINED_LOCALLY; } else { return ConstraintOrigin.DEFINED_IN_HIERARCHY; } } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "BeanMetaDataImpl" ); sb.append( "{beanClass=" ).append( beanClass ); sb.append( ", beanDescriptor=" ).append( beanDescriptor ); sb.append( ", metaConstraints=" ).append( metaConstraints ); sb.append( ", cascadedMembers=" ).append( cascadedMembers ); sb.append( ", propertyDescriptors=" ).append( propertyDescriptors ); sb.append( ", defaultGroupSequence=" ).append( defaultGroupSequence ); sb.append( ", constraintHelper=" ).append( constraintHelper ); sb.append( '}' ); return sb.toString(); } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintHelper.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000004331111262172500033403 0ustar twernertwerner// $Id: ConstraintHelper.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.security.AccessController; import javax.validation.Constraint; import javax.validation.ConstraintDefinitionException; import javax.validation.ConstraintValidator; import javax.validation.ValidationException; import javax.validation.constraints.AssertFalse; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.DecimalMax; import javax.validation.constraints.DecimalMin; import javax.validation.constraints.Digits; import javax.validation.constraints.Future; import javax.validation.constraints.Max; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Null; import javax.validation.constraints.Past; import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; import org.hibernate.validator.constraints.impl.AssertFalseValidator; import org.hibernate.validator.constraints.impl.AssertTrueValidator; import org.hibernate.validator.constraints.impl.DecimalMaxValidatorForNumber; import org.hibernate.validator.constraints.impl.DecimalMaxValidatorForString; import org.hibernate.validator.constraints.impl.DecimalMinValidatorForNumber; import org.hibernate.validator.constraints.impl.DecimalMinValidatorForString; import org.hibernate.validator.constraints.impl.DigitsValidatorForNumber; import org.hibernate.validator.constraints.impl.DigitsValidatorForString; import org.hibernate.validator.constraints.impl.FutureValidatorForCalendar; import org.hibernate.validator.constraints.impl.FutureValidatorForDate; import org.hibernate.validator.constraints.impl.MaxValidatorForNumber; import org.hibernate.validator.constraints.impl.MaxValidatorForString; import org.hibernate.validator.constraints.impl.MinValidatorForNumber; import org.hibernate.validator.constraints.impl.MinValidatorForString; import org.hibernate.validator.constraints.impl.NotNullValidator; import org.hibernate.validator.constraints.impl.NullValidator; import org.hibernate.validator.constraints.impl.PastValidatorForCalendar; import org.hibernate.validator.constraints.impl.PastValidatorForDate; import org.hibernate.validator.constraints.impl.PatternValidator; import org.hibernate.validator.constraints.impl.SizeValidatorForArray; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfBoolean; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfByte; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfChar; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfDouble; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfFloat; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfInt; import org.hibernate.validator.constraints.impl.SizeValidatorForArraysOfLong; import org.hibernate.validator.constraints.impl.SizeValidatorForCollection; import org.hibernate.validator.constraints.impl.SizeValidatorForMap; import org.hibernate.validator.constraints.impl.SizeValidatorForString; import org.hibernate.validator.util.GetMethods; import org.hibernate.validator.util.GetMethod; import org.hibernate.validator.util.GetAnnotationParameter; /** * Keeps track of builtin constraints and their validator implementations, as well as already resolved validator definitions. * * @author Hardy Ferentschik * @author Alaa Nassef */ public class ConstraintHelper { private final ConcurrentHashMap, List>>> builtinConstraints = new ConcurrentHashMap, List>>>(); private final ConcurrentHashMap, List>>> constraintValidatorDefinitons = new ConcurrentHashMap, List>>>(); public ConstraintHelper() { List>> constraintList = new ArrayList>>(); constraintList.add( AssertFalseValidator.class ); builtinConstraints.put( AssertFalse.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( AssertTrueValidator.class ); builtinConstraints.put( AssertTrue.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( DecimalMaxValidatorForNumber.class ); constraintList.add( DecimalMaxValidatorForString.class ); builtinConstraints.put( DecimalMax.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( DecimalMinValidatorForNumber.class ); constraintList.add( DecimalMinValidatorForString.class ); builtinConstraints.put( DecimalMin.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( DigitsValidatorForString.class ); constraintList.add( DigitsValidatorForNumber.class ); builtinConstraints.put( Digits.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( FutureValidatorForCalendar.class ); constraintList.add( FutureValidatorForDate.class ); builtinConstraints.put( Future.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( MaxValidatorForNumber.class ); constraintList.add( MaxValidatorForString.class ); builtinConstraints.put( Max.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( MinValidatorForNumber.class ); constraintList.add( MinValidatorForString.class ); builtinConstraints.put( Min.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( NotNullValidator.class ); builtinConstraints.put( NotNull.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( NullValidator.class ); builtinConstraints.put( Null.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( PastValidatorForCalendar.class ); constraintList.add( PastValidatorForDate.class ); builtinConstraints.put( Past.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( PatternValidator.class ); builtinConstraints.put( Pattern.class, constraintList ); constraintList = new ArrayList>>(); constraintList.add( SizeValidatorForString.class ); constraintList.add( SizeValidatorForCollection.class ); constraintList.add( SizeValidatorForArray.class ); constraintList.add( SizeValidatorForMap.class ); constraintList.add( SizeValidatorForArraysOfBoolean.class ); constraintList.add( SizeValidatorForArraysOfByte.class ); constraintList.add( SizeValidatorForArraysOfChar.class ); constraintList.add( SizeValidatorForArraysOfDouble.class ); constraintList.add( SizeValidatorForArraysOfFloat.class ); constraintList.add( SizeValidatorForArraysOfInt.class ); constraintList.add( SizeValidatorForArraysOfLong.class ); builtinConstraints.put( Size.class, constraintList ); } public List>> getBuiltInConstraints(Class annotationClass) { final List>> builtInList = builtinConstraints.get( annotationClass ); if ( builtInList == null || builtInList.size() == 0 ) { throw new ValidationException( "Unable to find constraints for " + annotationClass ); } List>> constraints = new ArrayList>>( builtInList.size() ); for ( Class> validatorClass : builtInList ) { //safe cause all CV for a given annotation A are CV @SuppressWarnings("unchecked") Class> safeValdiatorClass = ( Class> ) validatorClass; constraints.add( safeValdiatorClass ); } return constraints; } public boolean isBuiltinConstraint(Class annotationType) { return builtinConstraints.containsKey( annotationType ); } /** * Checks whether a given annotation is a multi value constraint or not. * * @param annotation the annotation to check. * * @return true if the specified annotation is a multi value constraints, false * otherwise. */ public boolean isMultiValueConstraint(Annotation annotation) { boolean isMultiValueConstraint = false; try { final GetMethod getMethod = GetMethod.action( annotation.getClass(), "value" ); final Method method; if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( getMethod ); } else { method = getMethod.run(); } if (method != null) { Class returnType = method.getReturnType(); if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) { Annotation[] annotations = ( Annotation[] ) method.invoke( annotation ); for ( Annotation a : annotations ) { if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) { isMultiValueConstraint = true; } else { isMultiValueConstraint = false; break; } } } } } catch ( IllegalAccessException iae ) { // ignore } catch ( InvocationTargetException ite ) { // ignore } return isMultiValueConstraint; } /** * Checks whether a given annotation is a multi value constraint and returns the contained constraints if so. * * @param annotation the annotation to check. * * @return A list of constraint annotations or the empty list if annotation is not a multi constraint * annotation. */ public List getMultiValueConstraints(A annotation) { List annotationList = new ArrayList(); try { final GetMethod getMethod = GetMethod.action( annotation.getClass(), "value" ); final Method method; if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( getMethod ); } else { method = getMethod.run(); } if (method != null) { Class returnType = method.getReturnType(); if ( returnType.isArray() && returnType.getComponentType().isAnnotation() ) { Annotation[] annotations = ( Annotation[] ) method.invoke( annotation ); for ( Annotation a : annotations ) { if ( isConstraintAnnotation( a ) || isBuiltinConstraint( a.annotationType() ) ) { annotationList.add( a ); } } } } } catch ( IllegalAccessException iae ) { // ignore } catch ( InvocationTargetException ite ) { // ignore } return annotationList; } /** * Checks whether the specified annotation is a valid constraint annotation. A constraint annotations has to * fulfill the following conditions: *
    *
  • Has to contain a ConstraintValidator implementation.
  • *
  • Defines a message parameter.
  • *
  • Defines a group parameter.
  • *
  • Defines a payload parameter.
  • *
* * @param annotation The annotation to test. * * @return true if the annotation fulfills the above condtions, false otherwise. */ public boolean isConstraintAnnotation(Annotation annotation) { Constraint constraint = annotation.annotationType() .getAnnotation( Constraint.class ); if ( constraint == null ) { return false; } assertMessageParameterExists( annotation ); assertGroupsParameterExists( annotation ); assertPayloadParameterExists( annotation ); assertNoParameterStartsWithValid( annotation ); return true; } private void assertNoParameterStartsWithValid(Annotation annotation) { final Method[] methods; final GetMethods getMethods = GetMethods.action( annotation.annotationType() ); if ( System.getSecurityManager() != null ) { methods = AccessController.doPrivileged( getMethods ); } else { methods = getMethods.run(); } for ( Method m : methods ) { if ( m.getName().startsWith( "valid" ) ) { String msg = "Parameters starting with 'valid' are not allowed in a constraint."; throw new ConstraintDefinitionException( msg ); } } } private void assertPayloadParameterExists(Annotation annotation) { try { final GetMethod getMethod = GetMethod.action( annotation.annotationType(), "payload" ); final Method method; if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( getMethod ); } else { method = getMethod.run(); } if (method == null) { String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " + "not contain a payload parameter."; throw new ConstraintDefinitionException( msg ); } Class[] defaultPayload = ( Class[] ) method.getDefaultValue(); if ( defaultPayload.length != 0 ) { String msg = annotation.annotationType() .getName() + " contains Constraint annotation, but the payload " + "paramter default value is not the empty array."; throw new ConstraintDefinitionException( msg ); } } catch ( ClassCastException e ) { String msg = annotation.annotationType().getName() + " contains Constraint annotation, but the " + "payload parameter is of wrong type."; throw new ConstraintDefinitionException( msg ); } } private void assertGroupsParameterExists(Annotation annotation) { try { final GetMethod getMethod = GetMethod.action( annotation.annotationType(), "groups" ); final Method method; if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( getMethod ); } else { method = getMethod.run(); } if (method == null) { String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " + "not contain a groups parameter."; throw new ConstraintDefinitionException( msg ); } Class[] defaultGroups = ( Class[] ) method.getDefaultValue(); if ( defaultGroups.length != 0 ) { String msg = annotation.annotationType() .getName() + " contains Constraint annotation, but the groups " + "paramter default value is not the empty array."; throw new ConstraintDefinitionException( msg ); } } catch ( ClassCastException e ) { String msg = annotation.annotationType().getName() + " contains Constraint annotation, but the " + "groups parameter is of wrong type."; throw new ConstraintDefinitionException( msg ); } } private void assertMessageParameterExists(Annotation annotation) { try { GetAnnotationParameter action = GetAnnotationParameter.action( annotation, "message", String.class ); if (System.getSecurityManager() != null) { AccessController.doPrivileged( action ); } else { action.run(); } } catch ( Exception e ) { String msg = annotation.annotationType().getName() + " contains Constraint annotation, but does " + "not contain a message parameter."; throw new ConstraintDefinitionException( msg ); } } public List>> getConstraintValidatorDefinition(Class annotationClass) { if ( annotationClass == null ) { throw new IllegalArgumentException( "Class cannot be null" ); } final List>> list = constraintValidatorDefinitons.get( annotationClass ); List>> constraintsValidators = new ArrayList>>( list.size() ); for ( Class> validatorClass : list ) { //safe cause all CV for a given annotation A are CV @SuppressWarnings("unchecked") Class> safeValdiatorClass = ( Class> ) validatorClass; constraintsValidators.add( safeValdiatorClass ); } return constraintsValidators; } public
void addConstraintValidatorDefinition(Class annotationClass, List>> definitionClasses) { constraintValidatorDefinitons.putIfAbsent( annotationClass, definitionClasses ); } public boolean containsConstraintValidatorDefinition(Class annotationClass) { return constraintValidatorDefinitons.containsKey( annotationClass ); } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/PropertyDescriptorImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000306111263050721033402 0ustar twernertwerner// $Id: PropertyDescriptorImpl.java 17638 2009-10-07 08:31:13Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import javax.validation.metadata.PropertyDescriptor; /** * Describe a validated element (class, field or property). * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class PropertyDescriptorImpl extends ElementDescriptorImpl implements PropertyDescriptor { private final boolean cascaded; private final String property; public PropertyDescriptorImpl(Class returnType, boolean cascaded, String property, BeanMetaData beanMetaData) { super( returnType, beanMetaData ); this.cascaded = cascaded; this.property = property; } public boolean isCascaded() { return cascaded; } public String getPropertyName() { return property; } } ././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000204411262172500033401 0ustar twernertwerner Implementations of the Bean Validation metadata interfaces as well as Hibernate Validator specific meta data classes. ././@LongLink0000000000000000000000000000017200000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaData.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000620611262172500033405 0ustar twernertwerner// $Id: BeanMetaData.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.Annotation; import java.lang.reflect.Member; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.metadata.BeanDescriptor; import javax.validation.metadata.PropertyDescriptor; /** * Interface defining the meta data about the constraints defined in a given bean. * * @author Hardy Ferentschik */ public interface BeanMetaData { /** * @return the class of the bean. */ Class getBeanClass(); /** * @return an instance of {@code ElementDescriptor} describing the bean this meta data applies for. */ BeanDescriptor getBeanDescriptor(); /** * @return A list of all cascaded methods and fields (methods/fields annotated with @Valid). */ List getCascadedMembers(); /** * @return A map mapping defined group sequences to a list of groups. */ List> getDefaultGroupSequence(); /** * @return {@code true} if the entity redefines the default group sequence, {@code false} otherwise. */ boolean defaultGroupSequenceIsRedefined(); /** * @return A map of {@code MetaConstraint} instances encapsulating the information of all the constraints * defined on the bean mapped to the class in which the constraints is defined. */ Map, List>> getMetaConstraintsAsMap(); /** * @return A list of {@code MetaConstraint} instances encapsulating the information of all the constraints * defined on the bean. */ List> getMetaConstraintsAsList(); /** * Return {@code PropertyDescriptor} for the given property. * * @param property the property for which to retrieve the descriptor. * * @return Returns the {@code PropertyDescriptor} for the given property or {@code null} in case the * property does not have a descriptor. */ PropertyDescriptor getPropertyDescriptor(String property); /** * return true if the property exists on the object * even if the property does not host any constraint nor is cascaded */ boolean isPropertyPresent(String name); /** * @return the property descriptors having at least one constraint defined or which are marked * as cascaded (@Valid). */ Set getConstrainedProperties(); } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanMetaDataCache.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000336211262172500033405 0ustar twernertwerner// $Id: BeanMetaDataCache.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Cache for created instances of BeanMetaData. * * @author Hardy Ferentschik */ public class BeanMetaDataCache { /** * A map for the meta data for each entity. The key is the class and the value the bean meta data for this * entity. */ private Map, BeanMetaDataImpl> metadataProviders = new ConcurrentHashMap, BeanMetaDataImpl>( 10 ); @SuppressWarnings("unchecked") public BeanMetaDataImpl getBeanMetaData(Class beanClass) { if ( beanClass == null ) { throw new IllegalArgumentException( "Class cannot be null" ); } return ( BeanMetaDataImpl ) metadataProviders.get( beanClass ); } public void addBeanMetaData(Class beanClass, BeanMetaDataImpl metaData) { metadataProviders.put( beanClass, metaData ); } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ElementDescriptorImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000001241411263050721033404 0ustar twernertwerner// $Id: ElementDescriptorImpl.java 17638 2009-10-07 08:31:13Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.ElementType; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.validation.groups.Default; import javax.validation.metadata.ConstraintDescriptor; import javax.validation.metadata.ElementDescriptor; import javax.validation.metadata.Scope; import org.hibernate.validator.engine.groups.Group; import org.hibernate.validator.engine.groups.GroupChain; import org.hibernate.validator.engine.groups.GroupChainGenerator; /** * Describe a validated element (class, field or property). * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ElementDescriptorImpl implements ElementDescriptor { protected final BeanMetaData metaDataBean; private final Class type; private final Set> constraintDescriptors = new HashSet>(); public ElementDescriptorImpl(Class type, BeanMetaData metaDataBean) { this.metaDataBean = metaDataBean; this.type = type; } public void addConstraintDescriptor(ConstraintDescriptorImpl constraintDescriptor) { constraintDescriptors.add( constraintDescriptor ); } public boolean hasConstraints() { return constraintDescriptors.size() != 0; } public Class getElementClass() { return type; } public Set> getConstraintDescriptors() { return findConstraints().getConstraintDescriptors(); } public ConstraintFinder findConstraints() { return new ConstraintFinderImpl(); } private class ConstraintFinderImpl implements ConstraintFinder { private List> groups; private Set definedInSet; private Set elementTypes; ConstraintFinderImpl() { elementTypes = new HashSet(); elementTypes.add( ElementType.TYPE ); elementTypes.add( ElementType.METHOD ); elementTypes.add( ElementType.FIELD ); definedInSet = new HashSet(); definedInSet.add( ConstraintOrigin.DEFINED_LOCALLY ); definedInSet.add( ConstraintOrigin.DEFINED_IN_HIERARCHY ); groups = Collections.emptyList(); } public ConstraintFinder unorderedAndMatchingGroups(Class... classes) { this.groups = new ArrayList>(); for ( Class clazz : classes ) { if ( Default.class.equals( clazz ) && metaDataBean.defaultGroupSequenceIsRedefined() ) { this.groups.addAll( metaDataBean.getDefaultGroupSequence() ); } else { groups.add( clazz ); } } return this; } public ConstraintFinder lookingAt(Scope visibility) { if ( visibility.equals( Scope.LOCAL_ELEMENT ) ) { definedInSet.remove( ConstraintOrigin.DEFINED_IN_HIERARCHY ); } return this; } public ConstraintFinder declaredOn(ElementType... elementTypes) { this.elementTypes.clear(); this.elementTypes.addAll( Arrays.asList( elementTypes ) ); return this; } public Set> getConstraintDescriptors() { Set> matchingDescriptors = new HashSet>(); findMatchingDescriptors( matchingDescriptors ); return Collections.unmodifiableSet( matchingDescriptors ); } private void findMatchingDescriptors(Set> matchingDescriptors) { if ( !groups.isEmpty() ) { GroupChain groupChain = new GroupChainGenerator().getGroupChainFor( groups ); Iterator groupIterator = groupChain.getGroupIterator(); while ( groupIterator.hasNext() ) { Group g = groupIterator.next(); addMatchingDescriptorsForGroup( g.getGroup(), matchingDescriptors ); } } else { for ( ConstraintDescriptorImpl descriptor : constraintDescriptors ) { if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getElementType() ) ) { matchingDescriptors.add( descriptor ); } } } } public boolean hasConstraints() { return getConstraintDescriptors().size() != 0; } private void addMatchingDescriptorsForGroup(Class group, Set> matchingDescriptors) { for ( ConstraintDescriptorImpl descriptor : constraintDescriptors ) { if ( definedInSet.contains( descriptor.getDefinedOn() ) && elementTypes.contains( descriptor.getElementType() ) && descriptor.getGroups().contains( group ) ) { matchingDescriptors.add( descriptor ); } } } } } ././@LongLink0000000000000000000000000000017600000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintOrigin.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000227211262172500033404 0ustar twernertwerner// $Id: ConstraintOrigin.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; /** * Visibility looked at when discovering constraints. * * @author Hardy Ferentschik */ public enum ConstraintOrigin { /** * Constraint is defined on the root class */ DEFINED_LOCALLY, /** * Constraint is defined in a super-class or interface of the root class. */ DEFINED_IN_HIERARCHY } ././@LongLink0000000000000000000000000000017700000000000011572 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/AnnotationIgnores.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000001035211262172500033402 0ustar twernertwerner// $Id: AnnotationIgnores.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.hibernate.validator.util.LoggerFactory; /** * This class instantiated during the parsing of the XML configuration data and keeps * track of the annotations which should be ignored. * * @author Hardy Ferentschik */ public class AnnotationIgnores { private static final Logger log = LoggerFactory.make(); /** * Keeps track whether the 'ignore-annotations' flag is set on bean level in the xml configuration. If 'ignore-annotations' * is not specified true is the default. */ private final Map, Boolean> ignoreAnnotationDefaults = new HashMap, Boolean>(); /** * Keeps track of explicitly excluded members (fields and properties) for a given class. If a member appears in * the list mapped to a given class 'ignore-annotations' was explicitly set to true in the configuration * for this class. */ private final Map, List> ignoreAnnotationOnMember = new HashMap, List>(); private final Map, Boolean> ignoreAnnotationOnClass = new HashMap, Boolean>(); public void setDefaultIgnoreAnnotation(Class clazz, Boolean b) { if ( b == null ) { ignoreAnnotationDefaults.put( clazz, Boolean.TRUE ); } else { ignoreAnnotationDefaults.put( clazz, b ); } } public boolean getDefaultIgnoreAnnotation(Class clazz) { return ignoreAnnotationDefaults.containsKey( clazz ) && ignoreAnnotationDefaults.get( clazz ); } public void setIgnoreAnnotationsOnMember(Member member) { Class beanClass = member.getDeclaringClass(); if ( ignoreAnnotationOnMember.get( beanClass ) == null ) { List tmpList = new ArrayList(); tmpList.add( member ); ignoreAnnotationOnMember.put( beanClass, tmpList ); } else { ignoreAnnotationOnMember.get( beanClass ).add( member ); } } public boolean isIgnoreAnnotations(Member member) { boolean ignoreAnnotation; Class clazz = member.getDeclaringClass(); List ignoreAnnotationForMembers = ignoreAnnotationOnMember.get( clazz ); if ( ignoreAnnotationForMembers == null || !ignoreAnnotationForMembers.contains( member ) ) { ignoreAnnotation = getDefaultIgnoreAnnotation( clazz ); } else { ignoreAnnotation = ignoreAnnotationForMembers.contains( member ); } if ( ignoreAnnotation ) { logMessage( member, clazz ); } return ignoreAnnotation; } private void logMessage(Member member, Class clazz) { String type; if ( member instanceof Field ) { type = "Field"; } else { type = "Property"; } log.debug( type + " level annotations are getting ignored for " + clazz.getName() + "." + member.getName() ); } public void setIgnoreAnnotationsOnClass(Class clazz, boolean b) { ignoreAnnotationOnClass.put( clazz, b ); } public boolean isIgnoreAnnotations(Class clazz) { boolean ignoreAnnotation; if ( ignoreAnnotationOnClass.containsKey( clazz ) ) { ignoreAnnotation = ignoreAnnotationOnClass.get( clazz ); } else { ignoreAnnotation = getDefaultIgnoreAnnotation( clazz ); } if ( log.isDebugEnabled() && ignoreAnnotation ) { log.debug( "Class level annotation are getting ignored for " + clazz.getName() ); } return ignoreAnnotation; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/ConstraintDescriptorImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000004431611262172500033411 0ustar twernertwerner// $Id: ConstraintDescriptorImpl.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.Constraint; import javax.validation.ConstraintDefinitionException; import javax.validation.ConstraintValidator; import javax.validation.OverridesAttribute; import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; import javax.validation.ValidationException; import javax.validation.groups.Default; import javax.validation.metadata.ConstraintDescriptor; import org.slf4j.Logger; import org.hibernate.validator.util.GetAnnotationParameter; import org.hibernate.validator.util.GetDeclaredMethods; import org.hibernate.validator.util.GetMethod; import org.hibernate.validator.util.GetMethods; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * Describe a single constraint (including it's composing constraints). * * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class ConstraintDescriptorImpl implements ConstraintDescriptor, Serializable { private static final long serialVersionUID = -2563102960314069246L; private static final Logger log = LoggerFactory.make(); private static final int OVERRIDES_PARAMETER_DEFAULT_INDEX = -1; private static final String GROUPS = "groups"; private static final String PAYLOAD = "payload"; /** * The actual constraint annotation. */ private final T annotation; /** * The set of classes implementing the validation for this constraint. See also * ConstraintValidator resolution algorithm. */ private final List>> constraintValidatorDefinitionClasses; /** * The groups for which to apply this constraint. */ private final Set> groups; /** * The constraint parameters as map. The key is the parameter name and the value the * parameter value as specified in the constraint. */ private final Map attributes; /** * The specified payload of the constraint. */ private final Set> payloads; /** * The composing constraints for this constraint. */ private final Set> composingConstraints; /** * Flag indicating if in case of a composing constraint a single error or multiple errors should be raised. */ private final boolean isReportAsSingleInvalidConstraint; /** * Describes on which level (TYPE, METHOD, FIELD) the constraint was * defined on. */ private final ElementType elementType; /** * The oririgin of the constraint. Defined on the actual root class or somehwere in the class hierarchy */ private final ConstraintOrigin definedOn; /** * Handle to the built-in constraint implementations. */ //TODO Can be made transient since it is only used during object construction. It would be better if we would not have to pass it at all private transient final ConstraintHelper constraintHelper; public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper, Class implicitGroup, ElementType type, ConstraintOrigin definedOn) { this.annotation = annotation; this.constraintHelper = constraintHelper; this.elementType = type; this.definedOn = definedOn; this.isReportAsSingleInvalidConstraint = annotation.annotationType().isAnnotationPresent( ReportAsSingleViolation.class ); // HV-181 - To avoid and thread visibility issues we are building the different data structures in tmp variables and // then assign them to the final variables this.attributes = buildAnnotationParameterMap( annotation ); this.groups = buildGroupSet( implicitGroup ); this.payloads = buildPayloadSet( annotation ); this.constraintValidatorDefinitionClasses = findConstraintValidatorClasses(); this.composingConstraints = parseComposingConstraints(); } public ConstraintDescriptorImpl(T annotation, ConstraintHelper constraintHelper, ElementType type, ConstraintOrigin definedOn) { this( annotation, constraintHelper, null, type, definedOn ); } private Set> buildPayloadSet(T annotation) { Set> payloadSet = new HashSet>(); Class[] payloadFromAnnotation; try { //TODO be extra safe and make sure this is an array of Payload GetAnnotationParameter action = GetAnnotationParameter.action( annotation, PAYLOAD, Class[].class ); if ( System.getSecurityManager() != null ) { payloadFromAnnotation = AccessController.doPrivileged( action ); } else { payloadFromAnnotation = action.run(); } } catch ( ValidationException e ) { //ignore people not defining payloads payloadFromAnnotation = null; } if ( payloadFromAnnotation != null ) { payloadSet.addAll( Arrays.asList( payloadFromAnnotation ) ); } return Collections.unmodifiableSet( payloadSet ); } private Set> buildGroupSet(Class implicitGroup) { Set> groupSet = new HashSet>(); final Class[] groupsFromAnnotation; GetAnnotationParameter action = GetAnnotationParameter.action( annotation, GROUPS, Class[].class ); if ( System.getSecurityManager() != null ) { groupsFromAnnotation = AccessController.doPrivileged( action ); } else { groupsFromAnnotation = action.run(); } if ( groupsFromAnnotation.length == 0 ) { groupSet.add( Default.class ); } else { groupSet.addAll( Arrays.asList( groupsFromAnnotation ) ); } // if the constraint is part of the Default group it is automatically part of the implicit group as well if ( implicitGroup != null && groupSet.contains( Default.class ) ) { groupSet.add( implicitGroup ); } return Collections.unmodifiableSet( groupSet ); } private List>> findConstraintValidatorClasses() { final Class annotationType = getAnnotationType(); final List>> constraintValidatorClasses = new ArrayList>>(); if ( constraintHelper.containsConstraintValidatorDefinition( annotationType ) ) { for ( Class> validator : constraintHelper .getConstraintValidatorDefinition( annotationType ) ) { constraintValidatorClasses.add( validator ); } return Collections.unmodifiableList( constraintValidatorClasses ); } List>> constraintDefinitionClasses = new ArrayList>>(); if ( constraintHelper.isBuiltinConstraint( annotation.annotationType() ) ) { constraintDefinitionClasses.addAll( constraintHelper.getBuiltInConstraints( annotationType ) ); } else { Class>[] validatedBy = annotationType .getAnnotation( Constraint.class ) .validatedBy(); constraintDefinitionClasses.addAll( Arrays.asList( validatedBy ) ); } constraintHelper.addConstraintValidatorDefinition( annotation.annotationType(), constraintDefinitionClasses ); for ( Class> validator : constraintDefinitionClasses ) { @SuppressWarnings("unchecked") Class> safeValidator = ( Class> ) validator; constraintValidatorClasses.add( safeValidator ); } return Collections.unmodifiableList( constraintValidatorClasses ); } @SuppressWarnings("unchecked") private Class getAnnotationType() { return ( Class ) annotation.annotationType(); } public T getAnnotation() { return annotation; } public Set> getGroups() { return groups; } public Set> getPayload() { return payloads; } public List>> getConstraintValidatorClasses() { return constraintValidatorDefinitionClasses; } public Map getAttributes() { return attributes; } public Set> getComposingConstraints() { return composingConstraints; } public boolean isReportAsSingleViolation() { return isReportAsSingleInvalidConstraint; } public ElementType getElementType() { return elementType; } public ConstraintOrigin getDefinedOn() { return definedOn; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "ConstraintDescriptorImpl" ); sb.append( "{annotation=" ).append( annotation.annotationType().getName() ); sb.append( ", payloads=" ).append( payloads ); sb.append( ", hasComposingConstraints=" ).append( composingConstraints.isEmpty() ); sb.append( ", isReportAsSingleInvalidConstraint=" ).append( isReportAsSingleInvalidConstraint ); sb.append( ", elementType=" ).append( elementType ); sb.append( ", definedOn=" ).append( definedOn ); sb.append( ", groups=" ).append( groups ); sb.append( ", attributes=" ).append( attributes ); sb.append( '}' ); return sb.toString(); } private Map buildAnnotationParameterMap(Annotation annotation) { GetDeclaredMethods action = GetDeclaredMethods.action( annotation.annotationType() ); final Method[] declaredMethods; if ( System.getSecurityManager() != null ) { declaredMethods = AccessController.doPrivileged( action ); } else { declaredMethods = action.run(); } Map parameters = new HashMap( declaredMethods.length ); for ( Method m : declaredMethods ) { try { parameters.put( m.getName(), m.invoke( annotation ) ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e ); } catch ( InvocationTargetException e ) { throw new ValidationException( "Unable to read annotation attributes: " + annotation.getClass(), e ); } } return Collections.unmodifiableMap( parameters ); } private Object getMethodValue(Annotation annotation, Method m) { Object value; try { value = m.invoke( annotation ); } // should never happen catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to retrieve annotation parameter value." ); } catch ( InvocationTargetException e ) { throw new ValidationException( "Unable to retrieve annotation parameter value." ); } return value; } private Map> parseOverrideParameters() { Map> overrideParameters = new HashMap>(); final Method[] methods; final GetMethods getMethods = GetMethods.action( annotation.annotationType() ); if ( System.getSecurityManager() != null ) { methods = AccessController.doPrivileged( getMethods ); } else { methods = getMethods.run(); } for ( Method m : methods ) { if ( m.getAnnotation( OverridesAttribute.class ) != null ) { addOverrideAttributes( overrideParameters, m, m.getAnnotation( OverridesAttribute.class ) ); } else if ( m.getAnnotation( OverridesAttribute.List.class ) != null ) { addOverrideAttributes( overrideParameters, m, m.getAnnotation( OverridesAttribute.List.class ).value() ); } } return overrideParameters; } private void addOverrideAttributes(Map> overrideParameters, Method m, OverridesAttribute... attributes) { Object value = getMethodValue( annotation, m ); for ( OverridesAttribute overridesAttribute : attributes ) { ensureAttributeIsOverridable( m, overridesAttribute ); ClassIndexWrapper wrapper = new ClassIndexWrapper( overridesAttribute.constraint(), overridesAttribute.constraintIndex() ); Map map = overrideParameters.get( wrapper ); if ( map == null ) { map = new HashMap(); overrideParameters.put( wrapper, map ); } map.put( overridesAttribute.name(), value ); } } private void ensureAttributeIsOverridable(Method m, OverridesAttribute overridesAttribute) { final GetMethod getMethod = GetMethod.action( overridesAttribute.constraint(), overridesAttribute.name() ); final Method method; if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( getMethod ); } else { method = getMethod.run(); } if ( method == null ) { throw new ConstraintDefinitionException( "Overridden constraint does not define an attribute with name " + overridesAttribute.name() ); } Class returnTypeOfOverriddenConstraint = method.getReturnType(); if ( !returnTypeOfOverriddenConstraint.equals( m.getReturnType() ) ) { String message = "The overriding type of a composite constraint must be identical to the overridden one. Expected " + returnTypeOfOverriddenConstraint .getName() + " found " + m.getReturnType(); throw new ConstraintDefinitionException( message ); } } private Set> parseComposingConstraints() { Set> composingConstraintsSet = new HashSet>(); Map> overrideParameters = parseOverrideParameters(); for ( Annotation declaredAnnotation : annotation.annotationType().getDeclaredAnnotations() ) { if ( constraintHelper.isConstraintAnnotation( declaredAnnotation ) || constraintHelper.isBuiltinConstraint( declaredAnnotation.annotationType() ) ) { ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor( declaredAnnotation, overrideParameters, OVERRIDES_PARAMETER_DEFAULT_INDEX ); composingConstraintsSet.add( descriptor ); log.debug( "Adding composing constraint: " + descriptor ); } else if ( constraintHelper.isMultiValueConstraint( declaredAnnotation ) ) { List multiValueConstraints = constraintHelper.getMultiValueConstraints( declaredAnnotation ); int index = 0; for ( Annotation constraintAnnotation : multiValueConstraints ) { ConstraintDescriptorImpl descriptor = createComposingConstraintDescriptor( constraintAnnotation, overrideParameters, index ); composingConstraintsSet.add( descriptor ); log.debug( "Adding composing constraint: " + descriptor ); index++; } } } return Collections.unmodifiableSet( composingConstraintsSet ); } private ConstraintDescriptorImpl createComposingConstraintDescriptor(U declaredAnnotation, Map> overrideParameters, int index) { //TODO don't quite understand this warning //TODO assuming U.getClass() returns Class @SuppressWarnings("unchecked") final Class annotationType = ( Class ) declaredAnnotation.annotationType(); return createComposingConstraintDescriptor( overrideParameters, index, declaredAnnotation, annotationType ); } private ConstraintDescriptorImpl createComposingConstraintDescriptor(Map> overrideParameters, int index, U constraintAnnotation, Class annotationType) { // use a annotation proxy AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor( annotationType, buildAnnotationParameterMap( constraintAnnotation ) ); // get the right override parameters Map overrides = overrideParameters.get( new ClassIndexWrapper( annotationType, index ) ); if ( overrides != null ) { for ( Map.Entry entry : overrides.entrySet() ) { annotationDescriptor.setValue( entry.getKey(), entry.getValue() ); } } // groups get inherited from the parent annotationDescriptor.setValue( GROUPS, groups.toArray( new Class[groups.size()] ) ); // HV-183 - payloads are propagated to composing constraints annotationDescriptor.setValue( PAYLOAD, payloads.toArray( new Class[payloads.size()] ) ); U annotationProxy = AnnotationFactory.create( annotationDescriptor ); return new ConstraintDescriptorImpl( annotationProxy, constraintHelper, elementType, definedOn ); } /** * A wrapper class to keep track for which composing constraints (class and index) a given attribute override applies to. */ private class ClassIndexWrapper { final Class clazz; final int index; ClassIndexWrapper(Class clazz, int index) { this.clazz = clazz; this.index = index; } @Override @SuppressWarnings("SimplifiableIfStatement") public boolean equals(Object o) { if ( this == o ) { return true; } if ( o == null || getClass() != o.getClass() ) { return false; } @SuppressWarnings("unchecked") // safe due to the check above ClassIndexWrapper that = ( ClassIndexWrapper ) o; if ( index != that.index ) { return false; } if ( clazz != null && !clazz.equals( that.clazz ) ) { return false; } if ( clazz == null && that.clazz != null ) { return false; } return true; } @Override public int hashCode() { int result = clazz != null ? clazz.hashCode() : 0; result = 31 * result + index; return result; } } } ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/MetaConstraint.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000001361311262172500033405 0ustar twernertwerner// $Id: MetaConstraint.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $// $Id: MetaConstraint.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.lang.annotation.Annotation; import java.lang.annotation.ElementType; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.ValidationException; import org.hibernate.validator.engine.ConstraintTree; import org.hibernate.validator.engine.GlobalExecutionContext; import org.hibernate.validator.engine.LocalExecutionContext; import org.hibernate.validator.util.ReflectionHelper; /** * Instances of this class abstract the constraint type (class, method or field constraint) and give access to * meta data about the constraint. This allows a unified handling of constraints in the validator implementation. * * @author Hardy Ferentschik */ public class MetaConstraint { /** * The member the constraint was defined on. */ private final Member member; /** * The JavaBeans name of the field/property the constraint was placed on. {@code null} if this is a * class level constraint. */ private final String propertyName; /** * The class of the bean hosting this constraint. */ private final Class beanClass; /** * The constraint tree created from the constraint annotation. */ private final ConstraintTree constraintTree; /** * @param beanClass The class in which the constraint is defined on * @param member The member on which the constraint is defined on, {@code null} if it is a class constraint} * @param constraintDescriptor The constraint descriptor for this constraint */ public MetaConstraint(Class beanClass, Member member, ConstraintDescriptorImpl constraintDescriptor) { this.member = member; if ( this.member != null ) { this.propertyName = ReflectionHelper.getPropertyName( member ); if ( member instanceof Method && propertyName == null ) { // can happen if member is a Method which does not follow the bean convention throw new ValidationException( "Annotated methods must follow the JavaBeans naming convention. " + member.getName() + "() does not." ); } } else { this.propertyName = null; } this.beanClass = beanClass; constraintTree = new ConstraintTree( constraintDescriptor ); } /** * @return Returns the list of groups this constraint is part of. This might include the default group even when * it is not explicitly specified, but part of the redefined default group list of the hosting bean. */ public Set> getGroupList() { return constraintTree.getDescriptor().getGroups(); } public ConstraintDescriptorImpl getDescriptor() { return constraintTree.getDescriptor(); } public Class getBeanClass() { return beanClass; } public Member getMember() { return member; } /** * @return The JavaBeans name of the field/property the constraint was placed on. {@code null} if this is a * class level constraint. */ public String getPropertyName() { return propertyName; } public ElementType getElementType() { return constraintTree.getDescriptor().getElementType(); } public boolean validateConstraint(GlobalExecutionContext executionContext, LocalExecutionContext localExecutionContext) { List> constraintViolations = new ArrayList>(); localExecutionContext.setElementType( getElementType() ); constraintTree.validateConstraints( typeOfAnnotatedElement(), executionContext, localExecutionContext, constraintViolations ); if ( constraintViolations.size() > 0 ) { executionContext.addConstraintFailures( constraintViolations ); return false; } return true; } /** * @param o the object from which to retrieve the value. * * @return Returns the value for this constraint from the specified object. Depending on the type either the value itself * is returned of method or field access is used to access the value. */ public Object getValue(Object o) { switch ( getElementType() ) { case TYPE: { return o; } default: { return ReflectionHelper.getValue( member, o ); } } } private Type typeOfAnnotatedElement() { Type t; switch ( getElementType() ) { case TYPE: { t = beanClass; break; } default: { t = ReflectionHelper.typeOf( member ); if ( t instanceof Class && ( ( Class ) t ).isPrimitive() ) { t = ReflectionHelper.boxedType( t ); } } } return t; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append( "MetaConstraint" ); sb.append( "{beanClass=" ).append( beanClass ); sb.append( ", member=" ).append( member ); sb.append( ", propertyName='" ).append( propertyName ).append( '\'' ); sb.append( '}' ); return sb.toString(); } } ././@LongLink0000000000000000000000000000020000000000000011555 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metadata/BeanDescriptorImpl.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/metad0000644000175000017500000000336211263050721033406 0ustar twernertwerner// $Id: BeanDescriptorImpl.java 17638 2009-10-07 08:31:13Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.metadata; import java.util.Set; import javax.validation.metadata.BeanDescriptor; import javax.validation.metadata.PropertyDescriptor; /** * @author Emmanuel Bernard * @author Hardy Ferentschik */ public class BeanDescriptorImpl extends ElementDescriptorImpl implements BeanDescriptor { public BeanDescriptorImpl(BeanMetaData beanMetaData) { super( beanMetaData.getBeanClass(), beanMetaData ); } public boolean isBeanConstrained() { return metaDataBean.getMetaConstraintsAsMap().size() > 0; } public PropertyDescriptor getConstraintsForProperty(String propertyName) { if ( propertyName == null ) { throw new IllegalArgumentException( "The property name cannot be null" ); } return metaDataBean.getPropertyDescriptor( propertyName ); } public Set getConstrainedProperties() { return metaDataBean.getConstrainedProperties(); } } ././@LongLink0000000000000000000000000000015400000000000011565 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000755000175000017500000000000011402110362033425 5ustar twernertwerner././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000176211262172500033443 0ustar twernertwerner This package contains the Hibernate Validator specific constraints. ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/Length.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000405111262172500033435 0ustar twernertwerner// $Id: Length.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import org.hibernate.validator.constraints.impl.LengthValidator; /** * Validate that the string is between min and max included. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ @Documented @Constraint(validatedBy = LengthValidator.class) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) public @interface Length { int min() default 0; int max() default Integer.MAX_VALUE; String message() default "{org.hibernate.validator.constraints.Length.message}"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/NotEmpty.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000370411262172500033441 0ustar twernertwerner// $Id: NotEmpty.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** * @author Emmanuel Bernard */ @Documented @Constraint(validatedBy = { }) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @ReportAsSingleViolation @NotNull @Size(min = 1) public @interface NotEmpty { String message() default "{org.hibernate.validator.constraints.NotEmpty.message}"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000755000175000017500000000000011402110361033424 5ustar twernertwerner././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfFloat.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000362511262172500033443 0ustar twernertwerner// $Id: SizeValidatorForArraysOfFloat.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfFloat extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(float[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/MinValidatorForNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000365311262172500033444 0ustar twernertwerner// $Id: MinValidatorForNumber.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Min; /** * Check that the number being validated is greater than or equal to the minimum * value specified. * * @author Alaa Nassef */ public class MinValidatorForNumber implements ConstraintValidator { private long minValue; public void initialize(Min minValue) { this.minValue = minValue.value(); } public boolean isValid(Number value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } if ( value instanceof BigDecimal ) { return ( ( BigDecimal ) value ).compareTo( BigDecimal.valueOf( minValue ) ) != -1; } else if ( value instanceof BigInteger ) { return ( ( BigInteger ) value ).compareTo( BigInteger.valueOf( minValue ) ) != -1; } else { double doubleValue = value.doubleValue(); return doubleValue >= minValue; } } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/NotNullValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000257411262172500033445 0ustar twernertwerner// $Id: NotNullValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.NotNull; /** * Validate that the object is not null. * * @author Emmanuel Bernard */ public class NotNullValidator implements ConstraintValidator { public void initialize(NotNull parameters) { } public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { return object != null; } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/FutureValidatorForCalendar.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000306011262172500033434 0ustar twernertwerner// $Id: FutureValidatorForCalendar.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Calendar; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Future; /** * Check that the java.util.Calendar passed to be validated is in * the future. * * @author Alaa Nassef */ public class FutureValidatorForCalendar implements ConstraintValidator { public void initialize(Future constraintAnnotation) { } public boolean isValid(Calendar cal, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( cal == null ) { return true; } return cal.after( Calendar.getInstance() ); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DecimalMinValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000346011262172500033440 0ustar twernertwerner// $Id: DecimalMinValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.DecimalMin; /** * @author Hardy Ferentschik */ public class DecimalMinValidatorForString implements ConstraintValidator { private BigDecimal minValue; public void initialize(DecimalMin minValue) { try { this.minValue = new BigDecimal( minValue.value() ); } catch ( NumberFormatException nfe ) { throw new IllegalArgumentException( minValue.value() + " does not represent a valid BigDecimal format" ); } } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } try { return new BigDecimal( value ).compareTo( minValue ) != -1; } catch ( NumberFormatException nfe ) { return false; } } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DigitsValidatorForNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000467111262172500033445 0ustar twernertwerner// $Id: DigitsValidatorForNumber.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Digits; /** * Validates that the Number being validates matches the pattern * defined in the constraint. * * @author Alaa Nassef * @author Hardy Ferentschik */ public class DigitsValidatorForNumber implements ConstraintValidator { private int maxIntegerLength; private int maxFractionLength; public void initialize(Digits constraintAnnotation) { this.maxIntegerLength = constraintAnnotation.integer(); this.maxFractionLength = constraintAnnotation.fraction(); validateParameters(); } public boolean isValid(Number num, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( num == null ) { return true; } BigDecimal bigNum; if ( num instanceof BigDecimal ) { bigNum = ( BigDecimal ) num; } else { bigNum = new BigDecimal( num.toString() ).stripTrailingZeros(); } int integerPartLength = bigNum.precision() - bigNum.scale(); int fractionPartLength = bigNum.scale() < 0 ? 0 : bigNum.scale(); return ( maxIntegerLength >= integerPartLength && maxFractionLength >= fractionPartLength ); } private void validateParameters() { if ( maxIntegerLength < 0 ) { throw new IllegalArgumentException( "The length of the integer part cannot be negative." ); } if ( maxFractionLength < 0 ) { throw new IllegalArgumentException( "The length of the fraction part cannot be negative." ); } } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DecimalMaxValidatorForNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000416411262172500033442 0ustar twernertwerner// $Id: DecimalMaxValidatorForNumber.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.DecimalMax; /** * Check that the number being validated is less than or equal to the maximum * value specified. * * @author Hardy Ferentschik */ public class DecimalMaxValidatorForNumber implements ConstraintValidator { private BigDecimal maxValue; public void initialize(DecimalMax maxValue) { try { this.maxValue = new BigDecimal( maxValue.value() ); } catch ( NumberFormatException nfe ) { throw new IllegalArgumentException( maxValue.value() + " does not represent a valid BigDecimal format" ); } } public boolean isValid(Number value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } if ( value instanceof BigDecimal ) { return ( ( BigDecimal ) value ).compareTo( maxValue ) != 1; } else if ( value instanceof BigInteger ) { return ( new BigDecimal( ( BigInteger ) value ) ).compareTo( maxValue ) != 1; } else { return ( new BigDecimal( value.doubleValue() ).compareTo( maxValue ) ) != 1; } } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DigitsValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000515611262172500033444 0ustar twernertwerner// $Id: DigitsValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.ValidationException; import javax.validation.constraints.Digits; /** * Validates that the String being validated consists of digits, * and matches the pattern defined in the constraint. * * @author Alaa Nassef * @author Hardy Ferentschik */ public class DigitsValidatorForString implements ConstraintValidator { private int maxIntegerLength; private int maxFractionLength; public void initialize(Digits constraintAnnotation) { this.maxIntegerLength = constraintAnnotation.integer(); this.maxFractionLength = constraintAnnotation.fraction(); validateParameters(); } public boolean isValid(String str, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( str == null ) { return true; } BigDecimal bigNum = getBigDecimalValue( str ); if ( bigNum == null ) { return false; } int integerPartLength = bigNum.precision() - bigNum.scale(); int fractionPartLength = bigNum.scale() < 0 ? 0 : bigNum.scale(); return ( maxIntegerLength >= integerPartLength && maxFractionLength >= fractionPartLength ); } private BigDecimal getBigDecimalValue(String str) { BigDecimal bd; try { bd = new BigDecimal( str ); } catch ( NumberFormatException nfe ) { return null; } return bd; } private void validateParameters() { if ( maxIntegerLength < 0 ) { throw new IllegalArgumentException( "The length of the integer part cannot be negative." ); } if ( maxFractionLength < 0 ) { throw new IllegalArgumentException( "The length of the fraction part cannot be negative." ); } } } ././@LongLink0000000000000000000000000000022500000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfBoolean.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000363511262172500033444 0ustar twernertwerner// $Id: SizeValidatorForArraysOfBoolean.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfBoolean extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(boolean[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000023000000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfPrimitives.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000317511262172500033443 0ustar twernertwerner// $Id: SizeValidatorForArraysOfPrimitives.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.constraints.Size; /** * Check that the length of an array is between min and max * * @author Hardy Ferentschik */ public abstract class SizeValidatorForArraysOfPrimitives { protected int min; protected int max; public void initialize(Size parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000017500000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000203511262172500033435 0ustar twernertwerner This package contains the implementations of the built-in as well as Hibernate Validator specific constraints. ././@LongLink0000000000000000000000000000022100000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfInt.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000361511262172500033442 0ustar twernertwerner// $Id: SizeValidatorForArraysOfInt.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfInt extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(int[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForMap.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000453111262172500033440 0ustar twernertwerner// $Id: SizeValidatorForMap.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Map; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * Check that a string's length is between min and max. * * @author Hardy Ferentschik */ public class SizeValidatorForMap implements ConstraintValidator { private int min; private int max; public void initialize(Size parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } /** * Checks the number of entries in a map. * * @param map The map to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the map is null or the number of entries in map * is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(Map map, ConstraintValidatorContext constraintValidatorContext) { if ( map == null ) { return true; } int size = map.size(); return size >= min && size <= max; } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000020400000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/EmailValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000245411262172500033442 0ustar twernertwerner//$Id: EmailValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ package org.hibernate.validator.constraints.impl; import java.util.regex.Matcher; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.hibernate.validator.constraints.Email; /** * Check that a given string is a well-formed email address. * * @author Emmanuel Bernard */ public class EmailValidator implements ConstraintValidator { //TODO: Implement this http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html regex in java private static String ATOM = "[^\\x00-\\x1F^\\(^\\)^\\<^\\>^\\@^\\,^\\;^\\:^\\\\^\\\"^\\.^\\[^\\]^\\s]"; private static String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)*"; private static String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]"; private java.util.regex.Pattern pattern = java.util.regex.Pattern.compile( "^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$", java.util.regex.Pattern.CASE_INSENSITIVE ); public void initialize(Email annotation) { } public boolean isValid(String value, ConstraintValidatorContext context) { if ( value == null || value.length() == 0 ) { return true; } Matcher m = pattern.matcher( value ); return m.matches(); } } ././@LongLink0000000000000000000000000000021100000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/AssertTrueValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000264611262172500033445 0ustar twernertwerner// $Id: AssertTrueValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.AssertTrue; /** * Validates that the value passed is true * * @author Alaa Nassef */ public class AssertTrueValidator implements ConstraintValidator { public void initialize(AssertTrue constraintAnnotation) { } public boolean isValid(Boolean bool, ConstraintValidatorContext constraintValidatorContext) { //null values are valid return bool == null || bool; } } ././@LongLink0000000000000000000000000000020300000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/NullValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000255611262172500033445 0ustar twernertwerner// $Id: NullValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Null; /** * Validate that the object is null * * @author Alaa Nassef */ public class NullValidator implements ConstraintValidator { public void initialize(Null constraintAnnotation) { } public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { return object == null; } } ././@LongLink0000000000000000000000000000021600000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/PastValidatorForCalendar.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000304511262172500033437 0ustar twernertwerner// $Id: PastValidatorForCalendar.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Calendar; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Past; /** * Check that the java.util.Calendar passed to be validated is in the * past. * * @author Alaa Nassef */ public class PastValidatorForCalendar implements ConstraintValidator { public void initialize(Past constraintAnnotation) { } public boolean isValid(Calendar cal, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( cal == null ) { return true; } return cal.before( Calendar.getInstance() ); } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfLong.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000362111262172500033437 0ustar twernertwerner// $Id: SizeValidatorForArraysOfLong.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfLong extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(long[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000455711262172500033450 0ustar twernertwerner// $Id: SizeValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * Check that a string's length is between min and max. * * @author Emmanuel Bernard * @author Gavin King * @author Hardy Ferentschik */ public class SizeValidatorForString implements ConstraintValidator { private int min; private int max; public void initialize(Size parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } /** * Checks the length of the specified string. * * @param s The string to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the string is null or the length of s between the specified * min and max values (inclusive), false otherwise. */ public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { if ( s == null ) { return true; } int length = s.length(); return length >= min && length <= max; } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/MinValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000336111262172500033440 0ustar twernertwerner// $Id: MinValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Min; /** * Check that the String being validated represents a number, and has a value * more than or equal to the minimum value specified. * * @author Alaa Nassef */ public class MinValidatorForString implements ConstraintValidator { private long minValue; public void initialize(Min minValue) { this.minValue = minValue.value(); } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } try { return new BigDecimal( ( String ) value ).compareTo( BigDecimal.valueOf( minValue ) ) != -1; } catch ( NumberFormatException nfe ) { return false; } } } ././@LongLink0000000000000000000000000000022300000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfShort.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000362511262172500033443 0ustar twernertwerner// $Id: SizeValidatorForArraysOfShort.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfShort extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(short[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfChar.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000362211262172500033440 0ustar twernertwerner// $Id: SizeValidatorForArraysOfChar.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfChar extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(char[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/PastValidatorForDate.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000300411262172500033432 0ustar twernertwerner// $Id: PastValidatorForDate.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Date; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Past; /** * Check that the java.util.Date passed to be validated is in the * past. * * @author Alaa Nassef */ public class PastValidatorForDate implements ConstraintValidator { public void initialize(Past constraintAnnotation) { } public boolean isValid(Date date, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( date == null ) { return true; } return date.before( new Date() ); } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArray.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000464611262172500033447 0ustar twernertwerner// $Id: SizeValidatorForArray.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * Check that the length of an array is between min and max * * @author Hardy Ferentschik */ public class SizeValidatorForArray implements ConstraintValidator { private int min; private int max; public void initialize(Size parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(Object[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/MaxValidatorForNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000364511262172500033445 0ustar twernertwerner// $Id: MaxValidatorForNumber.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Max; /** * Check that the number being validated is less than or equal to the maximum * value specified. * * @author Alaa Nassef */ public class MaxValidatorForNumber implements ConstraintValidator { private long maxValue; public void initialize(Max maxValue) { this.maxValue = maxValue.value(); } public boolean isValid(Number value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } if ( value instanceof BigDecimal ) { return ( ( BigDecimal ) value ).compareTo( BigDecimal.valueOf( maxValue ) ) != 1; } else if ( value instanceof BigInteger ) { return ( ( BigInteger ) value ).compareTo( BigInteger.valueOf( maxValue ) ) != 1; } else { double doubleValue = value.doubleValue(); return doubleValue <= maxValue; } } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfByte.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000362211262172500033440 0ustar twernertwerner// $Id: SizeValidatorForArraysOfByte.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfByte extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(byte[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DecimalMinValidatorForNumber.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000416711262172500033445 0ustar twernertwerner// $Id: DecimalMinValidatorForNumber.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import java.math.BigInteger; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.DecimalMin; /** * Check that the number being validated is less than or equal to the maximum * value specified. * * @author Hardy Ferentschik */ public class DecimalMinValidatorForNumber implements ConstraintValidator { private BigDecimal minValue; public void initialize(DecimalMin minValue) { try { this.minValue = new BigDecimal( minValue.value() ); } catch ( NumberFormatException nfe ) { throw new IllegalArgumentException( minValue.value() + " does not represent a valid BigDecimal format" ); } } public boolean isValid(Number value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } if ( value instanceof BigDecimal ) { return ( ( BigDecimal ) value ).compareTo( minValue ) != -1; } else if ( value instanceof BigInteger ) { return ( new BigDecimal( ( BigInteger ) value ) ).compareTo( minValue ) != -1; } else { return ( new BigDecimal( value.doubleValue() ).compareTo( minValue ) ) != -1; } } } ././@LongLink0000000000000000000000000000022200000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/DecimalMaxValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000366011262172500033442 0ustar twernertwerner// $Id: DecimalMaxValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.DecimalMax; /** * Check that the String being validated represents a number, and has a value * less than or equal to the maximum value specified. * * @author Alaa Nassef */ public class DecimalMaxValidatorForString implements ConstraintValidator { private BigDecimal maxValue; public void initialize(DecimalMax maxValue) { try { this.maxValue = new BigDecimal( maxValue.value() ); } catch ( NumberFormatException nfe ) { throw new IllegalArgumentException( maxValue.value() + " does not represent a valid BigDecimal format" ); } } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } try { return new BigDecimal( value ).compareTo( maxValue ) != 1; } catch ( NumberFormatException nfe ) { return false; } } } ././@LongLink0000000000000000000000000000021200000000000011560 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/AssertFalseValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000265511262172500033445 0ustar twernertwerner// $Id: AssertFalseValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.AssertFalse; /** * Validates that the value passed is false * * @author Alaa Nassef */ public class AssertFalseValidator implements ConstraintValidator { public void initialize(AssertFalse constraintAnnotation) { } public boolean isValid(Boolean bool, ConstraintValidatorContext constraintValidatorContext) { //null values are valid return bool == null || !bool; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/PatternValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000365311262172500033444 0ustar twernertwerner// $Id: PatternValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.regex.Matcher; import java.util.regex.PatternSyntaxException; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Pattern; /** * @author Hardy Ferentschik */ public class PatternValidator implements ConstraintValidator { private java.util.regex.Pattern pattern; public void initialize(Pattern parameters) { Pattern.Flag flags[] = parameters.flags(); int intFlag = 0; for ( Pattern.Flag flag : flags ) { intFlag = intFlag | flag.getValue(); } try { pattern = java.util.regex.Pattern.compile( parameters.regexp(), intFlag ); } catch ( PatternSyntaxException e ) { throw new IllegalArgumentException( "Invalid regular expression.", e ); } } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { if ( value == null ) { return true; } Matcher m = pattern.matcher( value ); return m.matches(); } } ././@LongLink0000000000000000000000000000022400000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForArraysOfDouble.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000363111262172500033440 0ustar twernertwerner// $Id: SizeValidatorForArraysOfDouble.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.lang.reflect.Array; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * @author Hardy Ferentschik */ public class SizeValidatorForArraysOfDouble extends SizeValidatorForArraysOfPrimitives implements ConstraintValidator { /** * Checks the number of entries in an array. * * @param array The array to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the array is null or the number of entries in * array is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(double[] array, ConstraintValidatorContext constraintValidatorContext) { if ( array == null ) { return true; } int length = Array.getLength( array ); return length >= min && length <= max; } } ././@LongLink0000000000000000000000000000021400000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/FutureValidatorForDate.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000301711262172500033436 0ustar twernertwerner// $Id: FutureValidatorForDate.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Date; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Future; /** * Check that the java.util.Date passed to be validated is in the * future. * * @author Alaa Nassef */ public class FutureValidatorForDate implements ConstraintValidator { public void initialize(Future constraintAnnotation) { } public boolean isValid(Date date, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( date == null ) { return true; } return date.after( new Date() ); } } ././@LongLink0000000000000000000000000000020500000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/LengthValidator.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000370111262172500033436 0ustar twernertwerner// $Id: LengthValidator.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.hibernate.validator.constraints.Length; /** * Check that a string's length is between min and max. * * @author Emmanuel Bernard * @author Gavin King */ public class LengthValidator implements ConstraintValidator { private int min; private int max; public void initialize(Length parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { if ( value == null ) { return true; } int length = value.length(); return length >= min && length <= max; } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000021300000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/MaxValidatorForString.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000334511262172500033442 0ustar twernertwerner// $Id: MaxValidatorForString.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.math.BigDecimal; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Max; /** * Check that the String being validated represents a number, and has a value * less than or equal to the maximum value specified. * * @author Alaa Nassef */ public class MaxValidatorForString implements ConstraintValidator { private long maxValue; public void initialize(Max maxValue) { this.maxValue = maxValue.value(); } public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { //null values are valid if ( value == null ) { return true; } try { return new BigDecimal( value ).compareTo( BigDecimal.valueOf( maxValue ) ) != 1; } catch ( NumberFormatException nfe ) { return false; } } } ././@LongLink0000000000000000000000000000022000000000000011557 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/impl/SizeValidatorForCollection.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000466311262172500033446 0ustar twernertwerner// $Id: SizeValidatorForCollection.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints.impl; import java.util.Collection; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import javax.validation.constraints.Size; /** * Check that a string's length is between min and max. * * @author Hardy Ferentschik */ public class SizeValidatorForCollection implements ConstraintValidator { private int min; private int max; public void initialize(Size parameters) { min = parameters.min(); max = parameters.max(); validateParameters(); } /** * Checks the number of entries in a map. * * @param collection The collection to validate. * @param constraintValidatorContext context in which the constraint is evaluated. * * @return Returns true if the collection is null or the number of entries in * collection is between the specified min and max values (inclusive), * false otherwise. */ public boolean isValid(Collection collection, ConstraintValidatorContext constraintValidatorContext) { if ( collection == null ) { return true; } int length = collection.size(); return length >= min && length <= max; } private void validateParameters() { if ( min < 0 ) { throw new IllegalArgumentException( "The min parameter cannot be negative." ); } if ( max < 0 ) { throw new IllegalArgumentException( "The max parameter cannot be negative." ); } if ( max < min ) { throw new IllegalArgumentException( "The length cannot be negative." ); } } } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/Range.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000445011262172500033440 0ustar twernertwerner//$Id: Range.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.OverridesAttribute; import javax.validation.Payload; import javax.validation.ReportAsSingleViolation; import javax.validation.constraints.Max; import javax.validation.constraints.Min; /** * The annotated element has to be in the appropriate range. Apply on numeric values or string * representation of the numeric value. * * @author Hardy Ferentschik */ @Documented @Constraint(validatedBy = { }) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) @Min(0) @Max(Long.MAX_VALUE) @ReportAsSingleViolation public @interface Range { @OverridesAttribute(constraint = Min.class, name = "value") long min() default 0; @OverridesAttribute(constraint = Max.class, name = "value") long max() default Long.MAX_VALUE; String message() default "{org.hibernate.validator.constraints.Range.message}"; Class[] groups() default { }; Class[] payload() default { }; } ././@LongLink0000000000000000000000000000016600000000000011570 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/constraints/Email.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/const0000644000175000017500000000365011262172500033441 0ustar twernertwerner//$Id: Email.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.constraints; import java.lang.annotation.Documented; import static java.lang.annotation.ElementType.ANNOTATION_TYPE; import static java.lang.annotation.ElementType.CONSTRUCTOR; import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import java.lang.annotation.Retention; import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.Payload; import org.hibernate.validator.constraints.impl.EmailValidator; /** * The string has to be a well-formed email address. * * @author Emmanuel Bernard * @author Hardy Ferentschik */ @Documented @Constraint(validatedBy = EmailValidator.class) @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) @Retention(RUNTIME) public @interface Email { String message() default "{org.hibernate.validator.constraints.Email.message}"; Class[] groups() default { }; Class[] payload() default { }; } libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/0000755000175000017500000000000011402110355033160 5ustar twernertwerner././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/package.htmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/p0000644000175000017500000000175511262172500033356 0ustar twernertwerner Classes used to parse Bean Validation XML configuration files. ././@LongLink0000000000000000000000000000017400000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationXmlParser.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/V0000644000175000017500000002541711262172500033325 0ustar twernertwerner// $Id: ValidationXmlParser.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; import java.io.InputStream; import java.net.URL; import java.security.AccessController; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.ValidationException; import javax.validation.spi.ValidationProvider; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.slf4j.Logger; import org.xml.sax.SAXException; import org.hibernate.validator.util.GetClassLoader; import org.hibernate.validator.util.LoadClass; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.NewInstance; /** * Parser for validation.xml using JAXB. * * @author Hardy Ferentschik */ public class ValidationXmlParser { private static final Logger log = LoggerFactory.make(); private static final String VALIDATION_XML_FILE = "META-INF/validation.xml"; private static final String VALIDATION_CONFIGURATION_XSD = "META-INF/validation-configuration-1.0.xsd"; /** * Tries to check whether a validation.xml file exists and parses it using JAXB. * * @return The parameters parsed out of validation.xml wrapped in an instance of ConfigurationImpl.ValidationBootstrapParameters. */ public ValidationBootstrapParameters parseValidationXml() { ValidationConfigType config = getValidationConfig(); ValidationBootstrapParameters xmlParameters = new ValidationBootstrapParameters(); if ( config != null ) { // collect the parameters from the xml file setProviderClassFromXml( config, xmlParameters ); setMessageInterpolatorFromXml( config, xmlParameters ); setTraversableResolverFromXml( config, xmlParameters ); setConstraintFactoryFromXml( config, xmlParameters ); setMappingStreamsFromXml( config, xmlParameters ); setPropertiesFromXml( config, xmlParameters ); } return xmlParameters; } private void setConstraintFactoryFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) { String constraintFactoryClass = config.getConstraintValidatorFactory(); if ( constraintFactoryClass != null ) { try { @SuppressWarnings("unchecked") Class clazz = ( Class ) loadClass( constraintFactoryClass, this.getClass() ); NewInstance newInstance = NewInstance.action( clazz, "constraint factory class" ); if ( System.getSecurityManager() != null ) { xmlParameters.constraintValidatorFactory = AccessController.doPrivileged( newInstance ); } else { xmlParameters.constraintValidatorFactory = newInstance.run(); } log.info( "Using {} as constraint factory.", constraintFactoryClass ); } catch ( ValidationException e ) { throw new ValidationException( "Unable to instantiate constraint factory class " + constraintFactoryClass + ".", e ); } } } private Class loadClass(String className, Class caller) { LoadClass action = LoadClass.action( className, caller ); if ( System.getSecurityManager() != null ) { return AccessController.doPrivileged( action ); } else { return action.run(); } } private void setPropertiesFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) { for ( PropertyType property : config.getProperty() ) { if ( log.isDebugEnabled() ) { log.debug( "Found property '{}' with value '{}' in validation.xml.", property.getName(), property.getValue() ); } xmlParameters.configProperties.put( property.getName(), property.getValue() ); } } private void setMappingStreamsFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) { for ( JAXBElement mappingFileName : config.getConstraintMapping() ) { if ( log.isDebugEnabled() ) { log.debug( "Trying to open input stream for {}.", mappingFileName.getValue() ); } InputStream in = getInputStreamForPath( mappingFileName.getValue() ); if ( in == null ) { throw new ValidationException( "Unable to open input stream for mapping file " + mappingFileName.getValue() + "." ); } xmlParameters.mappings.add( in ); } } private void setMessageInterpolatorFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) { String messageInterpolatorClass = config.getMessageInterpolator(); if ( messageInterpolatorClass != null ) { try { @SuppressWarnings("unchecked") Class clazz = ( Class ) loadClass( messageInterpolatorClass, this.getClass() ); xmlParameters.messageInterpolator = clazz.newInstance(); log.info( "Using {} as message interpolator.", messageInterpolatorClass ); } catch ( ValidationException e ) { throw new ValidationException( "Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e ); } catch ( InstantiationException e ) { throw new ValidationException( "Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to instantiate message interpolator class " + messageInterpolatorClass + ".", e ); } } } private void setTraversableResolverFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParameters) { String traversableResolverClass = config.getTraversableResolver(); if ( traversableResolverClass != null ) { try { @SuppressWarnings("unchecked") Class clazz = ( Class ) loadClass( traversableResolverClass, this.getClass() ); xmlParameters.traversableResolver = clazz.newInstance(); log.info( "Using {} as traversable resolver.", traversableResolverClass ); } catch ( ValidationException e ) { throw new ValidationException( "Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e ); } catch ( InstantiationException e ) { throw new ValidationException( "Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e ); } catch ( IllegalAccessException e ) { throw new ValidationException( "Unable to instantiate traversable resolver class " + traversableResolverClass + ".", e ); } } } @SuppressWarnings("unchecked") private void setProviderClassFromXml(ValidationConfigType config, ValidationBootstrapParameters xmlParamters) { String providerClassName = config.getDefaultProvider(); if ( providerClassName != null ) { try { xmlParamters.providerClass = ( Class> ) loadClass( providerClassName, this.getClass() ); log.info( "Using {} as validation provider.", providerClassName ); } catch ( Exception e ) { throw new ValidationException( "Unable to instantiate validation provider class " + providerClassName + "." ); } } } private ValidationConfigType getValidationConfig() { InputStream inputStream = getInputStreamForPath( VALIDATION_XML_FILE ); if ( inputStream == null ) { log.debug( "No {} found. Using annotation based configuration only", VALIDATION_XML_FILE ); return null; } log.info( "{} found.", VALIDATION_XML_FILE ); ValidationConfigType validationConfig; Schema schema = getValidationConfigurationSchema(); try { JAXBContext jc = JAXBContext.newInstance( ValidationConfigType.class ); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema( schema ); StreamSource stream = new StreamSource( inputStream ); JAXBElement root = unmarshaller.unmarshal( stream, ValidationConfigType.class ); validationConfig = root.getValue(); } catch ( JAXBException e ) { log.error( "Error parsing validation.xml: {}", e.getMessage() ); throw new ValidationException( "Unable to parse " + VALIDATION_XML_FILE ); } return validationConfig; } private InputStream getInputStreamForPath(String path) { //TODO not sure it's the right thing to do (ie removing '/' //remove heading '/' if ( path.startsWith( "/" ) ) { path = path.substring( 1 ); } boolean isSecured = System.getSecurityManager() != null; boolean isContextCL = true; // try the context class loader first GetClassLoader action = GetClassLoader.fromContext(); ClassLoader loader = isSecured ? AccessController.doPrivileged( action ) : action.run(); if ( loader == null ) { log.debug( "No default context class loader, fall back to Bean Validation's loader" ); action = GetClassLoader.fromClass( ValidationXmlParser.class ); loader = isSecured ? AccessController.doPrivileged( action ) : action.run(); isContextCL = false; } InputStream inputStream = loader.getResourceAsStream( path ); // try the current class loader if ( isContextCL && inputStream == null ) { action = GetClassLoader.fromClass( ValidationXmlParser.class ); loader = isSecured ? AccessController.doPrivileged( action ) : action.run(); inputStream = loader.getResourceAsStream( path ); } return inputStream; } private Schema getValidationConfigurationSchema() { boolean isSecured = System.getSecurityManager() != null; GetClassLoader action = GetClassLoader.fromClass( ValidationXmlParser.class ); ClassLoader loader = isSecured ? AccessController.doPrivileged( action ) : action.run(); URL schemaUrl = loader.getResource( VALIDATION_CONFIGURATION_XSD ); SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ); Schema schema = null; try { schema = sf.newSchema( schemaUrl ); } catch ( SAXException e ) { log.warn( "Unable to create schema for {}: {}", VALIDATION_CONFIGURATION_XSD, e.getMessage() ); } return schema; } } ././@LongLink0000000000000000000000000000017100000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/XmlMappingParser.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/X0000644000175000017500000006232611262172500033327 0ustar twernertwerner// $Id: XmlMappingParser.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; import java.io.InputStream; import java.io.Serializable; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.net.URL; import java.security.AccessController; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import javax.validation.Constraint; import javax.validation.ConstraintValidator; import javax.validation.Payload; import javax.validation.ValidationException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.transform.stream.StreamSource; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.slf4j.Logger; import org.xml.sax.SAXException; import org.hibernate.validator.metadata.AnnotationIgnores; import org.hibernate.validator.metadata.ConstraintDescriptorImpl; import org.hibernate.validator.metadata.ConstraintHelper; import org.hibernate.validator.metadata.ConstraintOrigin; import org.hibernate.validator.metadata.MetaConstraint; import org.hibernate.validator.util.ContainsField; import org.hibernate.validator.util.ContainsMethod; import org.hibernate.validator.util.GetClassLoader; import org.hibernate.validator.util.GetDeclaredField; import org.hibernate.validator.util.GetMethod; import org.hibernate.validator.util.GetMethodFromPropertyName; import org.hibernate.validator.util.LoadClass; import org.hibernate.validator.util.LoggerFactory; import org.hibernate.validator.util.annotationfactory.AnnotationDescriptor; import org.hibernate.validator.util.annotationfactory.AnnotationFactory; /** * @author Hardy Ferentschik */ public class XmlMappingParser { private static final Logger log = LoggerFactory.make(); private static final String VALIDATION_MAPPING_XSD = "META-INF/validation-mapping-1.0.xsd"; private static final String MESSAGE_PARAM = "message"; private static final String GROUPS_PARAM = "groups"; private static final String PAYLOAD_PARAM = "payload"; private static final String PACKAGE_SEPARATOR = "."; private final Set> processedClasses = new HashSet>(); private final ConstraintHelper constraintHelper; private final AnnotationIgnores annotationIgnores; private final Map, List>> constraintMap; private final Map, List> cascadedMembers; private final Map, List>> defaultSequences; public XmlMappingParser(ConstraintHelper constraintHelper) { this.constraintHelper = constraintHelper; this.annotationIgnores = new AnnotationIgnores(); this.constraintMap = new HashMap, List>>(); this.cascadedMembers = new HashMap, List>(); this.defaultSequences = new HashMap, List>>(); } public void parse(Set mappingStreams) { for ( InputStream in : mappingStreams ) { ConstraintMappingsType mapping = getValidationConfig( in ); String defaultPackage = mapping.getDefaultPackage(); parseConstraintDefinitions( mapping.getConstraintDefinition(), defaultPackage ); for ( BeanType bean : mapping.getBean() ) { Class beanClass = getClass( bean.getClazz(), defaultPackage ); checkClassHasNotBeenProcessed( processedClasses, beanClass ); annotationIgnores.setDefaultIgnoreAnnotation( beanClass, bean.isIgnoreAnnotations() ); parseClassLevelOverrides( bean.getClassType(), beanClass, defaultPackage ); parseFieldLevelOverrides( bean.getField(), beanClass, defaultPackage ); parsePropertyLevelOverrides( bean.getGetter(), beanClass, defaultPackage ); processedClasses.add( beanClass ); } } } public Set> getProcessedClasses() { return processedClasses; } public AnnotationIgnores getAnnotationIgnores() { return annotationIgnores; } public List> getConstraintsForClass(Class beanClass) { List> list = new ArrayList>(); if ( constraintMap.containsKey( beanClass ) ) { for ( MetaConstraint metaConstraint : constraintMap.get( beanClass ) ) { @SuppressWarnings("unchecked") // safe cast since the list of meta constraints is always specific to the bean type MetaConstraint boundMetaConstraint = ( MetaConstraint ) metaConstraint; list.add( boundMetaConstraint ); } return list; } else { return Collections.emptyList(); } } public List getCascadedMembersForClass(Class beanClass) { if ( cascadedMembers.containsKey( beanClass ) ) { return cascadedMembers.get( beanClass ); } else { return Collections.emptyList(); } } public List> getDefaultSequenceForClass(Class beanClass) { if ( defaultSequences.containsKey( beanClass ) ) { return defaultSequences.get( beanClass ); } else { return Collections.emptyList(); } } @SuppressWarnings("unchecked") private void parseConstraintDefinitions(List constraintDefinitionList, String defaultPackage) { for ( ConstraintDefinitionType constraintDefinition : constraintDefinitionList ) { String annotationClassName = constraintDefinition.getAnnotation(); Class clazz = getClass( annotationClassName, defaultPackage ); if ( !clazz.isAnnotation() ) { throw new ValidationException( annotationClassName + " is not an annotation" ); } Class annotationClass = ( Class ) clazz; ValidatedByType validatedByType = constraintDefinition.getValidatedBy(); List>> constraintValidatorClasses = new ArrayList>>(); if ( validatedByType.isIncludeExistingValidators() != null && validatedByType.isIncludeExistingValidators() ) { constraintValidatorClasses.addAll( findConstraintValidatorClasses( annotationClass ) ); } for ( JAXBElement validatorClassName : validatedByType.getValue() ) { Class> validatorClass; validatorClass = ( Class> ) loadClass( validatorClassName.getValue(), this.getClass() ); if ( !ConstraintValidator.class.isAssignableFrom( validatorClass ) ) { throw new ValidationException( validatorClass + " is not a constraint validator class" ); } constraintValidatorClasses.add( validatorClass ); } constraintHelper.addConstraintValidatorDefinition( annotationClass, constraintValidatorClasses ); } } private Class loadClass(String className, Class caller) { LoadClass action = LoadClass.action( className, caller ); if ( System.getSecurityManager() != null ) { return AccessController.doPrivileged( action ); } else { return action.run(); } } private List>> findConstraintValidatorClasses(Class annotationType) { List>> constraintValidatorDefinitionClasses = new ArrayList>>(); if ( constraintHelper.isBuiltinConstraint( annotationType ) ) { constraintValidatorDefinitionClasses.addAll( constraintHelper.getBuiltInConstraints( annotationType ) ); } else { Class>[] validatedBy = annotationType .getAnnotation( Constraint.class ) .validatedBy(); constraintValidatorDefinitionClasses.addAll( Arrays.asList( validatedBy ) ); } return constraintValidatorDefinitionClasses; } private void checkClassHasNotBeenProcessed(Set> processedClasses, Class beanClass) { if ( processedClasses.contains( beanClass ) ) { throw new ValidationException( beanClass.getName() + " has already be configured in xml." ); } } private void parseFieldLevelOverrides(List fields, Class beanClass, String defaultPackage) { List fieldNames = new ArrayList(); for ( FieldType fieldType : fields ) { String fieldName = fieldType.getName(); if ( fieldNames.contains( fieldName ) ) { throw new ValidationException( fieldName + " is defined twice in mapping xml for bean " + beanClass.getName() ); } else { fieldNames.add( fieldName ); } final boolean containsField; ContainsField containsAction = ContainsField.action( beanClass, fieldName ); if ( System.getSecurityManager() != null ) { containsField = AccessController.doPrivileged( containsAction ); } else { containsField = containsAction.run(); } if ( !containsField ) { throw new ValidationException( beanClass.getName() + " does not contain the fieldType " + fieldName ); } GetDeclaredField action = GetDeclaredField.action( beanClass, fieldName ); final Field field; if ( System.getSecurityManager() != null ) { field = AccessController.doPrivileged( action ); } else { field = action.run(); } // ignore annotations boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false : fieldType.isIgnoreAnnotations(); if ( ignoreFieldAnnotation ) { annotationIgnores.setIgnoreAnnotationsOnMember( field ); } // valid if ( fieldType.getValid() != null ) { addCascadedMember( beanClass, field ); } // constraints for ( ConstraintType constraint : fieldType.getConstraint() ) { MetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, field, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); } } } private void parsePropertyLevelOverrides(List getters, Class beanClass, String defaultPackage) { List getterNames = new ArrayList(); for ( GetterType getterType : getters ) { String getterName = getterType.getName(); if ( getterNames.contains( getterName ) ) { throw new ValidationException( getterName + " is defined twice in mapping xml for bean " + beanClass.getName() ); } else { getterNames.add( getterName ); } ContainsMethod cmAction = ContainsMethod.action( beanClass, getterName ); boolean containsMethod; if ( System.getSecurityManager() != null ) { containsMethod = AccessController.doPrivileged( cmAction ); } else { containsMethod = cmAction.run(); } if ( !containsMethod ) { throw new ValidationException( beanClass.getName() + " does not contain the property " + getterName ); } final Method method; GetMethodFromPropertyName action = GetMethodFromPropertyName.action( beanClass, getterName ); if ( System.getSecurityManager() != null ) { method = AccessController.doPrivileged( action ); } else { method = action.run(); } // ignore annotations boolean ignoreGetterAnnotation = getterType.isIgnoreAnnotations() == null ? false : getterType.isIgnoreAnnotations(); if ( ignoreGetterAnnotation ) { annotationIgnores.setIgnoreAnnotationsOnMember( method ); } // valid if ( getterType.getValid() != null ) { addCascadedMember( beanClass, method ); } // constraints for ( ConstraintType constraint : getterType.getConstraint() ) { MetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, method, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); } } } private void parseClassLevelOverrides(ClassType classType, Class beanClass, String defaultPackage) { if ( classType == null ) { return; } // ignore annotation if ( classType.isIgnoreAnnotations() != null ) { annotationIgnores.setIgnoreAnnotationsOnClass( beanClass, classType.isIgnoreAnnotations() ); } // group sequence List> groupSequence = createGroupSequence( classType.getGroupSequence(), defaultPackage ); if ( !groupSequence.isEmpty() ) { defaultSequences.put( beanClass, groupSequence ); } // constraints for ( ConstraintType constraint : classType.getConstraint() ) { MetaConstraint metaConstraint = createMetaConstraint( constraint, beanClass, null, defaultPackage ); addMetaConstraint( beanClass, metaConstraint ); } } private void addMetaConstraint(Class beanClass, MetaConstraint metaConstraint) { if ( constraintMap.containsKey( beanClass ) ) { constraintMap.get( beanClass ).add( metaConstraint ); } else { List> constraintList = new ArrayList>(); constraintList.add( metaConstraint ); constraintMap.put( beanClass, constraintList ); } } private void addCascadedMember(Class beanClass, Member member) { if ( cascadedMembers.containsKey( beanClass ) ) { cascadedMembers.get( beanClass ).add( member ); } else { List tmpList = new ArrayList(); tmpList.add( member ); cascadedMembers.put( beanClass, tmpList ); } } private List> createGroupSequence(GroupSequenceType groupSequenceType, String defaultPackage) { List> groupSequence = new ArrayList>(); if ( groupSequenceType != null ) { for ( JAXBElement groupName : groupSequenceType.getValue() ) { Class group = getClass( groupName.getValue(), defaultPackage ); groupSequence.add( group ); } } return groupSequence; } private MetaConstraint createMetaConstraint(ConstraintType constraint, Class beanClass, Member member, String defaultPackage) { @SuppressWarnings("unchecked") Class annotationClass = ( Class ) getClass( constraint.getAnnotation(), defaultPackage ); AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor( annotationClass ); if ( constraint.getMessage() != null ) { annotationDescriptor.setValue( MESSAGE_PARAM, constraint.getMessage() ); } annotationDescriptor.setValue( GROUPS_PARAM, getGroups( constraint.getGroups(), defaultPackage ) ); annotationDescriptor.setValue( PAYLOAD_PARAM, getPayload( constraint.getPayload(), defaultPackage ) ); for ( ElementType elementType : constraint.getElement() ) { String name = elementType.getName(); checkNameIsValid( name ); Class returnType = getAnnotationParameterType( annotationClass, name ); Object elementValue = getElementValue( elementType, returnType ); annotationDescriptor.setValue( name, elementValue ); } A annotation; try { annotation = AnnotationFactory.create( annotationDescriptor ); } catch ( RuntimeException e ) { throw new ValidationException( "Unable to create annotation for configured constraint: " + e.getMessage(), e ); } java.lang.annotation.ElementType type = java.lang.annotation.ElementType.TYPE; if ( member instanceof Method ) { type = java.lang.annotation.ElementType.METHOD; } else if ( member instanceof Field ) { type = java.lang.annotation.ElementType.FIELD; } // we set initially ConstraintOrigin.DEFINED_LOCALLY for all xml configured constraints // later we will make copies of this constraint descriptor when needed and adjust the ConstraintOrigin ConstraintDescriptorImpl constraintDescriptor = new ConstraintDescriptorImpl( annotation, constraintHelper, type, ConstraintOrigin.DEFINED_LOCALLY ); return new MetaConstraint( beanClass, member, constraintDescriptor ); } private Class getAnnotationParameterType(Class annotationClass, String name) { Method m; GetMethod action = GetMethod.action( annotationClass, name ); if ( System.getSecurityManager() != null ) { m = AccessController.doPrivileged( action ); } else { m = action.run(); } if ( m == null ) { throw new ValidationException( "Annotation of type " + annotationClass.getName() + " does not contain a parameter " + name + "." ); } return m.getReturnType(); } private Object getElementValue(ElementType elementType, Class returnType) { removeEmptyContentElements( elementType ); boolean isArray = returnType.isArray(); if ( !isArray ) { if ( elementType.getContent().size() != 1 ) { throw new ValidationException( "Attempt to specify an array where single value is expected." ); } return getSingleValue( elementType.getContent().get( 0 ), returnType ); } else { List values = new ArrayList(); for ( Serializable s : elementType.getContent() ) { values.add( getSingleValue( s, returnType.getComponentType() ) ); } return values.toArray( ( Object[] ) Array.newInstance( returnType.getComponentType(), values.size() ) ); } } private void removeEmptyContentElements(ElementType elementType) { List contentToDelete = new ArrayList(); for ( Serializable content : elementType.getContent() ) { if ( content instanceof String && ( ( String ) content ).matches( "[\\n ].*" ) ) { contentToDelete.add( content ); } } elementType.getContent().removeAll( contentToDelete ); } private Object getSingleValue(Serializable serializable, Class returnType) { Object returnValue; if ( serializable instanceof String ) { String value = ( String ) serializable; returnValue = convertStringToReturnType( returnType, value ); } else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable ).getDeclaredType() .equals( String.class ) ) { JAXBElement elem = ( JAXBElement ) serializable; String value = ( String ) elem.getValue(); returnValue = convertStringToReturnType( returnType, value ); } else if ( serializable instanceof JAXBElement && ( ( JAXBElement ) serializable ).getDeclaredType() .equals( AnnotationType.class ) ) { JAXBElement elem = ( JAXBElement ) serializable; AnnotationType annotationType = ( AnnotationType ) elem.getValue(); try { @SuppressWarnings("unchecked") Class annotationClass = ( Class ) returnType; returnValue = createAnnotation( annotationType, annotationClass ); } catch ( ClassCastException e ) { throw new ValidationException( "Unexpected parameter value" ); } } else { throw new ValidationException( "Unexpected parameter value" ); } return returnValue; } private Annotation createAnnotation(AnnotationType annotationType, Class returnType) { AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor( returnType ); for ( ElementType elementType : annotationType.getElement() ) { String name = elementType.getName(); Class parameterType = getAnnotationParameterType( returnType, name ); Object elementValue = getElementValue( elementType, parameterType ); annotationDescriptor.setValue( name, elementValue ); } return AnnotationFactory.create( annotationDescriptor ); } private Object convertStringToReturnType(Class returnType, String value) { Object returnValue; if ( returnType.getName().equals( byte.class.getName() ) ) { try { returnValue = Byte.parseByte( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid byte format", e ); } } else if ( returnType.getName().equals( short.class.getName() ) ) { try { returnValue = Short.parseShort( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid short format", e ); } } else if ( returnType.getName().equals( int.class.getName() ) ) { try { returnValue = Integer.parseInt( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid int format", e ); } } else if ( returnType.getName().equals( long.class.getName() ) ) { try { returnValue = Long.parseLong( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid long format", e ); } } else if ( returnType.getName().equals( float.class.getName() ) ) { try { returnValue = Float.parseFloat( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid float format", e ); } } else if ( returnType.getName().equals( double.class.getName() ) ) { try { returnValue = Double.parseDouble( value ); } catch ( NumberFormatException e ) { throw new ValidationException( "Invalid double format", e ); } } else if ( returnType.getName().equals( boolean.class.getName() ) ) { returnValue = Boolean.parseBoolean( value ); } else if ( returnType.getName().equals( char.class.getName() ) ) { if ( value.length() != 1 ) { throw new ValidationException( "Invalid char value: " + value ); } returnValue = value.charAt( 0 ); } else if ( returnType.getName().equals( String.class.getName() ) ) { returnValue = value; } else if ( returnType.getName().equals( Class.class.getName() ) ) { returnValue = loadClass( value, this.getClass() ); } else { try { @SuppressWarnings("unchecked") Class enumClass = ( Class ) returnType; returnValue = Enum.valueOf( enumClass, value ); } catch ( ClassCastException e ) { throw new ValidationException( "Invalid return type: " + returnType + ". Should be a enumeration type." ); } } return returnValue; } private void checkNameIsValid(String name) { if ( MESSAGE_PARAM.equals( name ) || GROUPS_PARAM.equals( name ) ) { throw new ValidationException( MESSAGE_PARAM + ", " + GROUPS_PARAM + ", " + PAYLOAD_PARAM + " are reserved parameter names." ); } } private Class[] getGroups(GroupsType groupsType, String defaultPackage) { if ( groupsType == null ) { return new Class[] { }; } List> groupList = new ArrayList>(); for ( JAXBElement groupClass : groupsType.getValue() ) { groupList.add( getClass( groupClass.getValue(), defaultPackage ) ); } return groupList.toArray( new Class[groupList.size()] ); } @SuppressWarnings("unchecked") private Class[] getPayload(PayloadType payloadType, String defaultPackage) { if ( payloadType == null ) { return new Class[] { }; } List> payloadList = new ArrayList>(); for ( JAXBElement groupClass : payloadType.getValue() ) { Class payload = getClass( groupClass.getValue(), defaultPackage ); if ( !Payload.class.isAssignableFrom( payload ) ) { throw new ValidationException( "Specified payload class " + payload.getName() + " does not implement javax.validation.Payload" ); } else { payloadList.add( ( Class ) payload ); } } return payloadList.toArray( new Class[payloadList.size()] ); } private Class getClass(String clazz, String defaultPackage) { String fullyQualifiedClass; if ( isQualifiedClass( clazz ) ) { fullyQualifiedClass = clazz; } else { fullyQualifiedClass = defaultPackage + PACKAGE_SEPARATOR + clazz; } return loadClass( fullyQualifiedClass, this.getClass() ); } private boolean isQualifiedClass(String clazz) { return clazz.contains( PACKAGE_SEPARATOR ); } private ConstraintMappingsType getValidationConfig(InputStream in) { ConstraintMappingsType constraintMappings; Schema schema = getMappingSchema(); try { JAXBContext jc = JAXBContext.newInstance( ConstraintMappingsType.class ); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema( schema ); StreamSource stream = new StreamSource( in ); JAXBElement root = unmarshaller.unmarshal( stream, ConstraintMappingsType.class ); constraintMappings = root.getValue(); } catch ( JAXBException e ) { String msg = "Error parsing mapping file."; log.error( msg ); throw new ValidationException( msg, e ); } return constraintMappings; } private Schema getMappingSchema() { boolean isSecured = System.getSecurityManager() != null; GetClassLoader action = GetClassLoader.fromClass( XmlMappingParser.class ); ClassLoader loader = isSecured ? AccessController.doPrivileged( action ) : action.run(); URL schemaUrl = loader.getResource( VALIDATION_MAPPING_XSD ); SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ); Schema schema = null; try { schema = sf.newSchema( schemaUrl ); } catch ( SAXException e ) { log.warn( "Unable to create schema for {}: {}", VALIDATION_MAPPING_XSD, e.getMessage() ); } return schema; } } ././@LongLink0000000000000000000000000000020600000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/ValidationBootstrapParameters.javalibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/java/org/hibernate/validator/xml/V0000644000175000017500000000330311262172500033313 0ustar twernertwerner// $Id: ValidationBootstrapParameters.java 17620 2009-10-04 19:19:28Z hardy.ferentschik $ /* * JBoss, Home of Professional Open Source * Copyright 2009, Red Hat, Inc. and/or its affiliates, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hibernate.validator.xml; import java.io.InputStream; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.validation.ConstraintValidatorFactory; import javax.validation.MessageInterpolator; import javax.validation.TraversableResolver; import javax.validation.spi.ValidationProvider; /** * @author Hardy Ferentschik */ public class ValidationBootstrapParameters { public ConstraintValidatorFactory constraintValidatorFactory; public MessageInterpolator messageInterpolator; public TraversableResolver traversableResolver; public ValidationProvider provider; public Class> providerClass = null; public final Map configProperties = new HashMap(); public final Set mappings = new HashSet(); } libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/assembly/0000755000175000017500000000000011402110347026542 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/assembly/dist.xml0000644000175000017500000000660111265106012030233 0ustar twernertwerner dist tar.gz tar.bz2 zip false lib runtime com.googlecode.jtype:jtype javax.xml.bind:jaxb-api com.sun.xml.bind:jaxb-impl javax.xml.stream:stax-api javax.activation:activation false lib/jdk5 runtime javax.xml.bind:jaxb-api com.sun.xml.bind:jaxb-impl javax.xml.stream:stax-api javax.activation:activation readme.txt / true license.txt / target *-javadoc.jar *-sources.jar hibernate-*.jar target/site/apidocs docs/api target/docbook/publish docs/reference . true dependency-reduced-pom.xml *.txt **/target/** *.iml libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xsd/0000755000175000017500000000000011402110365025521 5ustar twernertwerner././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xsd/validation-configuration-1.0.xsdlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xsd/validation-configuration-1.0.x0000644000175000017500000000266411257140642033226 0ustar twernertwerner libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/xsd/validation-mapping-1.0.xsd0000644000175000017500000001605111245471114032332 0ustar twernertwerner libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/0000755000175000017500000000000011402110347026343 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/0000755000175000017500000000000011402110353027267 5ustar twernertwernerlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/images/0000755000175000017500000000000011402110352030533 5ustar twernertwerner././@LongLink0000000000000000000000000000016200000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/images/validation-mapping-1.0.pnglibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/images/validation-ma0000644000175000017500000053356111251452073033233 0ustar twernertwerner‰PNG  IHDRŠ5*ÅhhsRGB®ÎébKGDÿÿÿ œ§“ pHYs  šœtIMEÙ  MUœ‰ IDATxÚìe`GǟÙ=¿‹\܍$$@Ð$8Š»§ž»i°à.åŵmqŠ)N°‚%XBÜs—óÝy?,Gr )$A:¿/ÝœÝ™gfŸÿOýªÞ)PTx|ÿïü§ŒÿEeff&$$äääÈd2@ðÅ!„ z= Wª#²4M'&&Ÿ|ùR£ÑX[[ÛÛÛÓ4M”šXªbi¥¶ÄˆÒh4ÉÉə™™B¡ÐÑÑQ"‘F üG¢gŒbu¹é™™J ó)þ!€T*_¿~ýúõëÌÌ̯§™ož·wûÞRK»T(*==3—B¡(H›¿æÎLlšø"d!„ŽÊÌÔÔt•Ž- þ|Îގü ;EJ|r–ŠDS¢ÓéââââããSSS¹î–o®ž$z.@Aú•Cë/ÆUë6ŒyY‹OôXE ‚—/_&$$…Â<^ƒÏç×®]û SnýÅ^ƒ~Z\µG5ÇRŽÚŒæzðàAll,MÓŠæBÉd²àà௶â!„@£ÌR³"k aúüÄŠ5g·5¥™¿Ž QT+2µ µ¶~î ²§&wÞ²|÷ÐT’F€išÇãeff^žpÁÂÂ"HS,•J‰§#Ÿ)yÆ0׎^xüTØx¬E±<ÏÂÂ⧟~zúô©···©+¡i:""B¯×óxŒRÜòéÆÀœJHC}©ÄDSÌ_úAá6{ÁeaaÑ¢E ww÷<ý–zœ>**ªŠÜ¿µ9ƒ™±Yš¿zòËÂí>]—üP øŽ‰RkkÌPC0BwÎü£Îø¥Í< )è¶0†"–oÁ%H[ˬ,­dÿÊšæŸý¡4‹D¢ƒ®\¹244Ô`0p-9–eù|þ7"""Ÿæf@ä¹ uÖ=ÿ+—ÖUªSÙªhŽ®^¯×oÞŒ¹mÛ¶y“RòÂÌ¥!¬6öŸÛw"c²X¶lµZ•Ëù‹i€Ìžš¿oF)5Z–-Ó¢s [!ÂzȥūëÏGKíüê5µR WŒŒžtáIŠÄ§\•ê!~"„²^>Jb¥vÅ­;Q©9ÖõÛ4tƒØƒ§"ŽªjƒŠN–3É1÷Î\ˆÀŠlFA¶ºp›rÞÿÚµkÖÖÖyµJ,.MmV$=œ|#2]‘Ë0žÛ×p²RÀŸŽºréŸXhçJõ”wA49¯Ÿ²øÈ›™6ÖI7®¿7m[/=êúßwc(ZæèQŸF-KåX¿ãj+{d<‹LŠí—o<ÈVYToR×Ï^Ќ¿µiîêmœ[*líkµ r•˜Ú•‰Ï¬¥?‰Œÿ2E\«i_‹ôgnd*õ•ê6®ànƒJyÿԕH ”PRŠn³*ŽbŸ^•c°uÖ¿ºs3FíY¶rhˆ¿ŒFÙ±OtBk:ç~äãälq•ïêWp·D€«MXî+qEëãïE(ËÛdGþy#ÎÆÁ·VÃ`[MæÓˆë×b’å~žR1߯ÁÅÝٚÒgÿsîÒãÔ,-˄4i_ÖђB("ƒÁ0hРõë×sM7>ŸÏªP¡éÙ&Ÿ9yÆ(Eš4šrUjßùt(ŠÊÉÉ1ëeŠW¡Åb±™9„ .âÌÒ© ¯g0ÎiÐÿg/1 I'wÏ_öËэ‹ /394°U°­x|È>³fÌíÔkשã”f\:ªœ.)fÿ’«nÝÁ +ž…ÿ°é?6ô~bÕ¢SÏg§ŽOÿ9ÝbÂpÏÌä?ÞÏ|pÝ³ÝÆC[XbÕß;VÍ>í"6$¿b:LýuÞÐ@ô¡6B(333ôé¹?¬54w££³³+5 :¿iùò« v¬"Gã5|Þÿ†¶s{q|ÍŒ ™'.l_Vúx_øâœÌÖ"&úiìՈ =Û³Ÿsö?'NÈ/Ûô<»–C=sò ðúÊoK¶Ou Ð$Fß9ö€Î€žå̹È{ ÷.96Zøûޱn2ž±{íìß#eÿ(µá˜=ëŠTÍM~ŽsRç?m;0¯_}NYzŽ\Œ`xË/O¯ûÇ?J§Üøž—Wž:7ïúˊÙÕÜå§&6ÛTg×é‘5Uœ˜Ñq»Å~ŒØëõ©T÷yGç ôSÇ=Ø1uâÚ+÷hÇ:~Íãçê.³Â'ÿXãÖ¯«g­8ª°æ€&ö©_ÆÁRð¡÷Ž›&ÆýÕªUAAAMš4ƒÁ@Šsߚ|ÿþ}NµZí̙3)Šº{÷îÇ‹+ozœÞÎÎÎÜmÔÉ#G膟:>¡’eŽ’òàEøˆÑ‡¡ÎÊߖµªæœ‘(¶àý}§úÌyÍq=8ŸÙ”¹ûfŽšùäܯ3V_ítú΂ºY?ué³sãŽF ÃùlÆÍ[×%îÜŸ,kS·æ?¯©ÔxêŽsá|· žûbÖ š&¢Ë}ßÿúœz¶º'‹»,]tfÚÐ@il* W­Z¥T*9WKÓôˆ#ÔjõÁƒ»—pcæãÜ1MÓOž<±··7טIX3í§­ìgïúµGCߜäDœhþÝ{üËŠ›Žèã‚^mÕ~PϱßuþÏbÒÒ^_|•0oÉÂ¥S#'÷œy`וŸM;ÞÜñë™\×e‡¶tq¥3uŽ¿z÷!ž“·4°bÜ÷2 +Zmjâí—ÏB—­ÚVßÑLœn{­ª.Œÿ}XÛ{¶ÞÚ΍Õde)²Ô ˆJ»ò÷·Îs7ï^ŠÙÓŠÖžÝOŽ n8`€ëŒãÃ&­R‰åK1Tjmœî @ÑB!ŸBLÎýȈD‡¶;Ö,”6×vøæÇ¡c¶îúÝîáP¿¶Ge w•ñ=kvœ8q#/sǛ~³-˜R•Æú”ä×Xž&|óûøyÃúlZº&ô»læœÇ÷EA=6‡wpx±·]ƒá+¿ï°aXmvlªškî 6éêÍەæÍ??OºcD‡UKM8ñÆÑM‹~}ÒuóßsûyÜÙ2¯ÛàéÙÔǬ(?èÏ-ÓªðrӑŒ‡ŠÔkEÓŽZ­>räȆ <==ÕjuÛ¶m‰6ß <#€€ˆ* „;E¥€€ŒzõŠ“gcÃ?77799¹žžb0 ÇùþuêU:±m䀸»whb!†Ôç1Ú†ÓÆ4 ñ pr÷z£ñðŒlë°: Ï-P‘wéµôÉ9 Ï蜘ma㚯Þy)ªRS `ÈÕY7Ž|ÒÀ*NŒ¬Ÿ*›öŽ© çAœŸÖa%vpŠVLùI­Æ¯A,‹ÏÍ\¯_¿6v9ðx<„Æ811‘3MÓ/^ŒxöìY³fÍŽZíǕHffŠyseÅ]ÒäT9­mƒr"D.žqŽR»×÷òÑ>=&N޳Ï?qž¬S–6­‡/žÒÒ'iÝ|œR©d5@µ¶-}îm_1tà­6]tj"—€Ì9’ZÛ9ÙۋhÐ2ðŸ|mÛÊX›Lg„OšÆäÆ=É6|S•ˆ¢$%Rk×tô–ðÁ•mèôÀbt=GÃðœ]ʁÄÒÁÚÊ€U&ß]6lÁc‰ˆÀŒ^êY¡c¿1Müd•NV­ÓŒÉ£xŠUUü-*üžlëøŸV`ÝËBžX@àæ%[1ë'…Jšñd±™¶ KËݺŒj àÞ€a³ÓÛ㟧‚Ôz«ºý–ŒîâBƒ[Æ^³O=IÕbÑ|ùÛ^i–…À+×ö ušOÙ@:&^ ¹1)éŒ&öó€ªýzÔ<ôô* ↺þ¶îðŽÁ¯«Žè6ªc}nÂÃß?„N§KHHÈÍÍÍÈÈHII"ÏÂ7'ÏB†WÔIT­á6`vÆÊÇ£T*8pà@Ӄ,ËÖ©S§N:Řœ©S§šéCG”Ï÷]–®²úcïþ_×-8•²eÁèj4|^Þ<" ø{ÛcÐi5¹ÉxÀbƒD"¹«£ ç6ì:¬ÚwÍ=î2¬»•DÀ² Sç°Nö”V ÀÓkõ  Œ=;pà«PG;Wï*·îŸë?þçU©T‹-ÊÓ¹-‘H† fü£mu÷îÝ=zt–Oçqõà¿í gP€³ F|O+ÐéÕz¡ \—¡¿Hüytë‚iWbswýÔÙۚ¯Ña˜Å@#.R÷“ËXÝóÛFŽ[$jjçîà”ÅbÞ»þvFƒœ\l„, @kT9KùhÕ:P¿íõ§yR7¥XÈ`ƒÌÙÙZÌcG ‘ !Ði¬œ„bôZ=ÄCŽ>õêàC2Ü¿qvq/SßGŒ±”Ï“XŠÞdŸfyXìi%ŒQb„ñ0g+ãP¥E~^v`0èŽ5…d<ÀÀà·FÍJWd(l)Z PwâŒMveN^ûkÓøQ÷rÖì\O*øðªwƒÁ`ee5vìXµZ]¥J•æÍ›ÃÛÍm·#Ϝ?¿©MUÔoQžÐÅôH–e-,,Ì6ÿ Žw?µZmf€!„µi©ÒÊ­'Öm]µ_³Fç.ߋï[­’OCZðçÂ=—CÊ7)o“•ËÚžÙ4ºwʀY­\Ëf‚C™Þ³ûº€V¯åŠâ°z˰\WR°˜}÷3H‹:qäғ‹Ç£êá§S«,Ó[`ú][šÀ\`ŒåryžƒVVVy<¯V«ýĉÜjµÚükk·:"‹m¿<û]ý.µ\rR^¬Ýlì}k³)ów^mö ².ü¶ ôu›‚1Æ­Þ˜zHJÈpoÖ}zëˆÚÆÛš/°ÔE﹝6Š‘;ÿ­Æèô€ ê緎ž~€ztyŠÿƒ?»¯Ùbh‰è÷[1£Ñ³¬qÞËŒQdxüëmíà@!Pbۀ~˗š 5Yc,)P²Ø€ß•Eç<=œ÷¯È#ñ÷[»€-«²HO³Gi3S"÷ÓÖm-ÔÅ\žÇsªZ֕‡$ŒøóWo7yQ³UÍóçâ µ+zŠòì(`Z‹XÌ0 ó±³ÑžÙ³lYûž!©G·,?qE3Ÿ‡„݋ÊПÃëöí#?,Ÿx:JÓ¿Îåc,ŸYK6räHã<GІߔ<#Y²3µ!Íœ©bìÙæVjNš4iÛ¶mŠrÂãñJi™ &æÄÎów«üíï%5j;²º› À*lå²Ì±ãFv¿éá K‹÷X{aCMÐä€Bû&a¬ÉÈ20•›ôž>ðᒰs»ª U©Z÷™2e8Ö*¹jÎϳ:6 k \€Çh10 ¯5íW jòœ¯Daëî«¿ž{Ҕï×ÏoÊC…™‹eÙöíÛ[ZZšúYN÷qØÿŒ!×Qsæ'Ö¿éz7»Œ8§EG~iâ²j͌«ú6œ`sŸ–Î\·¢ªƒ*'S¥Ç€kՌR `ïmY¶zß%ÖËòÙªÝè>¶šÖi`ƶe­ž˜žþP Z“ - ˆ'òð®{;Õú>ÀRÞ;<Úµiy‹ºßSLn®RÇbЫrr4sÚÇj€1P?€S·Ž~cšµýcª}-=ÍWoF›«Tær÷ÁzœÍjõðŠØ”ZFÏ05Ÿwƒ‰íü"Vž;ZÝ;8|pËuán€Uçv/êµ:Mñ\‰ì‡ÎZQ|^N惵cûýŸôUäiË& jVQ ÍÑæš¹­æ±&+toj£c²² €:íúO{˜õÛ¯³g_³w·÷r¶­5èø ;6noL²ÀžŠÌõïÛ¡Š„OåÚ¹sgzzºN§ã$™a¡PEú· „oIž1b“£d&15ûº­¶ˆ(•ÊQ£F©Õê<›zbŒ»wï^Z_3ùÖjÚ‚Þî¶Q?¶ñ±(ã>4¬œÊÍCU¯^̺zYóÀ¶Ö胿«ªÙ  |§Åû…2”žŒuuÉ»ùˆ°j:î>ÒÊý]ÉT*c`WÿÐޕíBqƒµ{öý™Æ“ÉkÖé|æbŠ…7R«„¶v­7À%ã™Òà_9ŽnP+µž š4šÛÊ 2sÚw®ßŒMyG 4Yø‡¿}”¬Ãе=݀Û|?tñÞÖVŠ×mj|÷VºØ[ž¶3êæA‘¥5€¬A¿þ’˜—™Zæ‡ÁUš×¯(âQ…¿€Z­¶aÆåʕ˳8cÜŸ}{???âæ„¯DQ”Ù°5þÆÞ՛÷y Ù>€ªìÓǝ/^|þüùÙ³gçää899–B£^­V[YYåý €ù=ÌoKbÌø{»O°M˜ÛÚäÿxXswkÑ¢EHHHÓŠM5·····wA]šÆ_^žpáøñã‹/þhs]œzuðàÁ‘‘‘…=Æ\~Í^˜ÇbÜjÃÔÔœÒTÄ}p[’<÷B‹*ãöÙ± º$ì>ÓÔÆôøµþ­»Åy¯ÜŸ¢­3õ!›œw0ñ̑e³ÖevíÑ?Ù·nÎSþ«W®úÞ_R€*pûöíÖ­[?~<++ËÒÒ²|ùò"‘èƒæ"_uô `øýÈ)Õd®2.†*F ƒZ­þlÛ÷¿Ýù+6+ÃF_ÿžwËw‡<þÏôb³ dú_ húètº‚†äKÉç˜ßwÇÞÚÐ|Æ!ó79ŠÞjbþò1Ö?ãÑBdªóæ,›¿$ÍýÿÝ£ÞÝEèZŠÕŽ)Z7:ê9vè5&Uê/0Ló÷Áò’ùúVi^érläÜœ€N‹Çtì\ËWWÎB`F­V$ÏD› „oFž1Æ ²ŽsµŽûV›Þú傜wÑÝ|Ÿùµ¹Nsù}w샹0odó&ɧ•ÿÒÌÅaYô®aööØÁ£ÕÈ¡ˆ/ÎsGã6ƒøÿ&™ÉŒ:Œ›ÚT©Ö³H,³²” PŸ×(+@äùÓ€‡@ø–ÁEÑb‰ôý+ÆxÏLÊäcŒ%[ˆÄf{a‘ç’G$}–_©³+¥íÇóñŸÿªô¿é;øŽ†lQz¿ G*•’ES·,Ï,˵“¢š’Ð3„J¥êÔ©S鋥N§ãr‡ÞòUHJ¥ª^œzé· þùçn£ò¯È\ÿYŽZmAs · Ϲ¹¹œ63 óüùóÄÄĒX݄1æóùJ¥²4ó&‰ŒOÔëõϟ?OJJúòD®8^¯/ÍçsæB)•ÊgϞeee•ÖR7ÂÇÔšŠÍ~]†@ | òlœAÍ0ŒX, …%'`¥ÙÇEÌÆÑëõz±X,‰Ÿ¢þÛR6EQFsaŒÅb±F£!òL* @ø<òœçïíÏ,ÍþÒOÛûì|vsŸŠJBŠ@øÆå!dgg' KôUÇK$ãçâK Š¢ìííÅbñ×åÈ0Æ¥Âòù|gggkkkâ÷¿ ø|ŸX,&v ŸAyæú6mmmmmmKMxJÍõs£tvvv|þùëÐéÒ4—@ ptt$¯©$ásACçR~pi>ñðYÄ\RpÂQž @ y&@ä™@ "ρ@ ˆ<@ä™ðMCö¢ú–lXÊ)ùŒÿ2ë-y›˜€ß›pKt®]»vîܹúPÊ7,Ƀ¶±±A} ‘iX·n]VVV‰>ÈÛÛ»k×®Ÿ1ã!­V»víZFó…TZ;;»Wƒ@ä™PlÞüäɓ[·n¥(ÊÚښeYb™¢@QT||ü˗/§L™âååõÙš{ºZ­^²dÉ͛7K(1!NwãÆŒŒŒAƒñxŒÏ•q•J5nÜž‘#GjµÚÏ^†™2e ‘g‘gB±ióü±aÆîÝ»ÿøãÄ,ÿ ƒÁ0a„ѣG¯\¹’SèÏ[šZ­v„ IIIkÖ¬ñôô,Ñ'ÞŒysöìÙS§N¥(ês)ŽT*]µjÕR¶mÛF^ ÂG6÷‰ yŽùСCëׯïÕ«§Ídäì_ِÇã-\ž0 `èС±±±ŸË€Fm=ztffæ’%K8m.¡Äp· »uëÖܹs¹¯†—~Þ?ËC B«Õæi ·‰@ä™ð‘Ú|äȑ5kÖôîÝ»GÜñ¢;”ë/ çàŠáEÖ¡P8kÖ¬jÕªõéÓ'..®ôÚÍ#FŒP©TáááÞÞÞP’›ró:eʔ;w‡.…þDão5ÁkµÚŒŒŒÌÌÌüjM éÜ&Œq¯,Ëþù矋/1bD—.]ŒÞ!ŽjÕªƒâÜB>>>›6m*@Z­Têe2¹XLä-"[¡AR{¹~J8A‰DÓ§O_žpá?üðûï¿»ºº–rij4šaƱ,;cÆ (ùfÚ«W¯þÓO?͛7/<<|êÔ©<Þ×ådÆLzF…lmlDŸ~;–eŸ>}ªR©x<ž§§§P($ކ@ä™ðïxüøñ²eËfϞýÝwßåñæÇ¯X±b“&MôzœÙߪTª=z̜9ÓÍÍ­„’—žw÷ôãO„ÏXÖâ#o¡O9Žeö-•KÏfßß8sI% h¡…4:ŽÅªmHÏþ ìùŸÜ£dTèI“&yzzvéÒåòåËTG–e‹ñˡӊM³··>|ž‡‡”ÖǬLzÞŒy‹-Ú¶mۀ Ïڗ÷¡-͑Fm7MþíjWÿb¹J¥R©T"‘ÈÒÒòë1È3á‹!+++11±AƒùÆž~ýú-[¶,è·Z­¶W¯^ééé%'Ï6V‘Úÿµ {—dˆË}’¡UÔIyõêY®Ì–‰ýóÜ߆òõk{yȲ_©|ÕÚâêç„J,÷éÓ§oߟÙÙÙVVV©©© 6Ôëõyl‹1 ãFŠ‹ˆˆˆ±cǖŠ6çQèòåË;;;GDD 0€¢š°°°}ûöåO†µµõµkן°WÉÒÞÖeŠÑ&4MÇÅÅõíÛÞÿ°WúK—.mÕªqA"τ¡iÚ¬7G …y+N‡*8B*°ÇžåàFþޝӖV<B€1äû‘™GŒ9d<(”ÈĖ,kT¿mÅrµX¡eî5ô÷óŽ6œF¶­ã¢U16nNÂw.LÑÌ^'/Š«ªbbb<==u:]LLÌœ{÷²³³—Éd²Ù³g?xð Øe2iæou¡7öÌ[ Æx7à[P‘¯4fœÏçgddÄÆÆzxx\¹r¥wïÞ͛7×étƟ…Âʕ+—|œ~¯nä­WæŒÇw{ºÀ\¥ôó‡B¡ÈÎΟxñbVVÇ£(J§ÓYXXŒ=:::š8B~ÈÔ0‚WR·DOþ²|Ó®;ç4ñ±Ž ™÷û= ¡‡G—{¹»:::y–x4:UE¯Õ~Öñܰ·*1rËâ©«OœŠù€ç[™ûG×­ì+·Ž Ž$JÉržÿÇ"7gGGgŸ²CO>Ïä”YzR+™Ä¢BËVón'æ h©˜æÙ99;È¥ö6RÔÂÊÞÉÖÆÞÅÍú¯Y]‡¯?¯Ö3œŠßÙ>²×Üóz}ÚÁŸ.>|~Ç€ï%nõۆÝI{#úÏÎÎi,Š&¬<™¥çdÉŒ%µZmLLLRR’¥¥eÙ²eCM(W®œ——W±ÏŸ2ÎÉÊÓbð÷÷÷óó 6œæÊ•+öööþþþ...˖-ã–EEQýúõóòòò÷÷wrrJKK3þŠeY¯o£FŒ?1}(Æ8999%%E­VWšP¡råÊŠy¯TIV IDAT©RiÕhôìïsfÍú뙚«W±§–MXŒ%:]ŸpõאŠeíímí~Ø~ãå›,°ofˆ©3_î ±õZBȐöt׆%óEq¥ÿðð„&•€"q…[.+ fJ??VVVþþþ¡¡¡–––YYY¡¡¡îîîd:7Èó· Æ˜‹–>‘HT¢Ûh2îø©gËõêŒ^8«“lQŸ-Wž² þ0cÜò­GîêWu[ÿ†G5GK³nÂòMä¥#›vþíR֓fcœ6ºw‡6ûªv^ôçÙ]5ž/ªã™¬П|œ5iõÎ#‡·w/·¹_ãã,€òÅÍ©ŸÝ÷ÃÄc§×µóÍ8»ã @*1úB–a0fßæZäáŠÞ9aÞõ Š[cFüâX©,Ï Šù{Ó€Þ=fAû+ÆØD¯2°O@Ìæù?8a3ü÷³{ýœnöê}WÔègµZí˗/Ív00 ó‰egæÅ6KSžñNù)‡Onïv |â–S÷µ…–Ÿià·oßÞ±c‡±ô‰û"˜…tn#…³gÏ6iÒä£ã‹œœœ€€€’K¡!3;®fM3õ¯æ=«<:²ãÏGƒË4?“æÑêDCzÊù8¶o­Ž“Ö/Øsoáž2ñWŽ_ÒÙun³€h>h"—D\ œ8yìÈ^PcýÊݕü§WÙFþ-'Ρù4@N¬“>ýìÅÐSsÿÈ©tÓÊ Ë@Ãrv©êbNºiŸMSÔi;ŒÙÆsêõªúè÷—”=6Žt1(^ähû‰»žMmHé*TŽšròð¥Hxt)ÕÇ{víºuœœ‚¶D?yœ®©í&*¬ãaçááÁÍàÕjµaaaŽŽŽ/^œ8qâíÛ·‹ež3MÓOž<‘ËåfOqz››[ŠL>ŸÏõʚŠÄ®]»öíÛGÓ4wJ£ÑOµnݚÏç›m ²K˲c;;»æÍ›Ÿ:uJ py7 ¡;wnߟœžŠÅ1 “¯c$ªåYmÛÁ»Gi•y²'ê®÷}kÛñ]ß±uù4°ž”2ç\Œb¬œõ{?EŒ^ÊÉ*fYc,ˆÛuÿ ”«òChÍvŽUænˆzú,§qE{Áºx<žZ­îÝ»÷þýûàÑ£GÛ·o‰DÄ}ˆ<Ëètºzõê-[¶L­VL=àñ®\¹2jÔš’K¡ža+:ºøÙـTDÓ:=K ˜‡–Ôî9S­+WŸ<ðiEsùFS«Þ4øÔ뙋'^6ÞÕUÀE5ø¬ùøyzÙr3ž|i>£3°ež»oníöB¹@ò ÆZÍWªâù&°Ȅ8§àǪþŽ~tçÞÇWvuZ7ø·º‹o ÐbÒüïŒ}€@$#3,Ë,£Ïïn°f±žO {õ www…Ba<.“É&Ož\®\¹… ~\ٙ ëÕ«g:Âmª^ÜÁ™3g”J%ðùüëׯ‡……q§Ú·o?zôh.‘–––C‡5oݺÕÖ֖‹1ÆÆ My滙%##ãøñã*•ÊŽ­€1îÞœ{§NŠ%㡬¬,??¿<‡(·–?»âÎÙâžm:íR?ž^]àÅå͍zN~žàV¡BCáŒ?EÆyH€Œ{Ÿ…Õ?¿­­sä0‹¥#$r^F„†‹Åûöí[œzõ™3gŽ9Â5Sˆû"yþÆá:HÅbñÇý\ ”ìJȧx\/.YŠùºÇ»kuŸ¶äÕ\¢·öš0‚ B+–CÆÌë׹ךêéþõ—4qxOäŽ:Ìd/“ÉÞ{2Æ\ìøÑeg6œ5[šzœþ… œ”òxŒ-Zp—5nÜxàÀ÷îÝãóù,Ëzxxxzzr§"###""²³³¹Qçzõêh­V{áÂNesrr>PþS•'ï\œ-ƌ›£áæ4èTõ·Ç‡Š Jz¡î0±^9'>$ŸlÚs\·å'§tª£<<̵ÃK”¿VP  QœÎȹF 4ÊôäÚýÞ²b¶¿ä_—>Ô¬YÓÞޞž,‘g¿”Ñ’Y‡#¶? Û¹Û¹Và„†/öOٙ`±€U(¥ÞÉ2 ËÉNñlñ =Ž€ef6€µŽlh«n†»Š4¿Æ4Œ$•zºù ÜðGíÚÕûKŸ9(=»e“ îúø$–]NVjLäÒûyòöY*äâSÙ5qóÈՏ÷ðúuÕÏ?ÿïbç!Í ˆŒcà—k&=ýà9ž¯¡¢6š™y¥ÊŒòèÁ¯[×çøµlû]pêýšÛVï˜ãÒhix#:õE m_ÆÍقŠbISý(霩óܜŠéFå?‹1vrrjÖ¬™ÙS!!!ùï‰1Šã)…L‡·#¯yò^:U!ÀÈŸJû ®Cç®Ol0ºAý1€!'•1èô¹¹Š€–ößÉ@¹Œl=ÈMÓÌdÆ«.\»þ­™ÜoÝ%ï>M Ÿ]B‡ÿ¶Ø¹Æ¬ uØ€˜4‘›¿«œäCŽÑU«V­Zµ*7ç€Ì #ØÈ&& äóe%³£Iª‰O,XF, ùqӐ­›»Uu°©Ú3ŒƒÝäúoY^Wsº©ÿOé€l\+ŽTS.—Oéøfr/¢y|Ÿ€F,€ ûÞœk[¥ÌmZF*qúñHýw6×tÚTûqNËэÝ+5¯°yYhæñfågCzþoãà‡3;xûµ;ÿžÚèqýuZIV-…öú݀1°î¹¹;øeX3ã+%…íãÁÞ¶r¯úfž¯ÛœÄ âšY¿ø!þXGkkW¿Ê«]TCaÚÌÍÝKJJ¢(ŠgEQK–,±µµ-ÒÌ¿dÎìñ¢œ*èžYmvrrjߟ}þŒ›É.;` šÙµiŪÖ]Tö·ž_»]ËoÑÌÙµ²tÁŒ6V‘-|FÛµç¬Úµœîí­-]­­ÝªmùëŽ@›ù|þÓ§OM-Àçó)ŠÚŸ}»ÙY"m·oƒ .?~|ñâÅ}‡[·n 4èôéÓvvvyœlÓŠM»téÒµkׂÆÉ”J¥··÷Ý»wƒ‚‚ ºÿõðsâˇ…Ï©nkЏÏi Àhµ4·Ù!£Õ_HS¹I·õª~XwðÞÅÖy֙Ÿ[ÄÊ4z,ñ¡Ð[`œŽAã¬+Œ1 læž'&Ú­ž§êˆÒd¿XÖ¢Ü?“ãö¶±Óê >œ¿òÕ Õñ„‚<·á¬Ç²ìÇëÖ­{üøqNÇãñ*Tš`mm] ;vlРAÿþý¹~ãR󪀿 ÜÜÜI“&åææ6L©Tººº–-[¶2ž••åêꚛ›û¡œ[wÆêt”@·ÎŒwœ1Ð4Ï̺gœVÇÏWúFŽZ­X,Ÿ~ýºJ¥*T(hã0²kDτ©X±âСC›5köÏ?ÿ䉺üüüheeåP>>>îîˢceÏØ€\5µ#cà-Ò°šç÷ÿ^ôšüØ MSÑ÷ïr¿šÇiówùîVØx«7_Â@|÷na BAŸ{@ú…›,†ýÞÕæbD¥‹ŽŒ¯R€ÏC&›p·{£Ío›jó±cÇêÕ«·téRnSŒ±éÄš‚¢ÕbaÆ û÷ï_°`Aff&”ÖwœŒ?lذèèè.]ºp¿u:é ð’Ëxá ïÿõÆ*oŽ™«=ô{«·ßþŸGóéqcéóó•~!Æ)µÒ'|±gÂß!úõë§×뇟jÕªªU«rî cŒf͚iÓŠ¥¥¥2XȲlá;‹yOýiWßǎÿŸGzç—LâÚÍ¿á_{›V-+ÀPáÞìí&ݱzäØÁ€\Ž8Y¡~ü6=<+Ç®èèäÿ&fa—=|øð!C/^ìïï_žeJ¢4mmm<ضm[šŠGŽ)—ËMw1+Qm~ýúõ̙3_¿~=iÒ$©TZÊyÿxÉ6י_Ðÿ *}È3¡øœ78:xð`œ^?a„E‹qKqž×ÙÙÙÙÙ¹è>:ßa°ó*gWØ5&w ùr¯JµŒ ”ûü0Æ<ÿºo&Ná7OR·ˆI1jóƎ;wî\N›ÍîáUÒ¥iccsøðá6mÚ@I+Žñ¶qqqsæÌ‰‰‰™2e §ÍD¹„ƒtnò*ôȑ#[¶l9uêÔ7nÀÛNÀŒä9ŒŠiüÛx·d").˜ÿÉ6œf÷îݓ'O +[¶¬é7E"‘T*-ÍÒŽ±±9räÈéÓ§W¬Xaìå.9ÓÅÆÆ†‡‡?yòdêÔ©2™ÌØ.¡iZ&“•Η%¿šAÜ_¬H Ñ3á?¥ÐE;!Ž`Á‚:ØÛۗèfŸß4MGGGoÜžqÒ€IÜnYÜ)‰DâëëkiiYjúaªÐݺu[ºtiõêՋ}÷Pã³4ÍÙ³gŸ={6uêT©TÊmT²,MÓ...nnn<¯tòž››{þüynvØ¿j\;}€•@ òLøx…7nœÝŠ+4é̄ÂC7àŸ{m0ŒsÄd2™¯¯¯\./åØÎšÐ§NêܹóŸþ™››[«¹Œ†‡‡ †<ÚìééiÜ=ŽÖƍÿüóÏ\rssµZíg¬œßÿ=ÙU›ð‘ï/é{ù6øô…UyŒ­Ñ£%$$$''“zRtEÌÍÍeæ³ksþÒd&&&F©T–D2ž¯ŽªT*cÆK_›ó?%>>>11±Ôö?1 ·ŸŸÏ/SЌ““yG$z&|’«5:;[[ۜœœääd†aH ý¯`YÖÂÂÂÏÏÏÚÚú3މK“Ši‡œœ…BQ¢‰aY–Ç㕲6˜Yvœ™™™ýyå™3>!"y&§³Ã …BoooŠ¢L?ä@( 4M{yy}^mÎSšr¹ÜÏÏïå˗%Ýã*—ËÝÝÝKS›óCQ”D"±ŽŽüìò Ü6aä¥ y&³B{yyiµZÒÅýo=²D"ùræs¥imm]ÒK±B"‘èój3ׯ6s3K'§_‹MDž D`„Ï\m>°õ BLêãûŽÅÄgžVmÓ·S q©h'y•E‡lKB þS`„d=Ùžfɑ‡Ù.öŒC;VNß}Ggà6!ö!y&„Ï¡ÎðèÄþc,º÷ì7xäԝ=ïîÙò0Kà „ÍFÛøý?¡à? "ρðqꬌk]!8žœ;'ªÝ€‰Tó8⥂eò}ÅøHuʓ«WnŒÎÔ „€UÇ?ŒïQŒž-¥¯þƒ±gð€òù³Ìtg_{©ààë#€ï?Mb*Ûóò-ÁBÖÄÜ86gSª†µ¬ÔlЀ¶êˆýû/ÜÓh‘Wœ^c»7w³€1U&è™@ >ƒÖÀXÃÛ WDQ IÅÀ†ÌÄ{çO B¯X:©‚úzøè‘×R,ÆÌ^¿r| Åµš‡’h3È3@ |²ÛbĈhŠ~Q³ØÝMŽ p‡¬AϊD.µŸ+_¹IçVí<Ó_*±ÔÕUîTւF:–X”PÎmðÃÒÃO&¿ð<3GÅØ hÈ~£Ïmàá@õc0ý–(Â™YÉE(ëÞŸ{;‘çœyr×Z뛩—·rŽ$%è™@ > `ݲIº¶çܝgÊ£ ×%«›4°áSºSót ;¬AÈ MÝûs¿KÏ߯«ÞÝ힆7ønÈ]ŠÆî«GÇw­µç—•ÇÓÛþÐ.ެ-±*DρðI Œ!·Šc†'€¯X~&{]%KŸŠ÷ƒ’·Bsûƒåfddj rG[ M#ÓMÃL:·¹…UðöÆØä/²K'DρP|a B€1–ÚØHMõœ;ÿÞ¥&Gž?M¯$ÚL(!ÈØ3@ø¯J4•%y&@ä™@ "ρ@ ˆ<@ä™@ ‘g@ ˆ<@ òL È3á_@¶zýªVÊ)ùŒÿ2ë*yƒŸÙԓ`Ƴp{(>}úàÁƒ4M“-• ±Ã0ýû÷F} 0Ó°iÓŠ»wï"„J.I–––sçÎýŒG…‡‡'''!õA"‘Ì™3G(’·ƒð©u›ŽòŸ Šë“F?»wïÞž»»ÛØØ°,K,lŠ¢RRRÜžqcøÜŸHàžn0–-[vçαX\rïxLLŒD"YŽh‘¥¥åçUè3fPÔçï ‰D“'OÎÎζŽ$&è™P×Ž;víÚ5tèÐvíÚ³|mÛ¶-X°À`04oÞü3†’Üs†™5kVTTÔÔ©SƒƒƒKô‰©©©Ó§OïׯßÖ­[-,,>WÆ)Šš9sæRŸœ”ŸúÖ?1!6ïÚµkǎ#FŒàŽ™ô¯n4èÓ§Oߟ}çϟúôi.˜+}£µyæÌ™=š6m§Í%š{{û9sæ8;;÷êÕK¡P|–Œs×ëõ_N• i:O !ˆ<>U›÷ìÙ³qãÆ±cǶnݚ;^tÿòì7 RϞ=‡úóÏ?ÿõ×_¥¯ÐFmž={vTTԔ)SªU«%ÜÓÎeÐÁÁaúôé^^^Ý»wW*•ŸK¡?-žÕ!”’’’šššššªR©ÈŒ ÂGC:· o| Ã0\±bÅ̙3›5kftî¡9sæüöÛo…O2òõõ=|øð÷qzŒñ>øá+Š¢Ð¡nݺñxŒ±cÇ®^œºnݺ¥9ŠÒétóçÏ¿{÷î̙3«V­ %? nÌž££ãO?ýŽhѢΝ;ïÝ»×ÂÂâ«kb¥¥ŸÒ³6Ž2ê“-FQÔóçÏ% ž»»sÿ!ˆ<>žššš•+W®[·®råÊyœûå˗»víÚŠM­VkÖœåææ6jÔèŋÞÞÞ_œïCʳ[;ù=]n!F<1Ÿ‡X]®U§išvjÝžª ¿Ø„ªcǎnnnC‡={ö¬]áɲl1Jø®]»ž>}ºbÅ (­jƌ;99M›6móæÍC† Ùµkןþ…5ãÐåÆuZ9î;)¿R¥Õj¹þm™LV:¥O òLø–Q*•ùµ™£|ùòUªT)è·\'žB¡ø"s†F­PefóxªŽ»—ÿºC»6©ßÀU‘¥TëŽÅÕË EQ5k֌‹‹{ùò¥Bš\¹réééy” cÜ®]»7c&d2Yijs…¶µµ ݺu+wp÷îÝÇçñxŠ)ẎoÞŒéååõEUµ<ÚJ£Cž˜ÍR©R%µZÇ,ËöéÓgɒ%Äçˆ<Š ל7ëÜ WfŠð®ï‚z1†÷b”ï—ï~jš¶"‹ÏÁ§Öø…U0_¬~lRÎnTiðŒiÁ¹Ù:‘••z'HŸóy`*÷êÕ+GÅÆÆ2 cŒŒÏç_žpaùòåÅ.“ù‹/ˆÆÍo:ã•ùOä9eüÓxCšŠÕjuttt™2eâãã5jŽnݺœœãOär¹¿¿¿J¥*é™iJ?Xž€d”%MzWóÔŽ–ŸYbcc5 BH hµZ¡PxàÀcǎoCø°C&& äwôÅî.!šK;WöD5øyþ¬®]g\‹ÍFˆ95§ëäÝçÿ˜^Û²ö‚ÜNjú×CmíVvð–ËZ„B¯¯ý±bÆìÓOT!ÍÃÃ^q"2!tméÈé[Ž_Ù×ÕÁR( Yuþ5'ùÏ/niÄçó„"¯ÀŠSÍZXY[J„2‰Ï§xRK%¶’Ëno3`úêÈÄ\®mñxϘvöf1ª“;OÞ}áÈì¡ÔÑœõ‡Ü8óñþ5B¶ ˜ó$‡“%óŠcYöå˗IIIàîîîe‚«««‹‹KéEQõëחËåvvv‰D«Õ5++K$ÙÙÙYYY5oޜ¢(£Œ­\¹R ØÙÙÑ4}üøqãl/„PPP­­­\.7f|(׉‘‘akkkcccšw+++‘HT:!}Öë› ‡Ž_q)+ÜÔ{‡ç„M>p7C}®Ãw•(!õðȪ£Æ·mÞæ$èӞÝxp-JɀA}çJTJ²Ž7v mÛêœý²]¿/èĎkêsà©k£Âš /9ñìqÄöeKï› cx“MÚÇO±eóŸ×c4ÑÇm²ð–Ò‚ìWǗ÷lØ.®áñc{ú—»ß¯qÐÕÈ~prHåáwÛ~ò`·¯úìšÑ‹ÓPý¡œtœxñÂìY–e‹œ DÓŽÙâËÌÌÌÊÊJOOW«Õ×®]3点ôôôœœœØØØäädc’ôzœ^¯OOOgYöΝ;\׈ñnéééYYYW®\1› „PvvvJJJAy4]wT\•?*Äb[±"vóŽ_ÕÙûüíFŒo›ø—­úL¹ñøÙáEìÖQ[oFeåùaCGr³ºŽçW¯_N€ø »ûןØûä“;›€Ïöÿ¶1³àÒϏB¡˜={vQ:¢„wý~Äß"‘èìÙ³ 4øèpC¡P”L,¹ááí  ÃÇiî!U~ùœü Š1€6]£é±!mc? ¯¬šÇço¿¶Ž‚2CŠÌyÑ{mø5U3wD,+Áoœ1ËØ]jvr÷ŏ °“@#—Ë{‚Öž|Ú±?ÊÕiÏÇŒDÖõê7âÙ¬T8Õïáè±kυkÝZTœùåbRóƒËòi3Žúñ‡˜…­°¡e×_óêŽáχ£ésG­-ÿ÷}š»£*ž¢û³ˆ»Ï²Àκ0•åqž–SHHÈæÍ›“’’–.]úûï¿ËîEœ~ýºOŸ>…Ó 40k‡‡:99œß—û†°°°3f˜ÂBd†_·¶¶^Œxñ€I“L$“É>|éÒ%nt±äÝÑÑñý[a$ŽqªÔŸeôžm§ÆŽÅ·"/ŸòŸd t£N~ ÊÁBÀDŒÈɰy¿7ŸµÆØ$#B€ÜÛQç¯:Ú­«SÕÃ#»Z€ÍùØÈXÈ-Š”þ1cƬ\¹œ×¯_Oærˆ<ÿ·Ðh4 6ü”M=¯]»6hРK 2°Þîv®Vœkшz×\?€Š M`ŸX„šŠe]O(°rü Oh„A ð&"Ö³lm'GKÑf1’V]znm׆ƒ<׏uë2ÿÒº‘^R³@ù.èíÞbØù'ý_»¯ÂøÕ•íeÀþÎŅBQM` ‘XÓ§ºsQý®?[ ŠÚôÉޝ;wÎÑÑqüøñãǏ/.ûΛ7/66¶py>uꔱoY¡PŽjՊûùòåýõWnX"‘lÜžqÆ ܩٳg7nÜX§Ó€L&kÖ¬Yjjj“”=oÞŒ‰'šT*•­Zµ2Õìbðb<ÞûFBҊëôñܰfïM?—ˆÄºËÿЉ÷ö<þL„Á×7-Aï'4§°èÝ¿\EŠ¥YÏït­æ’–CZÙw®X±bÔšQuêÔIHH€}ûöE òüâÓ‘’ÝM‚>ŒˆMŒËT€•D_ŸªR €·œZ÷¯A 8òy*„J­.7 !B0Ma)ñWHÄo~Ë҈áRÎ"\B€×wCo⁏OnìØ|bóàšF›ÛÛaTµÓLßu=Â†Ž¹c¹¹K K Àp·å®b„²b­"ËÊ#hÿ­ûíMƒDø’÷Àß»wïÞœ{ÜÔzNW¯kúŸh IDAT^=Óð÷òåË<ašŠ§‚ƒƒÃž?Îãñ4MÙ²eår9w*%%%""B¯×s;{Á¯@r÷Jß·h}xáñU\på­ü… ž;~òdIýaé7'X^_Øâ˜!VÀœ636ö8e7€Ñäd8Vš·ÿï‹uåSúr¹|ʔ)ÄMˆ<>Õ§¯ä`dQ®OPÈÀ•‹&rËv®ß÷8SBQˆ;ËÉ+Bȶ|óÞxΐék+-îÀ<9ŒuŞ@¿ !ˆ×Ó/ŸÆënܬüì¯ÉSö>4tŠ0H%·ç.ÞáãÖ·µïõµCŽñ«l[ «žîÚñO¥fµ-¬+R¢§"ñû‰ÁïÅXöµÇ¹û =~Ú/«SƖ[-¶¡ÿ5í×rK óÇßqùþ—¶åŽl»yXÓ9»ôµ×¥Šh(7ÿŠ®ôAÓ)Š<3·¹ÝµJ¡øžÀ[,gö²ºuëæÿ!ÆØÕÕÕÕÕÕ쩐³Çóä!€ÑhX–5¹mmm]Z¢Ž0Ûךë?uÓÉ«¥“»[€FŃ.;#6&ò€]ñ™©©©9zŒÃÀ(çΞ¹’uaU×ñÛåeG²²*­B Õ~ñæmÝ­rÒX©—o £}°,ŽZ­Z­Š(ªoߟYYYB¡P©T'C( dj!omv_ƬK)ü,Æè&+6<f}ò‰ÃO{6϶³€±ÜÑFÊu#M¥5Oÿð`T§Wµöó“o;pŽ'À£~Ûæ üö iXkÙËÐÁãÖ-C`=¶¬kshbç¿n n®ýû`CGšeµWÆüRÎ/°éМfîSÞ€ŸË¬œœ­ìy&-ªÉô–2kÁ”îu]-ßtüb„µÿkWÝË7$üÏÜ]—÷R`]±éÚ§¿6° «QÖß7°êÏ+·æ k³œœœ“““« ;wöõõ-â+šhò7õ"žÊ£ÍÆÑhŒ±ƒƒÃŽ;d2™iÞ%Ijjj©LÞ„1åT³Ýêõ+ût¬g`_}XV™g–Tñ«ô¬yËþõìæt »›)Žu²•rýÜm-‘Ÿ˜Z§~«ÖS7-h*ÑRàRÿ‡÷VVÐN öóó«º`ó~eXVVVr¹œ›«ïèèèêêjkk;dȐ2eÊoC(J&;¶ |ú%ïÞœ;dȐݻwçßÚ¢iө͛7ïØ±#7™¥RYµjÕ{÷îtÿÜø”LY9Ê% ?9Û·Ïé®gŽÌªä$CŠêòne†7ƒÓ…u!íî3ßoџ³:Yœ«ç—­<‹}MozqIÅ.áÕ÷__R7À 0b6ÕâméûèêÀÓèÐtÙÔÛví»Û×?~üžmÛ¶ .ä>Ädggg6ñÅ»oÔúõë/]ºŽtéRGGG(ŝIŒR(܇ÎV¯^mkk[±błÒPŒÉãñxjµšÏçú”‚×?›¬Ÿ7)qxåô»ºó¶‚™¯™2™lߟ}R©*V¬h(ÑÒ'|“Îm‚‚‚FŽÙ¥K—å˗שSÇTϪT©2sæÌ°°°B\j¹råL»póóhєþGïzŽnæµ÷ØÕÀ_ºøÙJMöà<ÝÛgRï4¡w#&¹Ÿv1d*ôV|ãI€ŒsåÙBäÍÿ4Âò†w(ïe à¿v¡VŸŸ$Ó0‘2¹õ{I:sæÌ°aÃlmm oçÃ$ÏÅë{÷îýüùó!C†Ì›7/00°tŸki|DzzúòåË<žpáBnœ[¯×gggsvø·Ý-Å|Œ÷”|ÝðF6±•I?ä9øöO”§ô !''§ y&ÚL Ñ3‰žÿ…ŸÅoÛ¶m˖-áááõëׇ·+d(ŠJKKËÈÈ(|_-­V[@ôŒNöøŸ»žÄ)°epýfÕŒeŸE%Åü“N^öÞG:;V™ðàaªcÙ²öV"êMSÇFEdËÊyZý+‰:qâÄ€I“zöìY«V-ã—Ÿ<==Kar. zœ~ʔ)qqq3fÌ(W®”ü«LµùðáÃóçϗËåzœclaaáëë[<sQ@ôüY0žœŒŒ<==‰w"è™ðIqçmûôéÃ0̬Y³~þùgã2YŒ±]AQ Y—¿(ÛU¬Ñžb^\tu'ßJNŸp+Œ1’¹T uy{¿7fð(ZÄ{¯9zôhXXX·n݌ڌ*‰íG )>>Ÿ?þüɓ'ϙ3gúôéå˗/Ñš»mFFÆÒ¥K;fÔfÓ]ÆÈ›E |4€ƒ…W¡ йsçùóçŸ={–;^t?[ô‰HŸìŸ‘ùÎêO¹Å{œ›Eº'wÍ¡C‡æÌ™ÓŸ}{n"ŽQ›E"‘••UiŸÏ_žp¡££cxxøƒJZ#333,Xpâĉyóæ™j3EQ¥3Œ3ø:“F Dτ’UèÁƒóxŒµk×Þ¹s‡û0"1Žùæ-E%''Ÿ9sŠuëÖܺa.bfYV,—)SF.——Ú,-£B/^Œ8,,lÑ¢EÁÁÁ\/k ‰bddä;wæÌ™cªÍ!OOO¡PX:ygYöÿû·WšñÓ Ÿ±XLÖMˆ<J<†¶µµÝžq£R©4Ýu™_ºví¢×ë9mfF"‘øúúrÃ¥i:Ó^î%K–œ@ä™PüŽë)õôô€iºD»I¿ž)Qnnn¶¶¶ŸQ›ó7Îíž]¢“H$¥¬Íf“!—Ë¿UÅ¥69Ž@ä™ðUh@àîî^Жa£<Ó4-‹¿mΣÐÞÞÞ%œÙ5ŸÿöÎ:.Š­ãϙm:•.APD±»óªš×kw{- Ôk`abc{íîŒêµ»;° i©]¶gæŒ ®+,êUJßóýƒ;³;sΙç<¿óœP(,öŒÛÚښ››—n2M òL(Ššøšo×é’3 À=>‘HT /–.Éçî. …B!1‘gÂÿ‹B“Bøy‹«X†KT6s6œ%Ù¿ëôí7¥Ë7í×§}kIh'©;„ï†lKB ~m0BäñÇ·/Ûq3®|õÊIOOLX},2M"“·Dž ¡xÔÞ?ŸuúZjV‡ Ÿ6š‰ñóSw^Fi£müùç\gI¡ˆ<«³*"6.ÓÔ±zr€KåZvªgï’€ÈóúQœ÷DÊ¢¯œ=ý8*ÌdD?»yóYªœ5øBt¡À!cÏáW€úCbJeábo!0²w53»“’¥ ­…¹} B0+œ8èÏÐ$…FhçÕšÿØã[0+e æþ#nj­ç"Êû^qDρð_`Y–¡Œ1›óYH¡Ž4©F£5p³Ìë·§»õÚ~d{ßrêÃóF/Ý>yÝñͳÇÖ1R^?D› Dž á‡ýñD<âç,¹B,ƒ,ÄÃK°0Ã2–u:[¹¶ê?± “’¡dEFv¥m¬L5*%)Q‘g@øaDÖÎvnÚø¬ÈD€âÝ»ìT[{k1ï“$ãOÿ!Ÿ€—¶ïTŒ2óù…=77qÜ㥓'nÞpääÍWŠI‰ˆ<1€š’… ðøâ±3±òÖ¶Ýá/Ýêz—³Àuã~¹.:S…}fNŸ€ñû²B<~…îÁíKíÔŒÓÊK;n_]»vmkkk–eI ÿDðxŒžžž[·n5mÚŠû=ÜݕJåøñã5MÕªU…Ba!y–eŸœÇãM™2E§Í…Îê2hgg7qâIJeËvëÖíçTèOé-š”'%%%%%%''ËårÒËýS@:· 9~M«ÕîÝ»wíÚµaaauêÔѹQ„Ðĉ·lÙòå9bžžž×¯_/™ïªÇ—¬~=A?šd]ovǎAïÞœwïÞ]³fMŠ¢ŠÒš E`` Ã03gÎtww‡Â×eÜÎÎn„ ¡¡¡ÝºuÛœ{·™™ÙO×ÄJ|ÿVKÙ»8˜Èå"##¹ÜÜ܌‰Ó#òLøi_µjՁÜÜÜr¹Ñ'OžwêÔI­V¬ùÙÙÙþþþoÞŒ)[¶lIèÈxv`ԟƒÿyNYÚ¹_žsb;ßç{AýàâÖ¿fZ˜‰)Ÿ1Ÿb­ŠÅÙIŠê=ÿìØØ×Œ_7áJ£M›6nnn¯_¿‰D_í)@ _Žh‘‘‘ÑŒ3¬­­¡šfšé+ô̙3W­Z5nÜž7~õî%¬q‰ÎÕj2vìþŽ :r9­V E}A›KfóúÿÒ¹MÈA©TÊåòŒÚÌáàààèèèawwwwww®³$Ÿ*þœcíþ‡l†oÚ²ºKK¯UŸ•Èòƈ‡)1ÅJè€k{×oŒrÿƒ@, x<> ÊCrBEQ”ŸŸ_RRRLL 0 caa!ÉŸÏ5jTÁ†×)))¶¶¶E©Íússs×¯_sCCC)ŠÊ›w±Xœ––VҔ‰ñJòbQÁ‹B¡°··Ï[<oƌD›IôL(¡p•Ó ýòwö u;¿ŸZŒsI@y/­û©~Úòs÷Šø·J¥æüöyMM™v­;Lg‘¡庰$åºWÞ/ç—C™Í{‹_³É #HõÜ#êÃ%ÿ£g ôU«Ž±ˆúöRýZªt¡$EQÑÑÑb±ØÉÉI*•j4…B¡ûšX,Þ¶mÛ±cNJÀšr¥P÷1oy~Ç)ÝG]Æy<^vvöÛ·oœŒŒ'Mš4gΜììlÝOÌÌÌLMM†)üžøÜ¢Ÿ2~D”(Ÿ\ÿW›ÔïáDZ*•r…CÓŽ‘‘Ñ… ߟ}K| ‰ž ?Hp€ˆÙ¹°6Þ¶¡:ŠýÕŠÍÄkï2bNNm;rÓ©]ã«ð՞j“öhf·ê!±µsïUçd!„â®í]0qòɗr„2|ÿñ¡Ç%!„®Ï8vÕރ¡Ý¬L•[pò-« ѯӁâ E‰ DG_YÚ¶BÈŽUß%Y€BHúï¢&Ö¡úSB&ÿöÛÄÛ Ùiþ6~ÏK„Kkí×ð¯!„˜äG;ºWFÕn3åY „^\:gޒÃ{—7ò·CšôèUç3U,BáÄý³ûI„ŠBBáÈ·!`±—FÕG‰<+õœžÀR<ŸP$PÀ§XBJ$ŠÎÏïÖeÒºÈ4%7ðom¯f£)pöÁa-Fm>¹=š.B”­K»CϹ²¡ß]]P!dÒ¢÷¢·Yœ,åû@£££cbb(Šâóùfz…B‰DR4F…rwwB¡Çãé"]„Ptt4BH("„:uê€jÜžqºS7nÜÐ?eii) …B¡™™™þ,0ÝMBR©422233ÓÈȈ¢(ýŒ@‘ É#„PÒóSÁþX}={ž1׎ž8õìkYúÃCu*ž „ª8iëM¹†Íi¬ršJ§ïù³Õôãq!&;éÄÚ ®‹® „ÒŸúwV3O„Ùï#×ÅÈ <ýüž…™™™T*ݵk—™™ŸÏ—H$d:7‘gB¡7Ñ¿ƒÂvLÌé¡}{‰ï8ûZlÌr|hÏ©S“dZž"æêúAmzIû^ŒŒ¡”òÅ›*K/·ž÷þæ®±±Áš7? tF죷_ËY`Ñ/ï¿Mÿ Zþdߘîïzn;sõï!“Û–Ýù"Ë¢B«!X;žs§Ùb³0B€£NlêÛ< Ožÿj¿iÄŸ©³7)Î÷èÚwúsØWsd[7Ÿ>}5ENð>Œ:{6Y€™¬Äûo§@ʃƒªFôŸðîlÞõÀ‘s3øtܙ%ãÿŠÉ”»&ÛlµñÎëL€ì%ºM¿ràZTôËÓÇ;šbP¥=åÚì@ÝÃñ‰‡ÖùЯýИÏú >EÕª:ß^œöܳ šŽÝS©‘¿¡¬÷çV ú}$îûÚɁ>†Ž©yG g·õkº”ºÿú å»ƒ“g®O‡¯ôGGGç5•7¡ÿdTZ­–Ši­V˲ìÕ«WušÊýåFIâããu§žè–;uçÎ¥R©;¥ýˆJ¥ºwïžÁö%B(###==]syÞ1XXÚó?Äî^ž_ Œf÷±[ñާ»éûXÅÈ9›"’“ÿ™ŸœŒÿö— ŠÏSÅ&œ<{!M ˜Q¥Ÿ{ôâ± ^îXÖ»óÞR³ïÇ=ÛŠžþ÷ì°}YðFFbbbˆÏ$Û„ÂE$]Œx±qãÆßݰ—ÉdÞÞޅ•ŸìðM‘Ï«O;j@=!,Ÿ±~Ÿç"K€:]CÚ®ø»·pâ•%˄ŠûîÍ­æ`?pêÂ7ݗͿ.ïàÆGFzZ„\ËR*M°âÝâ?]ÍPgûùÍÞÎŒé5¶ú:m\µic‡Lïr6ÌnÁþ‡Ã›ˆïŸŸñÌÝn]y'‰±Ióû©ÑɉO×Äœn8uV߀*¥°òîÆœKølN§µ~Û‰Ô¯^^ÔÞyǶ3÷:×+“Ÿgé}MßuÍ]hT2ͺ(V€u[¶âfՑ;O?k›|ó‘[éõœ%F™~e,n'œ~/+Ó¯q©Õj±X¬Óª€€€Q£FÅÄÄ̞=ûôéÓB¡°ÚþÅmòž%|y¹u떓““ÁSAAAAAAß×÷cii9f̘°°0]ޓ’’ÄbñÁƒ=ÊɁDÊ®®®y© v(S1 îʕû.' kšyáíª^·?<„zûÒj R%b!܍–©ªI®[ë‡UH ~5âN\YÇ)ž¥-x•\EQ ‘Ér07þzÚ`ðàÁ7n-[¶jß Èóÿ5*•ªY³f¡¡¡ß}…{÷îõëׯÐâg cw³RƜÛgµºø‚ÅlcÿòbŒ1`Ÿ‘…|Ý8?DñÄ 鯢?þ‡±#÷?Íâz¥-9™e1PÜž#ßiðüݝץå_}›”œsÏÒÌ,óÍÝ^ <0Z­U÷ÉL„Œ–u-cnk,šù,æA9ž c#@‰ÄÆÚ”È!MŒ‡£ÕšÿÖªµ€RºŒ—·“-hÔ2–5…Š(3S!Öq Å ÍžØÆï/`Æšrãv’|B,ä¹vˆsƒ±§ßö¯ž{Ôá¡gʉùОŽuNNðy<±ÄTq¿wNŸ,»Œïj!øŠ.‘H”+ÈÛ±c‡››ÛŽiÓŠM›VP=000!!!ïq®qÀ²ìå˗¹5{¡„„„öíÛK$FÓžqã°°0¹\Î}?44tǎ"‘H©T®_¿ŸZµj\<-‹›6mʍ%Ë^¡˗/_Ÿ|y®êÓµk×áÇRþÇb„ÌT«ÕÊâôöãwDé·h‹R­{W€×þî6|úã7~âdà'úRƒÂX Pc³äG‡»Ôõ@Àjµ6Bʚ~ÛÓ€ 6 >|РA<î/È3¡ä¡ÜD«ÕâŠŒÑ»šš·‰©Ž‰%ýäìÅl)ä,€f•9뵍œÏ<Å5|håòô„Œ<À,f0ÐÀ»È+,K‰y€(€VkÔZ@­V±Ti3>ÖªT,_,⛔i2~Åê ­ŒMwSHýšîŸtŸž.‘Þããˆ7)ñJ0‘@Ê»hZK Œ¬¡«’&<}šg;ӊlkGß÷³ÿ”­‡°FËҌŸ¬66í}†švá (šŠÑj•DdŸ!<³§§~GêG®Ó„P•^‹=—wês÷ŠŒìñÎUø<ˆeÎÜx¬VjŠoe„4qYNŸv]¹ÔÀZ¿{ö+1€ÁÓEø0Ã0§Ÿzõ*<<œ U•Je­ZµôÏÞ»wÏçkµZ@PœzuîøÖ­[çϟŸÀMõ*W®œ.àKIIyüø1—xFó_US—Ô¯€ÙøÔmX§ÖÂ9ƒß8Øû5P߁‚ô«ƒÆL©òçê{c»jλ¶»™·&³ h(²ôÈ71øX­4ëλN¬nþžþ§~]'DQ.ˆ'y&|¯’ô €LÊ ¬ÑhÈü5S™ÚsâU]¢`–epŽßŽöm3ÄláØ© ŒCÚ3oOmZ{²ZåMÕÄðÄ.œuzkþ‚ÞjºDŒJIÍ]ºÑɺÇoîwþtɺþ™v_ÿ³hK€KûŠåÌèŽÛö¹yzÔ®æâ€ šñldàï3…ýa*‹Ï6rªYÕ³]¹Šö®àeߘz3têŒ,uYDQ,[Þü÷øÙŠéwŽ˜ŒÓ¬To@TŸêïâwj>~ÕÖ>¶šÔL0ñ«S“˜Å,Öó¡ZFƒZ/ð-?dÐ áŒÖÞŠ‘/ª÷èìäßq,ñšZŽrd©\«5õ2Ë) 0Αh„1 ›úSÝ=\ŸƒvÔ±Q@hWFo-\Í^¶gÑÌd¿€þÍʉÄmk?>ºýôÅ+:›e'ÈÄ¥ÊûUΗçÛLÓtbbb®™Û‰‰‰EcTܘq… òžåþÑIr®SööööööOùûûçwµ\ڜšššœœ¬?sÛÜÜü«¢^P1 ‰SýêU7…n{`S6šskhh+~æ»×·îœ??a¶Fûæe‚º‚5f6§Á„±ÆøìÉם=ÿ];báÉRµÆk¬šÕ8Ÿÿ…À aŒj0oõ‘û6¬Ù^}îÞvOÚô¹Ê",Ü|=lŒX”_~BØ­M@ƒ¥ÕÛF ÉWV4Ù3!æfo—¯€Jï2Ü]†¹zõêСCW­ZÅíV¹råü6¹,ð]Ã"##§L™âââEž3‰îFIII+V¬xùòåÔ©S¥R©]ùò勊ß(¿Ÿ?¿Ë××?绌žÅ€Ÿôôs©ò… ž*W®lbbROŸ@¢gBÁàëë;f̘áÇOŸ>œuëÖú ݰaÿÿþ{Æ _ð"µk×þò¬×è­Ë‡Ÿž_ªIC›—Ç.GX.ëêie z‘ „ ÊBùnja€öV±™M›™ðuâ €¢„”Þ5 )(õYD.ðö)%Rã×Ï~’ïòDrrò1 †òf8„ì+®ºö]ý»‹…0”‘Ê[ÊdCžßçwYÝkNvîÜ2yòdÝ|쌌Œüä¹`œs``à€I“&Nœ8mÚ4__ߢy¯¥îÜDôˆˆˆ)SŠ( nc;™LfjjšŸ EHôÙ]òÇf'Œz+u(çe.æ¡ÍŸóLeêéioüícŒyóæ¥K—–/_žeY›[že?…%“Z­v„ )))S§Nõõõ-ì:—6GFFNž<ÙØØX«ÕbŒÍÍÍœŒŒò“ç—á’ã]uÑ3EQù­X#è™Pòši[è]»ve&,,ŒeÙöíÛëÚöææææææßîó¶" oÿzÞþ_ýò·ûa°uñ±-€KÆ$¥|ýJ}üPœ³d0Ɣ‰CùÊzÁƘr*[ésªÓæ¿ÿþ{ݺu#FŒÐ׿"ëÀäÒ -Z4a„¹sçr ]x1Žî²±±±³fÍz÷îN›¹ŒsÁ(©ï„ŸҕAÈÝØïÑ£G¿~ýV¯^}øðaøž‹Å·_äۏÿ˜£D¹ö‰„Œ*æ‘çÓ§cߒ8î;kÖ¬ÙžqãÀýüüôµÙÔÔÔ¢(J ,^ŒžtéÒ³fÍzñâZ72wÙžžžàààžžžI“&ék3ŸÏ·°°‹Å€²HôLøYcè^œz …ÂÝ»w_œzÕÚښŒ€ü\ðxŒÄÄÄׯ_÷ë×O_›†133óôô455-²YZœQñùüÐÐÐyóæ…„„”)Sæ«ïµünX–}óæZ­?~ŒŸ6óxB@+ãÃï^Ÿö$UΔš7p 2öL E EB‡X#‹úVÆG#£WÑÉJ c&ÈýÎq„°Úäðcý†/—#Ä·/ßzàÐ*Šó¡[.›Šùö Ǐ^ÃI„ó ;Dρ@ø/4Æ3¬n?l†OAZº”Š /6c4Š—çKêO<þïîå{ŠØ}3{ñ®Ó‡–Môg²\~ D›‰<áGá )JÄRŒ˜ Ý\¬…Â|:51 À¢J 犝‡ÕGÙ Ë2€Ì̌MÄ,£%%Jä™@ ?9€ØÎ³ŽSVô‡˜%@ú«…ÔÉÉV"€0CÓ4ƒ1À,CÓ ‹…ø•¶ÿ从ػç‡KŒáõõåÓ'­\¶ïJD¢e9;RªDž ðC Œĵëù—‘Þ8êÂyÊ?+·œÿP£±« ./ÜfԖT5 <6µkÀÄÃZJdZ¥ÇøfGzvz2¶ÜþKçMÄquÏùžºÝ;Ô°ÏQ}¯™F E¯Ïc0«ÐnаŒkVv>€a™Š—¯ânŒš+0 X-ÑŒ$–Ÿ£6œõ1·ªßkÃù^ÀÍÓýF~¹6ioý ì % BáóqoMš‘Ê•Ææ&<È­²Ÿ6Ã#7ãüüÙ¥“Dρ@(ÀÆñyfæ&UöÓîøÇϟ"Qó¯ {&„b•h *K òL ‘g@ Dž @ òL È3@ Dž @ y&@ä™@ "τŸ²Õ+á§6›¢OI1æ]÷ŸhÂ/VÂdSO‚GÃm^ŽuëÖ5kÖðùÄH_ÁËËkÛ¶m¡’°÷³. Ϟ=8p Ç+€$aŒiš^Ÿ|yݺu‹1ïEíÝ»7,, ȶc…@˖-g̘Aä™PRŽ™a˜å˗߾qc̘1666 В!äMÓׯ_ïСömÛÌÍ͋W¡uw¿páÂ̙3èááAÓt¡xO>?66vÚŽi:t(F…Ÿs玃ƒC`` B¡ Y€Ï÷Ν;G%òL(AÚŒlÙ²sçÎ͙3§zõê€X_¥f͚K–,éÚµëþýûÍÌ̊K¥t÷œtéÒØ±cCBB:tèPØ7utt Fµoߟžc\©R¥† S,XD"ÑÑ£G‹ëîd왐[›W®\yêÔ©yóæqÚLÆ¡ _6(UªTPPP¥J•ºté"•J9•*.mŸvíڟþ9oÞ22öLÈáéÓ§k×®œp႕•U.×¹~ýúîÝ»«Õjƒ¿•Édnnn/^Œ(_Ÿ| ˜.‘ßà‹BwëØ‘›ï+ÿÞ¯Ÿ‡qþýßxÁÂö 앥A—ûNéXQÀ£~èJŽ>pÎ}Œ$!J`J1RšeiLa›sfÔ².•BÙÚÚΛ7/44tòäÉk×®ýj`!cŒnߟíááQ”O—÷úõëߺu«zõꑑ‘ÆÆÆßÒ_UÄ&%{œ«N‹Ðû>ȐšcC&Žœqâ­uZr§±s§LæÂûŠËf‡?œ×jpìÎ+g[ÙMo4þ­w·5‰3³ñŠÀ˰,Ë0 BH"‘å%Ñ3!FCÓt^mæ066‹ÅæùE>Á!„¢¯=pé¥RÃ|cݐ¿ŒwþÔÙðLügûò̞7bJ@DÅú{ï“L¬ºD&öVV––VVُ–†® 7+eceeiim&p)‘Hìììbbbž 2((ˆëƒÑ!„’Ëå[Èiiieʔ)úùYºŒ;;;Ëd²èèh®ñx<*¡Ÿ}ûeòtœ#˜g¢WÏOÐäÑ7Ÿßäî»-Yš¶jÚgÑ7_߄±ôS—gù÷òÜÉÓOã² 5ƒžªŒš„*ÊàÒÈÈhûöí"‘È %GEEF~IôL(’výgîîdð{ù}Á‹Ÿ£ºÿ±<®VYÉÇ#_Lx÷Ÿ}¬?äãÁ1BwÚöî¿è6®ëšOiä›È/'8¿‚Í÷8@÷ëÙÝ?ŠÜ@bó/¬<ß.ÕcÒì¡çηew˜<€sÛº®øÚªÙŒ·Ë•r.R%“É"""ʖ-›šššß…ދŅ4Ÿ Ÿª/<…üN}ÇOôóŽЉ‰166vssã¯\ß·oßæÍ›‹Ž2#DÓ4ŸÏ—P>!@ò],Mx€€O}Á¬ X,•SóÒÿ95oåÙj{ë-r†ü«2hÌyæXh^«€…Ÿjóÿɛ|Åï!„222FµbŊ\ÔÉÉI«ÕJóœšÁ@7WÁºˆï•~më '+„B->LbBŠšu£~ãó(„ÿа72„R€Eü= Åä-ǖŒš‡*_ûÏk1*„"éÙüõ¹ß]º'AÚ奁ª fñŽFFü¡ëî2Hq °þ€•Wõ›5|®TíœÒ!„QÿQ¢dAô™“ÇÿuâM6BèÁº ç¬8°iº«B¶An𢠯ðçñ&~gš4B(êÌŠ cÖl mS³B¥ƒÖœ{}k{EÏÒ¡^sH•4Bèö扜¿šožù!”ôbõ€–£WmšÜÉ !Ê·Áš+Ñr„ÐËý ÿšŒbñž^ŠYô™{$UN#€ÇŽì¿ñŠ–ÁeïPoÔÆÓûæt@Y–n~ài&B±Ê'g·ðD¹5k9žOßÑËvÞÔ $‹Œ2²’—1B¡ÙÇ).!Žj)ÄYòkŽÜΝýðì䀑CVž‹‰>±|Òä©a‹ÇÕ,kАEïهS²µ!”µž§©€*·ærBˆ{Œy!”••%•J)ŠÊ)5ô)EcÀ¡£Gêî;sæLýÖ©SGw*%%E'Ž*•JwÜÛÛ[ÿ'k׮՝Z¿~}®{éþ‰‰‰ábèŒ/²ž9GÚd/C»JDBBí–ÿóÏ³ÀÚÔ'û{UE œ« Œ‘€pœISfî>ºeÃߖݧ>ù€’nl¯TÆ!„P¹ñ›n(Ž,BšCCŒÜñ!ÄÒª{[†×{ >6‰)ŸÒÃ7ߨyù՝Íþöm:¹§É§úhm4`åÁÍãë#„$ÆuþŸ‘€ReÄ.Ñ!„™“àÛïå!„3ïì™WÉÍ!„P£íWcuwDìٌ6~M§d¢ÕY{göD!$qöüï›L„b²ïîUÛ!äÓ©Û°Žn;ó\ƒÒ$nåa!A¹Î;ò\Ëü‡˜!Žcǎ§OŸö%òüëÀ­¬P|F­VsnŽàÝ%€öXÿ~ô_\wøšˆÄ÷n̬VƜ íË _eÿï³øäwWêÞëm’ @&!ü܂Áî Ÿyn™OÊÑy“®À¹Å¡‡ãJ¯z›ðêÉÈME,X×é4HlT¡Oÿ¿oßÓއ”<æú–ÀîSÍ&ß»¹ÑF›ijW÷jtêûðMÄÛgŽžtfì«woâU€~wbþè.‹"Æo=·'H²tÈŠgIJÇfýGòP¥ ‰;?P¿fs›z{{؈%תO;ž÷¯ªF·ð©³ehè‘‹Êî^}3!@!³=ù$:íCDXïóÛV ¬ŽtvÅô·¯||v‹oúÆqÃ"„8ñúÚ¹£€õ\ùìÒΧƒ;.9~K }wónŠ’@Ù)7V n7üIœ[÷OöŸ2æ÷C,@äémƒÚÎ×ÔØû^v}pyىí»Þ&ȅÀn<æ–W×s1 Qïþ^Ջò<$1vuwd„„Ed^<~ä҃Ìjµ]Aw}ÝŒ1‡?t_{ùì².g§ÿ±øøm²æ:–Ÿ œý,5ýöŽ#7»œ_诠(*===++‹Çã€T*•Éd2™L*•ê,VQ 4`}ïùúõëØØX…B!“Ér:{ölff&—ÂììlÝq…BñðáC¥R)“ÉX–Õh4ºS/_ŸÔå%ïMcbrÆGô3ÎuøsÃ@•k®$óæ»yš}¥ÉᣯœM|w¯ïœi[)>…H£¯ñïq¿ÓŌŽÇœüâ†vg_}øˆ }šŽ±oéÂ@oKm|š¹þh’Lúï|é’A;ß~Pð2£®]IS`V–òìÕÃOÙÇ V^ÍË×oèVîÏœÿ._:ÑۖÊS}žÈ“RŠßØØuÓïÑ£›sÚe¶ô= @kÝ|nÇ¥GÝžåšžeéÌÇpvôˆ?zÌôíµðuBü£ÛóëU°Ì‰tE„âfÔ©4ïB§-³ÛP€YV-¶šr)"9áõŸö¥wMém Ðk¿sç“IÒ›Soÿ=|4æƒJô:ÿš>ëöODZøñ>Ó:¶=§ú–®ÁlߟýΝ;…=œ”tnÿ"…Âëׯ·lÙò»©TêééYXéËz²#î¹÷è3Æts1°sˆ>9CÍ.ŸÚŒŒ-€ý²ÝÖø :ùfrPšˆÊMÚoN}øðŒZ­c'•ÐÂÌÜ,!õÍåÛáõ:Ôõ±2PB—ÊõEçÜ}*ùWµ€Z-Ñž£™‹Úp£í°?3²²Ò’A“*ñËLø !dŒ7oG«VÈjö;¶>¬—Yîg±âtŒTQÝŸBõÆðØ¥’ŸŸŠ5©w/?Qòy0ƒ$&Î^U Êö£KP#0ê»'më –f4kµeëÍ$èõèÕÍšj Nmîê(†®KB®%ð5 )¶°±zùúÙõ‡ÑœTr±0Êob™ÀÔºz»þ;çí¿,â~ýB€œÿØÚ&ðüCvfãÞÛç­ííc M ÝvîŸë±cýafH#WeÄ{±{Õò°âQŽŒ‘¥ñ—í !daa1xðà7ŠÅbP©TR©T >|xÿþýèãÜÜÜŸü…ýû÷ޙé¯Vôoñ×kÅ ÀPb0rDFfVz,ñ”ü2\~û YкŽ†n_|2nеu+L%ëPßUð>‘çè_‰šó$:£«ø+cc"‘èùóç ž{÷î… ®\¹²e˖BŠjˆ<ÿ:šÕêf͚͟?ÿ»¯ððáÃÞœ{Vúx%’?·‰€eL, +²àó(À,6ƒ:uÊ€F«Òš4<0ŠO MŸ0gXkש5G/Z6³{m !(Lc-Ë0<®£µ¡o`åi¯ÃŠŽžºá“œ›±Ø¶”%%Ðïo ¥Œ¥²ŽŠP*2Xl*D<FAƒ¹ «Ó^†µ 8ej$`i­e¹ÚWîóŽ1,ëagíamZeëgcf! ÅH€( gXÔsöAcaÅòÞ&Š`3¿š… 04Í ñ(DcìkfdÍçfíh–åór×tBdа³?0ŒV¥”QÈS€ÀÚT ¶€F¥ÑhXðúl]“Ômèª.uÿ*Ýjé֕Õñ Ž Ý}ëWTힾ·v`Zx4ÛcUKÐ`ìkfdó1=4‹ù<$ŠŒ$Æ;‚ûà# <×6ž–ßä@ÒÓÓ7lذaÃýƒZ­¶gϞ (ìqÝÚ?¥R9dȐ¡C‡r°©©éðáÃïÞœKQ”B¡8zôhéÒ¥uiûí·ßž‘c77·]»vq?‹ÅGŽ™3gŽX,–Ëåß2|.r}gïÞœuëÖݵk—îHHHH:uš5köÝŸ0aB||ŒÁž+.ën.äFfå %W…B (ÒŠ÷i ØÕm7ÜA £dX%ÍõæÞáå}&.ŠwšRQªgú,*GˆÂ,x8W¯ ÍjU,˲Ü)ª›KçÍÞýo’DÄÐ*³ëÍ8ºwLKsl͹zJkµ,!3 \žû»k)Fc[|Ÿ˜â‰$B@Ÿ+ ÄIül݄[YÐnekGƒ!Àª¬ÈÕÁ£Ç¯¹éPÚÓÒÌÚÈ !(m!t0ãZ>*…–Šð…&Æfǖ]X-À|놞V’o)g•Jåëë{çΝîÝ»÷èÑ# sJ,‘ç_gÀø· R©T…×  ›S8&:55Míâ$¢5*, °d_Üz•ÚÎÛBŒèÔw÷µ0R0K+ÔúÐØŠ×²]œ–­Zլᚰ­-ê”oíeΰÉïe*VÏA(Ԁiõ« kŠîxr_“VU¹€g¿]rM^çÅšÔlÎÄh€1`DñÙÄ) @elßpŸVe0O¬–fµtÎQfÕøÓP;%P„oë2yËÞHmWþݐ¶uÃi€X–ÎL˰PgI³b±•1#€Ê–gÉTb€¬t.m)Î;;‡–«ô\!àIxrEƒ»€ö>ì›+_<‹«TÍšy_žˆc&ºú[z€Sµ@gsÑ獄‘gÃþ÷Ú/ÄߥAώåE@QH•%Sˆ€éJ¶Ž…!0’fußòfI7/]”ipÎÚç# ˜ëÜ΋V«‰DebWcŒ›7o.•J_ŒxÁçó …¥¥e©R¥ž³§NŠÍÎÎæzüüüt?LNNçñx ÃÐ4­;5qâÄQ£FEDD™Lö•ŽÏççrè4Më÷™Z­ÖðšÄ3Æ/¯œMmåeJ©2? §(>°4miTz區žå>}WÉâOÁ”+ƒ‚BšM9°rðoÆžt}ŠÀ¬–•c€•&œžýä¿Ô°<¡<È¥Êô 5€ Ææœ6ìµÉÀ@ÅijºŠÆb>ÈÓ3Hìh¢º~4lŕ̗l²Ï‡{ã;y®¥ÂÙ±RRTeÜÄŽFÍòB%’7œup¬ÉžŽƒŽ\X8 ‰)ŽŸº~üšk7åÒÚŒøõýz,‹Ñ ˜ð3>D§§z; =néâVmpùK+ kš³­«f­j»fÇ_™5t[ ãÖìè\Ó~?}AŽ€Íô5Óv«A(‘Ìm<Р.êŠÑ4]¹råS§N={6—EU«V-¿šúG„9¯çmk~õÔwüD?ïºSUªTéÕ«W®ŒcŒ{ôèQ=jr™{|ó“nA+gߢDýϝß8å¯ç "» 3ß5›Ðmt•æí}[Žá9Vš^ÙÎÍÀ®Ñ”‘œCÖ{Š»dúø­[ö…ìéÖ©êo¡«êœ5{úyó^s­¿œê¹ ð-œªÖe¬`ëÛ¶ãØ·Ó¬^¿Ýbڄ‘ù( £Å–m<¬šŸAÍXÙûìügµ«,šránØ_c«6®;bõ”ý¡—n¹2vÚFgfÚâ=“ÇíÕªýÃêŽ(å×°š»©FƒëMŒ{€2qãÔÇŽ®_wÀô®gVÏ r.ëÕoﲂ·oYr~ˊ~Û_ûlY¹%ƪçŒ%íƒ'Ò£h²õОúݧ®›wb BÏšÑý«ŸÑËËkǎݺuÓ ,˺»»›ššÒ$û$ÿ \Ÿ|ùäɓ‹-úî+Œxñ"00pòäÉMš4ÉåàZŽháããÓ¢E‹ü–÷)Š^œz=}úT?ªøzHþµÕ‡,Ɣî<7@ÇîûôWñ~¥ €e1EZûywíW×=cÌ¢#cú' ®ÁΎº;3 UÂÊ÷»›é0·ß„'Æ׬necž(òYrЉ á·Â¿2"õÍíÃæü£ì7c×ȖN•ë³Çªw¡žG{Gö"n~eß²Ê\ºÎ0á¡(hÍÚÖ¶ùw>±cDDÄâŋiš2dˆL&srròöö.‚®–e4h0lذN:qíÅ"\„BZ­öøñã³gÏ åæ‚U®\ÙÌÌ,¿ÔêzJ§OŸ^«V­Ö­[wƌcffòmÅkð0«[ȓõ1`Ԙź5È,·Êúë  ×û VŽzþ§OÞÊûÕ{êßñ«c+ÙO_Ċ*•wŠdçVw™{Ã3dٚNÕlñW§À¥K— tðàÁŒŒ [[Û|ý[álA¢gB>>>ãÆ›5kVJJJ÷îÝõ]yûöí7oÞ|á…üì!ôÛo¿}iüŒ[!û¹ b„PžM4õoAéߎBy·›ÈuQô±¶æ¹Û§Êš;JQV¬rô5 /ÜÔÿ@¡Œb²ãcâ]:-Z0 ‘xY˜Ðj¹ls§'ïÓ?øìÙ³Y³f±,;bÄn6ƒR©”ËåùmrY€ !Ž}ûöž={ÆÅÅqs²Š@¡u¯“Y»víúõëǏ¯PÏÈÈÈOž qžG®âÕ+…†˜ë0— åWY?Ù/ÊÛÓß„ÊuÝ|ÅYš×2j )ä©°€A¿Yˆ?kŠçӐþtãŒç·6L[Y³¡oÖÓG¯5¿Øž‚­ÁFù—m!€V«³²²ž Ւ‰<r»Š¢Z·nÍ0LXXÃ0\§×7bĈŸ}ûfee}Á§°,«?Æöu Î_/Ÿåç†fè9ZùŸjѺ2ÿ£oÌåCÄî}w¯ŠÌ­r}ǹÿ€e2Öº”è¿$ ëšŠœ=ðúeLšõ ö¯ì]šgh3¯/^EXŸVÇý{ºÚ|ü¡sßþKóIOÞÿt· çöý9r€P(,âW"„<<<¶oß>tèP­V;iÒ€"Phîú,ˆ……íÚµkìØ±žžž\ß~Iy+†^:ò«†LÄðÏŸ^3ŸÉòš†{¶Ö;}þœo«°ßxãım繕*¿y›©ió§oÕJ,ö+%Püy&ä'g²,Ë®Y³†eÙ>}úèZÊ&&&&&&ßè­HyæS6ÀˆÝŒ Wl‚ÁÄÒÎÄò¿ ÂS”°”c¹RŽåŸï`Œ'4³s3ƒ×ÿ1=º/<þ|ÚŽi|>ذaœ6s1elП//¯5k֌3föìÙÓ§Oçóù…g“:m^²dÉ¡C‡†êíí­ÓfýîkB®b+íê]øîaŒ)žØÁ­‚ƒ[…ŸÑGë!|ŠÐП}ûaÆíÚµkëÖ­ðqg‰ÿÞR'ä-d86Aèû Ðà—ÿëPîÿ-=Ü^Ÿ|ù×_ …B}mfYV$Y[[àê©o1`Ÿ¥K—>zô(88žPm’»rhhè±cÇúõëW®\963 cnnΜ`Šhï /S*y¡ˆÜŏW“bœžE¢g‚ºC‡‰dÓŠM§N²¶¶&ó _€a˜„„ggçN:ék³@ pqq±··çñxE²è ž|ùò‹-ZŽhQ@@€““S!0EQ©©©*•ªoߟúq3Ã0^^^ÆÆÆE“qŠ¢Ö¯_§ÑhžW’†r”jddd1&‘g‚aײeKKKË'N€ŠŠÜї@ÐٌŸŸ7,’K›‹L›s°Ïœ9s6mڔ’’"—Ë |×.177ïØ±£‹‹ MÓ:m¶ŽŽôôô455-²Œ÷êÕËÑё›A"•JSSSµZ-QèŸnnnMš4á66'òL(A ]£F5j€€€ÄÆÆêö&ò‚1V«Õº1×âÒæ\loo,“É¢¢¢ I¡@«Õꎙ{cº——×)ZdƒîU«V­Zµ*÷Q¡PŒyó†{é±Ì‡eÙÂÛB‡È3á{|œCamm­T*ccc¹~3R8„/K…P(tqqqrr¢(ªžŠáè°‰‰‰ƒƒCdd€L&+ÔN –e­­­9m†"œ‡‘ëFr¹\.—y.pÃÎõên"τâ£y<ž““Ç“J¥dšðU›177·³³+FmÎFÛØØ „RSSõ·ô*xgÊç;99q+Œ‹1ï"‘ÈÖÖ6¿„ß-ωä»ß*Fä™Pˆ moo_ªT)²nŠðe†âñxÅÒ§ýe…¶²²233+ÔEVEq{ßoÞMLLÜÜÜHU-Œç[Hã#Dž ?ªÐElš„Ÿ]§K”SU4¡Oñæœ(sZšùø¶=7qÛ&òLø&G ðóLQЧØûóKކiâ/Y¹îêãhçš=Šus5Þæ `ŽòØ÷¯^{˜ wüWbÛd[@ ¬:#„ åqØÒwµeF¬ystÈâã‰Yj@ÈÀôڄš ݇üµaϩؔ–!‘g@ ž:À³KçïÄ;÷îÚ³UËNKƵ1xèþûZ„ N/å•vo°gÏîéÃëÉY€³ŽÈ3@  C¥OcRŒ<Ý=˔ëòՍe£ÓÕ4Tƀ„B w'K#,!òL „‚@v|BFŒ‰¹¹…˜`ìPF,‰ŒJVkC?À#€;ŒÈ3@ ~!‘ŠY†Í‰„iŠ‚ŒLcxÝ9™{Jä™@ E_Ìã‰x| å,ÆÄ4ÍxžÛ Ÿg~êÃÆùôgÿßwsy&B@ìàc甑“$H|òZ®tw² (­2[*W±#„Õr™T¡ÁåLèf1…1FÀÂǵYÿßúLä™@ Â@T¯q5ϬçN}—ôvÇ¢RºiSG …/†l7zgÍdÚ­Ó”ã Ö(Óß{ò,*^%Ë||ÿEdL¢þßG£‰<¡õa ŠŸí·}øÀÀ=o=&,RÎÞ EæNb#>O$¶p‹›ùþáâ9‹Ï?‘áø53§ïÃ\üµñ™‹wË{ž»!süÀٜt7–µsVZ“Ò³,UƒêH]Sµé‰Ú,^"Óñ¹œH«™ÖòõŒÑÞû̚Ý`÷•<žªŸ*¹\~åʕáÇ_¿~}èС—.]ZŸ|9ö:£<#‚ügÐjµSŠLiҀɿöaêä çâRŒU+RZQ£¶pV†Ñj$†•ÈÁš{äûQ'©ŠBœÞ®*Kҕí[×.NP•õÑæòŽ2Q/øUTˆ¢(ðVs.€£€t k2™ªU«vòäÉN:Mš4©N:€Û(Ï‚ ÿ!!f³ùy|à¬VÂ_˜3RFÿ Io®éd'1d&é@ì¬ÊسÎíŠ_hûž©Ålæ²/ÿüërƒ{“…›VHOFΙºUB€Ábms¥J+°R©Ôöc̘1+V,xSLn”gA©ô۪Úì2þªû~e íõ~­@¶m Ÿíû&w7èêy¢Â-°Z˜«³ænÔ¥£›q§÷èŽ÷ãÎ_Ìl& VAxžP(DáY k›@uᅍF…BqòäIAìíí³³³1EPžAÞuš@*tšéQIžœïðe«ÌŸÎ§³¿ñ”X§ –«6(szÿJEŸðfÁ»Õj9 W»þÂÞ­ÕÚukX婚ôŽUÛUV”•²„Š‚Ò§QÆfͳDƒãžš5k8p`þüù†ÒV­Z©T*L”gAw[­Øç‡ªRìdÞÄ¹Ššò8A"u•æ_œh.)‘³,X:šÒ³Gh¯ülÑÚd0å-Œ"˜š-«(XíÆŽ©KL:ƒ@Ÿ2“ L&S‡&MšTb°p« ”gAw@)g4s@)B€Ï¡ù«’¬V@8ŽRJ¬f1_4i~G3oÊBåÀÓfYÛ®‹Å¢ÓéìííKr€iƒòŒ òëóC!Ž)rae|ø‹>: …u¥ôõƒ«†!‚ ZÏ‚ È …R*“+í4RVâøZ •…ʧ5£<#‚ ÙûÃâ{7Î jµÚßßÿµƒeYL ”gA$ßre†aJ± -ŒúÈË ä~pYA·„’äÐÖ|÷ÀòæÍšµj÷Á¬ÏÛVü|-APžA „ôãˆÌßY£ÿ̯‡·Ø»~æšíw€¿…òŒ ‚Œ6uÐï^ó+­3inÏúáMz¯èWñîŽ5ñ„Ð’¬mZÄøFPžA0ÅþD#ZWF"ó©i4Å_O„’úŸ !Đt|÷–m{O€é̈́Còõ¿üvøj¢ Rx• ’œÃàÐ0A·S•í\Fáêãe¶ÞŒËhçëVü ƛÓ'Ì?~=+Ž_õ‰Ý„Ékœ«øÝ_±`÷€5‹?®ŒœÊ(Ï‚ ÈsÛτkÁdhÊ ‚šÓ•žgöÙ?âøŠ_oYøà—±_mèÕ+cäõs7\þ¶õðcڏ+k0N_>Øž ò¶Ûa ')²ՙgå’ åÜ í]V–÷—Sp«õqË2Þ®Jif|rž‰ã)Q£l õŒ ‚<7@â^OÍ>v«O嚌`J¹}:UáRÅG ‚9;;*]ìåŒI—£³Èí4J©Â³ŒâüɋÊñç.0yÖ ã÷5B÷àãŒ_v¹uøÒã­gAä9!”xõP+o{䖓W¯ÿs`ÝÒó¡uÔ²‡ìØ ‹ŸüՖ«tfç„ᶏU¥Ÿõ©|kÏâ9›~9{Îê•Z‡Ç;’üñ·ƒŸôÓZÏ‚ ï€>J¡Â_Jøýй{ˆÒ·Þà“ê+³÷õ­À;©@Šv ðõ÷¶“¥P¹Ý°%í†=Ž¿åÍ\úQ9NWAyFA^„@SiЅŸZMŒT)!¶îf¿°Ïæ…©wív“j·ÛB –䀔èÄ¥:QžA&Ð6I•É”%·°È†<éôáeÛá#ǚͯ ì{FyGÅAyFAåAAPžAAyFA”gAAPžAåAA”gADQEãAyFyƒðóósvv†âvu, ÷§øoÖɞéõDydggçææÂ¿]ˋ²lÙ²)SŠH¥R\ ì ‡RÊóüŒ3FòŒ òFcgg§×ë9Ž“J¥ÿ·˜˜˜Ÿ}ûΚ5K¯×c|ŸÉšÕê9sæÜ»w¯4ŽQžA^'>>>iiiyyy®®®ÿÚ&srrrtttttÄø|Ãqrr*e- ûžA^'!!!ééééééðÉØý_ّ³€ŽCyFyð<-vÿ‹ê-U}…Ÿ!5†arss³²²bccÓÒÒ8Ž+)ÑQžA^³ÌŽmÛöܹs±±±ÿS˜þ “Š¢(–$/¥Ÿ„1/æè‘Ky”’Xuçí\»fÓ¡sQyVBž¡ÐTQ€‡,?H¶à¿(yÎËˋµÉ3Ïó%ºÄÏAäua³œj×®íêêºmÛ¶ŒŒ ÛÉ7X¡ ¥Tx^ ¥·õO.1fÕ_ÙF¡„8 ”RAàñÙ~Ä MÙÑ€ÆMm eIýñۑµ;Ÿ4?òçõëîX3ë›UçM%{løuL÷‰»îÙñ00©W.œ>Ç,”èÀªÍ8úÃÚ_¯f?Í†Š”š~Fd DÈJðВ{1³Cç™÷n|¿jA¥Œk—nÞK³ji§Œ6óA®‰H€*9&œÁ€–YìӍ&#Q‡ŒXŒC–eÀªË53 ±dæèxQâì±„(ûÈèÇHš>!ú§þ£ö­®ß­<±Ú¹ø4ëµüýž„•!À™uÙ9Z‹•—š\œä,!@ÍyÙV™œB4€eë ‘;{žª€ xzšéõú]»vuêÔé‰ó¶p¢õŒ òF(4DFFšLŠùóçŸ:u*--M¯×Ûú&Ÿ®ÍÅ^¥@ݓ‹†}X>8€jÕ*!!Óc@0ÅÞ6€]D¹ÀàÐÚõú}µùN€žCëgòÍÒȏ:5ò÷÷ë9zSl÷þÚЫZðÐ*åý·\πۿΞ ›<¬UzߟϵŠ]^þyÛÏŸšói§ŸNXuì'mÊ•+úáðuÑi8:¹cÏ¿¥qßèƒæm\7÷³ŠAA}ê|»;xÝéK7ƒ9cÀ‡m[vÛsÛTÒ[ ñç ªQ³FåÀ O[º_5p©§~üAÙ ÊÕjÖìúã‰DA—ŽuÕ7‹~Þ{ve—ΝGœLîo=d쬣q&8³xðÈ/¬^<¡n°²~ãVžµˆ`Øüqø'[¢@4_Ü»`†aŸŽ‰hÿk”9°ãß IDATçâoS}²öR.МØ= &EÔ©X.Œ]ïÕûnk-@Nh?ø›ï¿ìï[}î/Ñ@è³ÓÝh4Ú~Oœ8ÑÖµñD«òŸçȑ#cǎÅx@ÿ.ù£§(=}úôСCǍ·aÆÇ_»v->>þv $&&öéÓgöìÙÅy?Œ¥c“mç㠆¬›W/g b^ìÁvÁëS9kÜéu­=ݪœ¿ÎHiÜŸÙM<‚º,úóÊ?ë:¹Cãµûâ(ÍùÂQYiÄúDƒ>#úNL'RªKŸø…’4šèÁƒä=—stx%€ò ûþ|&G›}íܑƒÇ2)œ»§«¿ŽÎ’-єҜ}ýCÇmJÈã(¥[{*€Qù~²ôZìõ•=ÔÀLÏŠôÁ©_z;:w_w:-=-Ã`¥"oµZ9V«•ã‘Rš;·œ›ŠÒÈÃw²u)çÆWòhq>WŽj/tðqÄ,æþŸ £sÃKšuc砍Þÿ`k|n¶I€——õmÚsàλ&Jé‰Yï¹ÉAÑlâ¡ÛÑ»Æûô¿©³Rª_Úª¯žI)M»òǧöêŽ+OŠ¥¥fYiâß«{µª=『RË®Aí| |öÆšýë䆍7K ”îúÔ™G÷…—co¯ïk0!­„Tž;wn›6mΟ?ñâŚ5kþüóÏF£166V£Ñlݺ5!!RÊ0 ÏóØž òfµr×­[·nݺQQQçΝ;|øpzzºŸŸ_TTT±V²D"¹téR­ZµŠñ1æÄ ŒÙþӇ5œ rš3ˆÖ{Qgöjüìíç!šÛ}ðŽ³ƒŸßtÕø©oåCšÌŸ¹jTWîjÛ2eVg[rÜ*7¬ŸæÄî7Û5hð^{(š=ƒ*׃÷@//oȶ œ³W»á?løÈCBeÊèkÇÎfÞÒ2²„>—+qa VŽÚ÷Þ¿áC 4n/Ù})À·lÅÀZ’d`w7G.éÖ¹#]ÐÉ¥ ʛÔë¶lT×Ãtv••~±€oý@'ԚwbÉB·% ¿{ò7`†Û'ý±-5Ñ€ô ©1YîYߜGš³¿ŸƒÀhXV “™m5íÜŠ/«:0ºIçŸI3ÐÊvÀ0àJì}‚j³‚{»»+耚XVò`ù=%­ÊøŸƒú„È>ørIØÖ'ïEØÈ×jáí{®‰û±@Ùžùérºîì³]&“?~ƌZ­vôèÑC† ™:uj~Êâ' òæ(4<ìi.Í]ãǏOII)æ‚D%K ïŸ@$r9 ùÊAFÁ€„a@0‰eœÜ|]íÀhÌx¹ Tƒvl0ö³uÑšÉ3+ÏùaõÄQ48à(WÐ빒kܝÀtñàÆÉsVßÉ,SÝ?;‡º*Û+=šEµb툊„RJ“>—€› @ÌFx°ù)fG]Ý·zuŽœZÀ› å;ÚÕ®S׃€„º»Êdù•Î6úJÂJÄ¿¶­ŒÀð"(ktXÙšÖl Ÿ?ä7øZ!¬Š¿£!‹‚ƒœôˆ‚ÙÈ—˜üó€D"qÖ°vù‹¯©r–! jÅÚM*2ŒÆhÈâ(+ÝP³ÙÜšQ£#GŽÔ¯_Ϟ=¶ÍQl`ß3‚ ț(Ò¥Çjµ2Lq…¹C0ç~?›¬ãÀšÍ1‰D"“;k/ýzV  Kˆœz^ƖuR¬oål! ".Cï5rÛî3·O Mùkò†€! ?Ÿ\ðQy‹@{Ó÷+r|šÞŸµoóÈ~¬”gHÑ×ã æBݲT á,úÄkéTÚyðÖ[7.ž={öìًWoì˜5 Ø @¢rƒûû/Fe)¯Küñç?E`äŸFýzúÌÙ³gŽn^3®¢xHI³›,§8Qx2€ŒÀ.§=~šQz2·¯]»™`Œy0']êjgo3Æy©gB)•Ëå¶ß‘‘‘O¬ÉŠÖ3‚ È[¥@œ/Ô³ÿ’a#¬j—Q4íËÒË' ºØ¿·üÙ¥MǙLVÞŠ^œÙj䄇"&pPعx—óŽœ:jiఎ­;–Uy¢ þA»×};1ëŒ[–þÐõs~"¥öAmvl>v@ ýíåTœEdZ Rƒ€•çM4ÿAg1™EA€ XŒ&Êٖ!TäAä g'€T©ñ­TáÄW£UÒµk7–r“ÑÊq~œ>èszþÖ¯§ŒkâtfïF¯°kK8³Þ”¢@9Qx–ñK!„üòË/™™™V«U©T^Ÿ|Ù&ضí&Ù/¿üóñ[@\\\ttt‹-0*ä]ãÀr¹<""â±Ò(%ŒÛvÕüÜžžŸšE%m:ÖrP9×nÿžcü±—â²ÏæŸÍœÐ¿ p‰“_Hhx„€h‘x×i\³œ»]ú?'Îݍº“êüáˆåŸ5×È !ÏÀê¹·3dWŽhç¯x"÷¯þ~%7HËz»Š9ÉWo¥†÷ìÙ¡Q¥Ô{æJ ÂŒìÁ> ^íÀ2 áM¹N¡-ê”sB@šsh«!j™[ù ÌœkF3Sµ~cy1£ˆ¢êûµdÙñɱ÷rÄF˖õ“Ï­k:Ȕ!µ rºòϹøÄätÖÎñœ&MÜ€ÔBT>•ªÖ¬è"g–¹†††ž«YÁbTWš]3š¬ZÆLlPË6áNRb5æº×hYÛϞ•š<*„dä^×iùFMœ%œšt ¯[ÞIêZ«N1ñÚù+·ÙÀ^³ŸýŒ¶Ÿx“αJ“ºå]†€(XíBZ·ªª..±N:aµZ¥RiFFFBBBRRR\\\bb¢íGýúõÛ¶mû&¯Mƒü=ztߟ}‘‘‘ò®1räHF3kÖ¬¢t‘éÒ¶ÙÃEÝA±s¬‹u]²œNŸÙ0_üî"g‹uVÒäïâŠ? žM㜑H óŽ7},.÷ŸÈ¥§Æ^ ®ç͛wüøñ™3gæååùùù”WØ÷Œ ò–B)Œ|UþB%e5•<~SÁo(fAìÖÈ&ä‰ÕH‹qUŒz?y_ñ•RlØ=ýè~[ò#O˜ßô‘ûÇ_â±,}ì‘gÔT!&“Éd2¡<#‚Œ³]ø×c²ñÌahÅhOIb^äZéŸòT?KpVôÍJû0xŽÀŒàG=”gAyã@yFùoC)U«Õÿ Ôju)‡|áÄ*Aÿ6‰dʔ);wîäyžaۆ ț™R7n܈ˆˆ(M«8Ê3‚ È›Q£FµoßÞ¶VsNNNRR’Õj}©Ý¢È¿ƒRÚµk×2eÊ섁òŒ ò֖ø>>>>>>¶ÃÜÜÜèèh‹Å‚1ófBEQ”gA·Œž/|X°ÉZÏo8¢(Úö(CyFyûQ*•^^^Ç¡<¿ùòlgg'‘HPžAÞ~ÔjµJ¥*i-äÍÁ–FOI&”gAw¥ÄÃCïd•¢€ºÎ{FyKø 3¥”RzyçÜú 6kÕaú†Ó"!ðNîQRª¡<#‚ ¯Xœ’ôçŒÏ—ÿÝzܒ…cÚýùã×£ŸeÛgºD9ü°Øßo(Ï‚ È«Ug9¿}¿ß>búԎÕÃÞ﹌o@ÌïëãŠÙ}ª`ó'JÑÖL©(‚ Ò'ö°@yFA Ú˜célDËJ¬Ô5(ÜhJŸ™X‚{B€%+úÏí~Úu81ÏDÄ>·gë/ž6s"!äíÓg† ‚Œj ‰×ÒRÖAÀ°*g/7“%*!³­¯kñ7ä]˜4náy¬5gÍéAË?”NùjG@ÍrћVüÑs岟!oß 2”gAä•Ð K¬ J9^€&“¹$÷™gþHQUŸ¿u\Ùžm£Š¯î70kҎS݃ìLW·zÜÐ7äíÛ·AWTí*)Gò5ˆZ,¬BRÞßœÀÁÝɄ! ooÖlu ïÔÀÕÝM-‹¿~#KgÌÎሓä­Ü­gAä•Bd~á É߇.õ©üËic®œÊRyWõ‘E—ô 4ž>.*‹6ãA–ÉÞÕÃÕ^®ò p\}ìøQ—$œŠJMÚš7:'¡kúî¿*ö™£xc ­gAä•B(ðê5°‘u÷µûŽÝ»ó‡ ÷4ýŽª2îùvÜ襻n@â©í“GÍÜs. ”AÝOþgÇ֓ô‹™Ó'Î_8€Kcݝ;êFƒæö© oãŒiŽžAW¬Ï„R(ßnòÈÌ9›ßr‘µ+ßñ󑟅€ÔÎ=4Œ¶Ô×TnåëÖ å]Ô@)µ8§ÕÀ‡ö·æƒ‰ß|P`Ž¿ ŽúN®ÒòöqôèÑ}ûöEFFbT ò_€æOqæy+#‘1P0œ9ÿ²H óð·M~.~I)-tTàZÏ‚ ò"ŒCBH$2(X.ŒÐe†2¶‰í_áÃÇoë:ÝØ÷Œ ‚Œ}~Lqƒ-”gAAyFAåAAPžAAyFA”gAAPžAå£AAPž‘ÿžÔ+&Í’×øîoæßéÛ .ê‰óÍÛð™1cƬY³d2ÆÉ›€ƒƒÃœ{÷4MAœ^lažÿ~åʕ_j¬Vë̙3§OŸNy]ïN9pà@ëÖ­¥Ré›ù<ÏwïÞ}˖-ø] <#ï–6ëõú‰'fddÄÇÇ»»» ‚€1óÚµðȑ#AAA¬ZµêkWh[Ž=Ú£G#GŽÔšQƒçù—ñ –eÓÓÓnj3bĈ9sæØÙÙœ®wÏËËkÚŽé¡C‡ ÃëÍ 2™lÿþýsçÎÅïåy·ŽY§ÓMŸ>=))iõêÕ-o­[·^·n]óæÍÿúë¯×«Ð¶G;v¬[·n{÷î­S§Èåò—ô8??¿e˖ 4hƌ_~ù¥œœýkywJ©D"µZýÚ3ƒB¡À/â­ûž‘ü¢Çf¢iµÚ¯Ÿú***j͚5”ÒÒ÷o=wOØc”äÛcz|ªo/öiÏ÷­2LëÖ­×®]ÛªU«k×®ì¬÷ZòɱcǺtébÓæ—J©§§çÚµkoÜž1gΝN÷ZÞýåfŽû©Ð‡`!†òŒŒØÊ»ŒŒŒÈÈȋ/þðÃîîîù;ŒbµZÏÂd2ÙºŸ/”R*Š¢øžyTØ[B¡TEj }Þªo¶ëÅé©ÅïËš»¥”a˜¶mÛ®X±¢}ûöW®\WŸÍíqGíÚµëŸ}ûlÚü²Ã`Küñ̙3‘‘‘Z­þc[•:#•Ú;£Ñ˜“œœl±X°{ûÀÆm$N·dɒ“'OîØ±ÃÕÕµp±ûÑGíÚµë)cÄDQ”Édƒáùˁ3^?~ÔT®á{4¢ÀsVŽHå2ÉãõHsÊéÓ÷Y¹Š]Ùð­(t—.]>úè£;wîRÅÞâáá!•J_`>iÓŠÍœ{÷|||^q¹o{w77·'N4kÖ¬^œz„ÔÔÔbG¥Éår77·7êÓߺŒší');¯ó}1œ× Ã0 c2™’““õzœh«ÂÓÓÓÖ_Ž <#ÿmlöqÑb×VUZ¹£×BX–-AµCt^–X ˈËûÊ&29€É”—¯ãX(ì ȕ ucëVŒ/øskží7²q™‡7 BŸ©êf VSb˜”Œ[õû2y!Cù ßlçdþ5Âj{i¥r»ô¿GÏÜYcη4RÆ¢e|ØÒŒû“‘UœT0¹ÈÙÙÙd2ét:{{ûŸ~úé³Ï>sss+\@3 “‘‘qñâÅêÕ«¿ÀLB)uqq)ü"E3LÁ™Ò_*Í-ï®P(âããkÔš!“É|}}ííí汚•ÙlvrrJLL|É_Ìc}vÞvdý«ýXiI^›úOG­V¯Zµjýúõ¶Ô/è`²¥þýû÷˗/%Ê3ò–ð¢M"B³Sr¬¬“‹›JJÀ’“”bQùž;ñºô;±Q$Œs¹`G…š&>ÕÀ¹UrÌ¥ô©3Ç(€Œ`1ŠÜ¹š wpõ._΋1d€çYí]=,púôä\Šn—Ÿ  ÛûøWwj}1r˜ rî&R?_'ˆ‚5/3ÍÀºxÙ Ù9:F!7d>HË¥®e|}<lmຎ;q): ¯ôtµ“B W2 dÌjµÆÆÆúúúZ,–~ýú­_¿þ‰€W©Rå…OŠ#„WMM"yyó} † ›~èz–ípûן YŒ;¯ìø¶MÇΝ»tz¿f‹ék¯=qWVÔ±9:/< BêݳvëÔšuˁÃF­¹Ÿ`”Hd€[{VwîÚµs—Žk4¿ô,pÿÏå+ìÏúŽs÷íWó€ËùgÜ^=µnݱ{¯ {Î%€xmãä^]:5iÝò³‘7Šd,Ö\ÑÇ×}þÅÇÍ5kÛºßÖÓ7ãÎþ4æ³AÇØÜü³~ÂÀ©k¯Åël‡:}𝙧¢ðà§±-ºÏØcÓImâåy_|<‚öîß †8tæÌ!ƒ»×¯Ý KßIÇ£’ÀtóäŒq»tïТaÛÑ v¥x Pì8†a8Ž‹‹‹KOOç8®šŽã^xÛf±™$!!¡zõêaaaÕªUëÛ·oáJÞ̙3ÃÃÃêW¯~üøñ—ªV­VµjÕÂçoÜžaó-<<|̘1ÅVY–ÍÈȈ‹‹EQ¯×?q5//ï…7Œ—ð‹ëGöùbù­Ûdh뚱m†­;-wâû™m:tþ CÓ÷:/Ú~ÿ‰Û’Nl™3eÊÞ»F0ÝÜúé˜È?®Š€þòß³FµïÜœS‹†í',ۗc¡ÏýH1›Í¶ßóçÏ¿xñ¢í7.W€Ö3òF`[œáòåËOo…~ÊíW¯^µ··5R§nÞÌy>ÛŽz[uöÁ ëâú­©j/‰k­?ÏO«â.ým¬üƒ;Š|^ñН"gÌʌ“X€ÜÁesf,Ië³#jj[õ®±Ã÷ïœ(qšòËßgC}ÿúRÖbÒö)cŽ<ÚaåùéßüÔ§2(•÷Oü8|ðʀ·Žw‚ýFÎ\ôÞþE§fLøæwÕĝуß4` —K €•ãàQL)‘È¥,agåO:Uå›Õ1³ ‹G÷7zҊÕãÍwýúG×6eL–¬8[¶DzÞùHý¥„x5l[oDß¹‡fuké`žsò·­ ×ÓÛgï_9µ3+ðÛ¯w¯œ}zpÏ~óW”¯Œ|Àú>Zé3ðàÙiÖû‡}Ö Cħánl bÃ0ŒÙlÎÉɑÉd™™™Ç·õ4[­ÖN:Éd²»wïò<_ Þ2™ÌjµþëŽT©TŎ,\5|ðàÁúõ뜜œAP«Õ)))—¶nÝj4 ¥T¡PÈårېc‰D2þüªU«Š¢È²ì­[· nÑjµ©©©žžžÅêeZZš(Š ÃìÝ»7¥*•ªbŊÇeeeÝŸ}û9«­ñeggW4o×iþþY}Ò©’OYÒ®‘›²Vž­ÆÁ¡\Ósw–Ùg¬î_fÄg»Ç}<¶p8SvrvR:G@ä33²-F cV›66˜}úÊÇËýêônÜ)¹Wг;ª†áyþêÕ«6lHII‘J¥¡¡¡8" åySä9!!áÇüwUfÛggç—ÑHd­""ŸÝ~ñdŒ±­°i¥g÷µeÀVkZïC{.êä I@ØšTœïõ–3;–š|2ýGÖ:”cº,šŽüøtž3 ¡u>|õž<%Vžj€ònå+ք(çr®.n èn$ߺª–7ŽÚÿýjslº¥†¬ä;åæTØ»ûûÞ @ïuÓçùR äî^¶îšÞ(æ7€ [ îQӓ ”“Ú×ÿò§5ËÐnŸ økü÷ÄÀf­C÷ýxôâÍ¡ÜåŸï 5§5ªí*-Ú×M¡!mF¹ÖY±ôF˱êC÷¹¶˜ùŸ=$ë-4 ÎÄéKGŸgPö£Š[ÜÏMŒza¿ŒTP&^·ê’âä%€iEêÊ>¥G“BˆL&;{öì×_m[4C«Õ†‡‡+Š .\ŒxÑŠ‚ Ã;v¬aÆÿ:-¥R©\./Zî6+—.]j›hDzl\\\Á¥'Nœ;w® A»`:Ïó?ÿü³­qÞ¶hÝ£*š(–0Š!_–!‰dÑ¢EÄ\]]¿ûî;«Õzúôéýû÷¿‘q,ËÞœ{·È*=„šj~ÜŒÞ7[ÿºÐ§u•kK"œ*Mh_͍ÞŽöŸ?·ý£ïe‚Êþn:€#y,èj†U[ ÊYVEXh¯ýªV‘ßß»ò;•4ÙòâRuP y–H$III«V­Š‹‹ûí·ßœœœPžQž‘7«ÕZ§N9sæük®^œÚ£G—8 @ì‡v~ÛŽ›‡þÜyeÉíæãú؃5æ›qöÞàüªøk H䀸»(€ÂŽQæn&ƒÀñ@$š¶dú°õg³Œ5aÎr9¢`6ZÁJx›n° FýÕ ÇšYPvhÿ¡¯JD¥=«ÈÏýœ(@ÈŒzåRŽVÈïædTõ9 @•&ÄAi3{x^d‰ÀIœ»µX¿zÙok—ýùÏÑòmÖ¬ê ÅtÂ:W]Ò¿r«Yó ßsÂØ÷zà<”2ïüPŒ HY0DÊJão3‰Hk86¢¢ [ŠbÖ`0ŽmÛ¶mÛ¶…OjµÚ>}úT©R¥àLDDĒ%Kž'1—.]ZŽW£ÑŽoß^¯× ‚:zôh…B!Š¢R©üå—_vîÜÉóŒÉd9rdœzõl]Ô2™lÒ€I6ñ¶Y϶ÁM,ËÆÇÇõÕWƒçùʕ+?sR¯Åb9|øpá3wïÞµ³³k×®]»ví^T.þý÷ߗ/_^\ÞvÕ'¢RäÑN;¯Xßo Ëç]Ÿ2lèŸDu°K€“Œ"LÑ6"a[ÍC4PÆ,B€IòýGõ @¡aÏIýKÕ e±Xüýý×®]+•J?þøãúõëÛj6X0¢<#¯BH±œ¥Ç`0<ÅLyŸ°QâÚ¢oÓ¹Ÿý4rø5Y“ßê‡:IÀzsÿôÕ6ÜÐõ ±û£÷?߁ÀH€bVî¢t“o]¿|*Žëè£Ýœù×[Ñé]åjküßSïœu(fÌûåN {9¬Œ0„!,œÿw ô)¬ÔNáTž:¶î¿nBMŸ‡æh7&wǕ˗S„÷3~^ÿKÂÃ\úoú©Ñð3DäLwœ·¶i)ƒœ;·nY5î\€PŠcóF;–-çÒ(rf};[S6)\­xh)ÉkôžQn~÷¡“ϐýú²ÀJCjÊÝ w zXî_‹Kw«èæâ]Š¢Þ ÷X²ixy{3/+¡Ø«Mà†n^Á$Ž#üaÃôaœM–»¢‹pêëñûM±êMF+*òfƒŽáÏVmº­?ºbxÿî¿»{§d_Ï2ó'°åZ„H]0áÞ–Þ6¹ÂÕ¯Gÿ²fy‡JMÞ»7ý‹ázöÿ|JhƒîãÚ_:¬áƒÍ¬™.! >: g׏6ÏØ2ìÓµTn)Ú&ÊóÂÓbDŸi=úÝâ©Ú}.îÊåšfCWD”—.Í[îÚr §Q£÷ª³@‰­ÃYŽ µŠµ BË7WÏwèµôÏV|fV.5eÜ?0wºìfÅìžÃ×ÌÎÃ{¶)ë4iì„áSìy:$À]ŸßlÂÊîUÝ жbŠ`&Ã0˜9sfa1V©T…;q_`öx¢Ü/˜ïTŠL™¢¹È&ÞÞÞ`Óì— 7?1·ª$ß gNÛ0òÑ£G–pBHzzú«E(¢š1¬£O«ïþj¿øã9(\«9â/P€ç$1ª”Ñ‹NéÀX :‘£àìúmKÆz9ˆMŸ¥5™ÔŒÕ L•9“'™5­OC•Ê:iÓ[O[×-Øñéõr†a~ýõW©Tj«Ê‚ ‚R©|ðà–f(ÏÈ[¢Ê¶VÄ¢ÛöQJŸŸ €m—‚§"@HµŸCšÊ4‰p³#À”i²héÂmGâÌijdžI7oœb5³J—£æ…Uwû2U» Ÿ& R@p›—ƒê·?OšiåñÃ>éÚ=¥J%‰SðבK¶ŠÊ±J»®÷þ/;Îdó@dõ?]9ÍŽÁl¶P‰GЀmßyüŽòïk*Óxyº+â÷Ñg«Y§ƒ'/Z ú¬I}ÚwH¬áïXRӁTåÞjÔ ±¢ãœ³×-þŽü€×'ÍmjàYE¢ôòïU»~˜—ސ:ƒSAs&{Úç/vF#ql®ßl8®•«Í[ÁÊk+Ô­ÔÈ ôŸÆèÙ±ITè?æ»ÊšÍ{®§æ O_9!ÅTž8޳)Çqµk×f扝”ŽZíĉýüü^l>±Z­Ç)•Ê'fc•ÿ÷Ò3o)üî¶üf±X&MšÄóübìììüõ×_¿¢†+ €á„i‹Ê6lÒ-T*! h¿bŬ§3$öU{l™ÔxÓ/ÉVœÒ³òŸÏ+«À­F«1S,¿øGlÜ»o¿O’Ùp{þ|úš0§Íû£3õ¢£—¿¯æÛ¹Z,–&MšžººF›‰o;¯Óé&OžìêêŠ%ÛžM'Æœ=ztߟ}‘‘‘ÿڇÄÄÄI“&O˜0A*•.|[Žh‘]­Zµ’6 ŽZ­?ÿüóõë× ws>Õ(ž4H錸’ ú§O -ÙM ÷³*D‰M €€qÍÔŸÙ£YŽfíu |}b­ š˜{žY£æÞŸ\ÙýM˜íæž_V|>u}ðϧ#ÃeO B¡pø|ýúõéÓ§{{{÷îÝÛh4:::†††–Ô7Q8<GŽyžœ6yòäžžžÈÈÈÂӑ_Y£ÇqóçÏ?uêT¿~ý<<|žK—.nnn¶“ƒ¡€næW&KÅæí'óåãy»Ø ¬ŠMý§¿…­ÊòÊRy•`ã6òšø ›:uêœ9s&Ož£¥À8”køíŒFÎN\:…Öê_¡ŠL¥*æQŅÎöÿæÍ› šQ£F·nÝ$É+^z‚RªT*g̘1oÞŒîÝ»oߟÝËËëeÛgÚQ«Õ£Fêܹs«V­222^^ºÛ|ž1cÆéÓ§ŸÐfžçÝÜÜ<==_Y®{ʞª¯FƒÃ†Þz°â‰. y5襔eÙråÊùøøÀkš@xÈkÿ"(¥ž¶6Ê3òîšÑîîî¶“± xCÒE­V?±@ækÏ$ …"00P£Ñ”Žv͋)°$ww÷WÖß\r¹ÜËËËÉÉéMgÛ֜ø] <#ïšB;;;¿œí&‘ç*šß„öŒ‚L"“É^ø¢oæ»ËåòÂK‚#Ê3òz _Àµ‡Þà€y73Éko3xJ¥¡`ɔüY‰¥Y{AŠ€ÃqA^ŒIo“íš}Kš4mÚŽIÄÀ9»óÀ¶ö,F‚òŒ òšÔ2.²pO£á X<*ñÈ·ý‡üm¡‹·¶éã‡Pò!‚òŒ ‚ü;u6ÿŸa[wüÌ.Õ}«uúaRӜœ«®Zà)ûSQÞj1[¬¢­7 V‹ÅʋPdç ä]ûžA^ž˜c©Ža¯Q€ §À: 9v)ÚRÌj ¶í© éÑÇÿ>r_o_»IÓê\ӢΞ9mq hR¿º‡FŽc>PžAçE|•!òõíí À:y–è͘)[ü ºÛ«/ûãRŠ#›·ålìøŒßuÌÉß#e׆}×g¬ÕH-c1VQžAç‚a$@/>œù-r"€Õj-ÉœöÎŧ!‹vr¹1sÒ×ÓGG Zœgøûž©Y÷Ë9Ãë«d,šÏïnvÂ(@y1Ø»«Eb B «ÁÌÐூëOô%†‘j4Ô*0á!žå|í±—/D§iÄdñ.2 *3ZÏ‚ ÈsBˆchs?ÕŸý'û×îê*³Þ=öGãW«œðÆžšÛy*ÿ°ò.V}fll2ãR.À[£ô.ï•súÒî-–Ó¹ç9fÚœÞµbQúuý™kºOÐHÑtFëAy>¥ªnC?p¿Œñ»¶îÙŸþÛ¥×#:~^ËŒ¹IÛfžµþäÜ?¿bÊÔuûï€Ä³^÷O;–!÷ÎFAçCFM3zØ'ž"WŠY¿œÞSJY¹Ö3‚ ò\úL(çšƎ„mÇ®%;1tD *Q8VoÖÉÃÔ.e·j#v·YÜU›­ÚŒÀ¯Û}pÝî r\p åAyMIpË3š‹0R&_bevî͍*ROå.C+?Òއ‹‡SJ =\ µåAyM€RJFZœÄ†<æ À:~žnù—‘wì{Fyэ‹ <#‚ Ê3‚ ‚ (Ï‚ ‚òŒ ‚ Ê3‚ ‚ (Ï‚ ‚òŒ ‚ Ê3‚ %"Š"F‚ <#òfQ­Z5(²­aéù×7"f°ÿ\ÔAÞ!¢££-‹\.ÿw·B"##F#Æ$òbEÑÇÇgàÀ(Ïò.âé陔”T¡B…íƒÅb™ÚYåAw€ºuë&''ÇÄÄŒð˜>Ü<‘ŠœA››™™™£5qBÁ‹ÿB0ŠƒBçy¡4%8!„P* /ˆ”òâ5çÿµ×š€„*𜠈…#­p!„Š/âKŠ«gDM^^^BBœ{÷L&~­(ÏòP„>}ú|÷ÝwÇB^˜BPj³ÇyCú…¿¶}9qx¯Þ÷2~ùÖý±Yú‡ ]Œ`s2r Üÿk'ŝ8°ûtŽÞZºIbŒîî¥cGÎ\ãàÅÛc„bÑåäèL¶ ÀSõ˜B«Y›“c° ¯Ü:ä®îÞŸïf6ˆ§ÏÉԚø'Ã`Í8w쯋w„bâêßU§þÌ©×ëÓÒÒ8Ž{v;Ê3‚ o¶²žuëք•+W ‚ð‚:ߌ嵉?3¶é' S«õ[ÿãæ¹Ãj]Ö}àˆ/o€ „@ÑYwî2j{ÔÿûŒ›£†w_s(É(<œžÏÿ%dïÛ<{òœ…†—±gŸýbÔòý©:Ÿ$ëÝlÐÌŒM Ó¯^4~ÌæËÚWžþ–?»ôêz8 Ì9qëGôšw$ýÉž²&.ùzØÊm¿[J°¿-F­ÎÈœ€Š!„a‰D¢×ë¯\¹råʕËE0ïN£7ŽÜFwˀffÚŽiC† ñððèØ±£B¡(0¬ŸÃràrýü͘í)?]ºÜÁŽÙYï}úËÞÀ~íf¯_·oæäö„Ð'M2‰Òj¶JåO•ØbÂ%©¯ŽP«Ô%8¿™ýáU¹\¡Q+ʲ%»-ÍÙü×,X!r«•WHh á̺£ßοÙtԘz®ÀŠÀŠ/‘>í­KŠÇÚ$ö©‰Hì›@s¥eäœÕ"‘jø…ReWG)õ/Æn£„\]:ç÷°A_·.ÿD„<#ÁJó~‘)—8p`îܹÁÁÁ<Ï3 ¢(J$’ššš'N4hÐåA·Ó€Öh4«V­š4i’Á`hݺµ——×ý‘ÿ—TBhêsë6ìöÓåŽqûø#V›“£unÚ©ÿœ/Â&ž?6®e3yOIĝuUn –ôè(‹kyeޝ3·2=üêÛKp†ô×£’3óDÁ¥J­ªåœí Œh3øhfôõ\»r<íÀ˜~ï¶Ö¡F€; \vÔœQiJ_©ç˜‡odH»yõæý :žzõŠŸN,!Edæá ªŸpôv*ëàì[£n;ƒv/&9[R1<@#% ê£/Æ7/çÐQß.$j5 ‚9ûÆÉ ÉR­Q oÉžuzÕŽ9ë«·Šžö!u|S]â CFbŠ‘Ø«IÌÝ;²˜àêa圝$„ˆ©wŽ]1òÔ+4Ü9+…–S’b"ސ•˜œitö pU1`Ό¹ŸË–õõ•œ¹|Û`²âZ?ÄG£ÀƒÍÀ—;û~žøÑÞNŸxýò¥øl§Êet‘W \^ʹ«·sŽBÜCꄔuµ³æÜÙ'hÂws†v y>‡gtÛ\wÓÎáuXÑ¿OnóG»Ô]}š)ëÔ²/ÇoܐIjúÛ¹XŒ)vÕj0–š³ß-™ºíJ\n"[®QÏo挚áïHŠ‘=*òúKk#Çn^¡ó‘ð.=ŠÏØœÒ­ý›Š-:ÙaÙ²ñíÜØû¢ºÓâí-,~=o÷ÈÍcë9ÅÿœþÛÿXœ+$ÜŒpåØåÐÎ ×.è¡HÞ³iìÄQX?Wµ^HÚÁËöß]\œùŸvu÷ìûÃ/Ý¡<üþÝøMé5ÍËÜ2ná^ŽŠßN¯;xÏó[š Ýnʺ¿zP·ØVwðáÒc~[0qŽP§ª§ôú­ìöï«€÷Žïš6ÿ‡Lƒ)ûnjX¯e?-ýPwfÛ6Bì÷lùæLjýEÆ7×\\±xÒÊßï«Z*º‡v›øùØf5í’Ïn[°ö—$×ƒK }g-Ì»|3rÚê"j³Ó‡o<òÙûA,ûì ŸÅ’ßŸŸzõê2eÊŽkמÒ!òŒ ÈÛ`@ÛÚÉÉiÚŽiꊻø×©swúýp¥›[ÌÕßž< nîÉ&»Øž_Ɣ“’¿Õå%:tÐWsÏO³,þŽÿÚ†wêèûESïïŽø‡/‡4ƒœT^éPž›Xscb¶¢œZM²8 忟c&,÷ŠŒpbl՘}ßïó­XÊ@Ø9cÉÇÈßoöp<õ^hïŸÕüŽ©œ·‚Xà¥(™RJŽILJ ­Zsóæ@¿] Ÿ1nL‹.G"ú èzóõ_~ád|bÕŽI¯îÝ‹61U4ó”x°aì’“w^ùº³"3-G)*7ë7Ô}sÜì…k?ª@•*í?ºÜÜÇÃj¯üs0&lìú¥¿ú_Ñ{×ù]=Ì>ì¶Òüݍ"Ñ ºôŒQpx“E`™ø ‘)ʅTWq[öîÚÛ»Ã׌ãK~Ž­Ü¿“ôw­-{‡žÛŸ˜k×hҎÙ3›U¶+TEy}v\Š•à/ïÛ8#òt‹Íç÷ô:³êëþÃwQ"ŠR÷°•[öùº^úίư·ŠŽ­Ûtà^_þ>düÚ!ՉÜ.û΁ŸÏ÷Ûwe}ë­ßFõ5|„âŸ&J9Ýís§®ÕŸºjâîÕU_…÷9]¶û¯›fÔdõ™ŒFZºñN ÂpèСµk׺»»+•ÊŠM›_5DyFä-Shۏ–-[¶lÙòÚµkwîÜINNNKK€ÌÌÌb‹B†a †b„Vä­ÉQéޖÌ쬄h‡] ÙȔº+iBæZlW+% 83ùr#J%á£W®ÚžŠ•ƒþŒJÒќkYñÒö]lí,ððÍ¿í±0Iœ[M‚0¬FÂÊøŒÄ—Œr ˜Ö1ë&£q7îIÁð$ À5pàøn|Ù¯÷J6ë¿hDO_ųy°cˆ(€MÝ® ÿÜ4ŽérxV=ê¹³§WI¶óT*m ˆT$R“Î l3oúÄæaJ]fgǍŒ‘>Ÿ²Mä<{M÷0G @ØØ cÆy®äŒi7–Ž˜K*PÁ,s hбÀòµþóЉ‡ƒKøˆ#W«€ømë/[“€š €ÛI: Ê6VÄڐvãɜ̪Õw €J}{DŒ3èµ€˜ßÖmüÏè.«ž—¢7‹ÄnÞáDiçæâèÔ|çþÕmJ_ÖH!u¿èßhÿO»nêÆžéMâˆ&SnjnWZ `ªÒ¶ñÚ5ŠÐUnÔæË†,ÅüÊkè†Ñh4§Nzôè‘Z­Ž‰‰©^œúçv'4Æ3BŸiBCŽë‰ÂÃÃÃÃÃ_çƒÓ§O·²3å€öÞ¥ÅÎN¥41vºšxë—_wkV²Ö•uGµŒÊ-Ð=¯ Y‘Ë™D%\Àd2ôz†(X@–&¿ ž@$‹!x}Èð$ [>EÍf}Šå„PJ‰ Ñ§=Ê4Öî9ªiÖÌóŒÙ,X XV„ `ôÉi:‰KDŸ15"ì,ír‰T f•ãóc @©`ÓuåOì„ù{¯øzížk+YØ4Hà ™&b BÖüÍ:ÂôÔÃÙÎ^Æ€^ŸÁ󎈈@•°ôÙáQòX™å`†3›Íf \ÛÆ’¯Æìß/gžËÀ@©`æ3„jîÇ¢Œª=` Ÿ—Ëמ]Ø%ê•ñL)͵¥gϞ–› €e?¯ÀÂxFœ @¹P¹°bȜŠ?}³"2æ¢Ô?Âǎ܉9ñ˜x” ÷‘çqAž!2ôŒ%õF­I°Ô/Í>=Ãl®qÇ×N ]=ºéßÌO€ŸÓ£qž93=ƒ5ò”zÍ,þŠíµå‰b£pÓŠëRû4ùsv—ú·Ë†˜5|:+µÍ0AÞ©ÿè»±c'}YyMp )éAÍ¡³{5šd+ʕ @± ª7oÄW#çÕšy²–3«Sžù˜0%ióÔyûôŸ¿·]·ªÅú5ïëYÅTS»×ãuê Æ PHêÆîœÎ88ØÊt§‡'µ ©=qz×îÎ]‡ŒŸâJM™j‰oÈÔdjM† êtÞ`6Q.lîÂi£–ìûaÌrg‘›/5§i>¥ïÚ ^Ùe+~ó /]¡8€cp‹²ÊÿMé{j©ØC¹Ã¿Ã;,Û²­“!2 –ÒæuéZ# *_«mí-1ÿš}À¿$CÒÓN—idì•qÙ³xT“mNÞ x¹q]ßóu™–m¿Ӻß!3VÕn8œ‡oÆ7h±5ܔòàazؘ±Cœ®èuÆ`9ä †#Ó¿ýãæ¹»øŒÚ«Mã * ÷ÊCF†a¶oßÞ»woœ^ϲ,¥”çy©TzöìÙÏê—%š4iî_Š€{÷îݺu«^œzXš@=zŽJ•*¢WßZîL’ÚórÛ÷ó¢U‡/x•*ïÁ¥^:s…:”/å%fòºY‹Øƒß$ç IDATyù”._)ÈENÖѧxéÈò~b‰<‹—«\!4ÈEêâ]ŠNYo7{…k@HÙ*QNJ…‹ohÙJÁÞNb)^ÎÏEáèèQ©ÕÀ¯Û×*Zºt #§p)UÆÓFââYŒn³Ž}{5.^2ÐÏYîXŸNˆ›“JŠpñ-^²RTe_g[–䮯S +ó¯[­lš Ë:s÷ /Y6$PDÄ¡5ZŽ©& )êçáìãébëâR¶bˆ·“X$– ”s°³sò®ÕoðІ¡0"©[É ž6nÅŒJ•)ãbcã^¢tDXˆ«R$±-æVŸT¯”ɝ#ÊW®TÒ^)q‰ŒnÚšŒ¯·ÍÎã*dþžüléñc©òjt ÄÆÓ»dT™–”òs€Ô5¢T°œÊÑÙ3žõð!õCýTNþ•ª–põò-SŸb “”a%Îþa¥Ë–õ±ã.ޑeƒ}m¥®>eŸèÜ©c»Úå"‚ŒÝ}ÂBƒìœ܂šО\I'ß •‹û–ˆòñ±s¶s¯TÙÍÖ6€fT˜#CÅ>ÁQ_ôÔ®® V9ù…D–*à p¬R¡°-V±s¯am*;+8+7Àh4š'N›L&‡°°0777WWWWWWwwwggçÆ׬YS¡P|.[8*HÑpøðá]»výðÃXš@M:uÔšQb±8Wk$!@žñï-{Ž¥hY(ÏÚT¬U¯NÕ`ižM˜Ï";gx¿äV{°ÈqŸ²ÕÔÏóŸmëýaX{ö·~¿ø‘æ^5¥çɔçRüÝ®Ã"¿rí£Cҏ,_Žz›Ï×'wŽ­×¹?ûêîIòù^keœÏt ÿÂÌ£“ë«áɓ'sæÌiÙ²¥Á`°±± ËkTòÏgŽ lÜFœóaþ³›µïð:Ã+=žÿH­Är¥“³“8¿œô(×îÜÒãI®ÀÎñŽì›ÄrŸòlŽ—?“×ԈõYËû{_üÈ 3¹æ'÷ÌP äYÈæ¹Ô.µK»Þxüß᧺E›‰ÿû²K€ç̳Ÿÿ•ã+_JÑÜßkm9s”kîã¡ìoVʒä3+VÞcÏóZ­6¯xÆN=Bè!œÒ+ ø«*Ko6å|öÍÙOäý¶×üãÍŸ÷•Ÿz£ë•CÜcð÷©é‘²2ggûŠUÆaÞª|­O!÷BœF œÙÒ#Œg„PA$ôg]ÙyO¥H)±2{g™=Xm2@Ÿ ± !ôfrxF}”ó9dsöÝSkÏ¡·!ÂôéÓ-a0ŒF#– zw&“  0žBooäȑ٣Ý»wïÁƒžKEïÃ0xއñŒz”R™L–ý§L&“H$ŸÛ@š@70,Œg„ÐË5,ŽegŠ»T„!ñŒú„888Œr|h„Þ4›9ŽËÙHƒñŒBoV“¶·····Ç¢@”ÓŸù‘ž4B!ô)ÿ}æ%€ñŒBa<#„Bã!„ÂxF!„Æ3B!„ñŒ>Ø-ÀçYÚ~N>â²ɍ¹E Þ÷Œ¬üÂ-·4œ;wî¿ÿþÃ. ®œÃªV­j)ù£ßF’=/^<~üx®wBH—.]d2ÙG\jBȁîܹS4"R«V­ÀÀ@üea<£"žÍGŽY¶lYjjª­­-’ÄÎT«Õîß¿?--­I“&=¡³¿ýرcK—.MJJ²³³+ õNyòäɝ;w†îââò|РAŽŽŽžžžÙƒ|Rb±ø?þ˜2eÊðáÃñDžñŒŠr6ïÞœ{Ñ¢E-ZŽèÓ§KÁÙºuë¢E‹ÒÓÓ;uêô:û{÷íÛ·`Á‚ƍ0 @¿133³W¯^#FŒ˜={öGLhBÈòåËCBBŠÀ¶Ô¯_¿Â~rÁvK”{œgϞE‹µjÕʒÍXu. Ò€Ö­[÷îÝ{ýúõ6l°€ÅG9ûkYïû÷ï_°`AÓŠM-Ù\psB)•Ëå˖-ã8nðàÁIIIeÁ-®V«‹Æe0rÀ_.Æ3*RÙŒwïÞùóç·nݺW¯^cT¢×ôšÁÐ={ö\·nÝGIèìõ~àÀ9sæ4oÞŒ_¿~PÀÝ[–Q¥R͛7ÏÞÞŸgϞÉÉÉ+¡‹Ò•™™i4SSSµZ­ Ø)fa‡ÛèÙo[„ƒΜ9³K—.=zôÈÞGBV®\¹k×®ü?îëë;wîÜO»{JéóŽ|_9«”Â+^§ïÔ-pvkvëÖ­ !K–,!„ŽoßþC^‹gYïGŽ™:uj§N²É z%Z–ÝÆÆfæÌ™ãÇïØ±ãÆð—øö5-†yúôé͛7µZ­£££^ԉñŒŠˆ›7oΙ3gøðá7εÞŽi“§§g­ZµL&“ÕÏêtºŒ9ÒÍÍ퓍[KûI7OŒžì_±fp1iŸõI f}üï?nz€”ËÃrcTëy“Îlï\³YméûI)BH«V­ììì,Xàåå-B>ûÖ÷Ÿwïޝ1cưaÚ6m p˜ ì„þî»ïV¬XÑ­[·;vŒÆ1ÅJa^åi04F£quuå8 ãÉÉÉqqqyí£›5kÖ¢E‹Œ>k2™ ”ðaã™ ±1qz—Ò%Ý9öµê ‰ÿî\±áRCªyÄ3!„Æ_=ù˜ø— vŠŒúÖÕs·ävrcúœ³»ïdT®ÛÔOŸ€sÕ++Ñ÷¶ –Ò®U«Öìٳϟ?Í0ÌÀOŸ>mµ•â·ß~{…˜ššÛŒyó¿ï¶,»­­m¿~ýFŽi0$I\\\‡ÌfsÎ9±Ž{O›6­nݺøSͧ< !666“&MºråÊË«ÒÕÕuûöíXPÏšðý¶Y–µº&„Æ|>«×ë !ù5ŠYm ¶’y¶[}/r§ÿÐîõ'Ÿ ó䀌*\üšôSEoã¡Èk> íŸ2fç­`NÐcâw†ÍÃí‹bƶ˜4¡±&E/Q9ºÊžÇÆ+*|/ÍT®eÉNh±XüäɓøøxmÛ¶Mš4É××7çYœ^ߢE‹÷ÏV×ûËÕ÷ìWsÍ|^ÏçœH>S³ü+‰!·nÝòööNOO¿zõêŸ}ûr^Ž¥T*GŒqíÚµϯ:©‘œÞ­l»¹ž²vžc} Ïg»‡WOóÇrí‘s[èê\,žM¯y73(!DÐ=Þ8ºgEOO—bÎ~Þ©&$ýì/C/žœ>y|#OŸ / DpÞÀÙ{ÎìÞ$¬tÇX£i÷â‘eštþñªÚ©wÏ:pàv²®ÿŸxùÿöÆ\Õ€fYOïzËÝà yžVŸË7c‡ôo^¢ÄœýIn>~Ÿ^ž>Þ^N*‰£‡£m1?óœ=Ó'MÜ}-ÝR_I:³~Ü÷«/<ΞðóÔy9¶vdùˆþÍ֟IK6ó÷—öòñð*UkðùTK[/sžçúodÅ2AþþþþÜÔBš@ïØØÎÛËÓÇ·z£gÓ!$óé͙Ã:º¹»yzÖ2sçS=O!`>ŸŠCt7÷.?­_6`À¢j#°f` O`™Š=O&ZÙx¬þࢣ£kÕªU¯^œ§OŸf#îÜ0žÑG@)}Ç·\.çyŸ@æBàԀ᭫ÒùÖÿaÉÒ)j»:ŠY0þ^%ªÍ€»='.Xé4ZøÃÏG“ÚÎ]ŸjîÌšâD¥OHyFêW¹bÇñ¢K¹0ñÇWMìPeƌî"Ö%§$Ñ Vý8œøÚœIÃÏ@ÆÝ3{ÿu)Uí£× o9øÏ°6ýº–=5¶ÕšÉ&Û 2• ªW«ËøñåýÙ©)ð&JŸÝWª17nýõ—¿2ÒWÍ]zá~ªÊA¥Ÿ»géW5£·j; ×6ðV¿Æ{ïiÏ š:Nßsõ† ýïtj>ø!!4¯Œ!..Î`0Œ|Šßh4Ÿ÷ƒ'™LfuœÇÅÅ]¿~=&&æÎ;gΜəßgΜ9wî\LLÌ©S§ npŠ÷•ÿüçNŠ&$švÃhxR®nË¥é ǯÏ3ßdT@éÀE'÷œKmS%qçîãòªøKàNbʜڣ~?¬ªŸÓ¢øeûʋöܪRíìøž‡#êZ«¬SÆÕÍ_þxúÑBOw’ÏŸÕl6€­­mHHÈdz[€ ÞqãΝ;'‰,ÇdÇétº·ŽíŒŒŒàà`+Gî9š£ûöí;|øðìæèì3<ÏK$’ìÍþȶmÛlmm-‡Œ„ŒŒŒì—t:]>õ`³Ù,‘H.]ºnccjµzùòå ,Ø¿¿åLŠåæiœ^ÿÖUj‘H”””€PX;ÍAA§h5õ¿…]ŽwMçßü·Áúƒß —Ò®dþûøžâWŸ=̅Öm_œ^9;ﵳ֞œ~¯SŽôé{Gƒô‹‚«×«^_  †ô»Ož^ã¥e¢›D‹€§\C*õ+U•H°ÙóÓܵ±‰OÀ¬™uâp¹q³‡÷éè¥"UÝÓ·VÚÈP¢‹Ý3:6®ÿì.µJ»’»«W;~>¯^×2™ì·ß~5jT||Œ\.;vìøñãq?‰ñŒ>£Ñ5g̜ûÁ7ØXöĉ£F*°i(±÷.æä(N,`ÍiZ©Œ§”e"v(LšÎDA rbS§Y}WLŒHÄ0Œ 2Ô=zè­ójM o³tÁŒ¯jp †ŽeY*@tZ*ðÆ€m Ÿm;jƒœ—R.õ-c"YMF–ŠtSxTåªaRC #¶TKšD"‰¬Ÿ‰¹·kŸï;o¹¡¹¹Ó]£ÍBEÿ’%Š9ˆYl"òToÕýŸIÐ LFÁÞœ®êõ~v–ŠfεÌqÜ÷ߟšš Ç?~|ǎ ,xëõ~öìÙþýû¿ü’Á`È~þ|Ίì|˜LŠR¥J=~ü8ûÔµ««k·nݺví:|øp­V J¥²uëÖsæÌ±t:öËnoo¬ÓéòoŠVµšîRÖ¬g¥n2»š‘r£R$³a2(QڞY?«òÖù 1ŒÒaœÌnßZ}¥Fïò¿O–4žxrÕè`GVêXnúÚo;~ÙZµÈ;ª×»Š}a/cÊõïÇ~=uõo/>)Y\‰åÁdN7E†ø;ª(ý\–š`n›°„ð|Ørà¢T*6lh™BÓŠM»vízîÜ9–e !þþþ<ÏBN:uúô锔˕hùw?iù–\‰"‚\.‹Åb±8»úkkkkgg÷Ö[eöÙq«žgÅB©™-cYõ–kÂx“^ò€æ éK'í-6ð”‘H¥,€¢B§œÉ-]ÞÝ­rçș¥3g5fXy…®“.4íꏟz üú‹RuuZûãÄmqÊÓÉOJ=ÙÜŸóbƒÉ f öQŠÚĈàÁ©SŒI „˜Žé0ÿTB¯¬‘FÄÉd¯»ñ°,˲ì˜1c<==ßûy„ñŒ^»ùOIìu7¶¥»ù†õ˜7g–GÐ7_UHŸ~U\Œl_­þÉÐ «ª¯X‚}°hTF4°NgN 9/0 ×cN&òÎQåC¢ím—$ð&ÀƗ»1mSL—*сÎR–Xv¡@© Mº¯7 œyçßÃÿ[ýÓ€†àå«¿s4^SP‘Ê .Œ\¥WHq…„e'Že„° m]²ì¡_\ˆèY#ÊÅdg&Ìþ_hpߖÅO.ò?sÐöŠá*»ˆU§”Ÿ<6ÔÆô0îq °œruˆD¢—+»ìhO$EFFfo–‹à,åryƒ r5[xyyyzzæÜ&-/1 •sjoº1[Ò‚Ýh©õíxpýû,Z¿Ü§Ê7ʛݺ+õ uÖìÞyœx劁åª Š#L7wî{T¹QThh©Òz]ŒI|Š&õ‰Éì*Òþ^¹ãä¹³î ‚ªZ߃+3ÇxܙüýºZš o>©<©ìµ‰e]È£žXÞ-,Èî՛Aö™6mî )Œ4 |TSJmŒjíŠÉÅwNnàfï5øì­d3žþpçäp͔ÈbJ¹Cð7ñ#ÝŸï X.¶l "–Û2ŒLÌ£í¿ô¬Äe³c毇YÕW5z.vqÛW/ØeÚ¡{(!@€a¥ÁÑ]:z>j`ßð›µÇô{ºsNŸþÛt*…èùÞÿyp!¶G€zƒW1d^žƒbÙå̬l«"öYùL)SŸ}ýàŠöµ¢Ãj‡eÝíÍ3ÒH²¬}%%#«>hÛ¬ý6õ3ÒÀyON,;£œ‡­LåTœy§;&Ñ+KÛÁÁ!00ŒH*•ªTª°Þ³O33YrE&“C®dÍë#V_zyÙ9Ž»zõ*yÉÚµk-§¢?ø¯ˆpJb—]2‰ ö¢ÕëíšQÍQ&s ÿùðãN éRÊՆ‘|W²ÇßÃkP^—ޱmMW…ŽXÕWÚŒÙØ¡8ˆ<5jîû{ž³ýŒøô–MË®ñõÜ_/wÝ·gãíînšÂaü﫟“‰ ñü!åâ7µTñs)ìËÕjv]÷êlvtt¬X±âËe˜}•*4;bT:thĈï2…“'O†‡‡gddXþ!û¥zõê­_¿žRª³F¯×'&&ŠD¢‹/æ9õ¬É™ôú ­ñI]FFF†îåïÍù˜Z Œ6#Sà…¬×J)åõš 9ÇÛ!û± ÓhJ©À35:£ÙêÄ­|‘Y—‘¡ã_œVޝ€”Ò‡G×ð(=~áeJ)(¥tg 6>Ñ ™ZMföG²˜2Õ­!×d²dff6hÐ`„ Ǐ?xðà­[·^U–”RzìØ±!C†ŒËz?þ|HHˆZ­¶RÌò]<Ï_žpÁÆÆæäɓ‡:~üxrròë,{‹-?~ü.3râĉ—Ÿ‚浑XùÃdÐfhøkš×ëslÌÏÞnÌÌÔ>_õ”RʛzœÑ2]fЉç£Á`¶|âÐ$.lì!ÇÆ“¡Ñè_ž‘lœzõêÝ»÷ÿýwðàÁëׯçµ?äúEïkÏ虈ˆˆÞœ{ךQãúõëðâ='^^^;w&„È­‘ÉdÎÎίžB‡ËI]V"QÊÅ d_sE)©R©TJ_îâã…ê—e~#WÊC²ú… @)e$ ¥T„dµAòüv\©BN€a8™Bʉ¬¶¯æú" ”Š€J¥”Éêv<ç;³zîxŽlËÕø 5›¶ JÈEÙÙ}†Á,“+²»-!YuDVŠRÈÅYw¿Ð•G\\\‹-*W®l¹Ël6çŒ(ìýžÈÈ)88xȐ!ÑÑÑ×®]ƒ8&‡eÙAعsgµjÕ,X`¹RšWß±P7å[ù ë_÷òv@)V,W*²¶gËÆ(Q*¥97%àd2¹\œµÑRJq @Ke2–a޶©ëÝeÌäžUëOJüM{)—cãQ*’œO>Ìfs^eˆ=z"xî=ÛWJ$’Þœ{›LŠž={ZÁÍÞS¯\¹r„ IIIùô &Bþ=‹œœ‚äÅç^¹ã°šùÄlŽÞl÷”óNÞŒÞc”tì6¶­w°  –õR«–î%^ž2Qž ™ãìlŸ{÷î!Cìììºuë&•J ð=kë],÷èÑÃd2uïÞ}åʕaaa`äéìlÞ±cÇW_}5þüÀÀÀŒG>YVVëK…fmó|yË€$jÚÿ8uñVŒ®íìÃkZGÙÀË7`ºb<£ÏeÌqÜÀM&ÓÀ,XPªT)Ëó”Roooooï×Üí~G3 u ®•]C¶Éx…WözœrÈ~ÃíÛ·GÅq\Ϟ=-Ùüá{œfY¶OŸ>&“iÀ€ .Œˆˆ(ЄÎÎæ?þø£_¿~³g϶dóg<Š$¡”Êüª7ö«þùýšP^°qåÞS6¬N:#FŒžpáŒxÉî›Õ'ŠtYœÔèIò¬Æç]P·nÝ7nœÙlîׯŸ¥÷.ËZ‰DJ¥òCŽŲì Aƒš4iòõ×_ÇÄÄ誎|ãæÍ› 4cƌ   œÙ,‘Härù‡« °ì'²Eœã¯ ‡ÄÚ3ú,ÚÒ?É€I“zôèáììœÿ]ªèmŽ‹&==}Æ F£qРAR©4;¢†ñòòrww·ÜJôAζ>;&>|8Lž<¹GŊ+ õnéÀdƌSŠLÉ•Í …" @¥R}˜§”ž>}Úd2YŒ ïÁ¥R©Œ‹‹óññÁ_Æ3*ú =nÜžå˗>Üd2 ‚€lï=AšS§ÎèÑ£M&“%¢A‰D^^^>>>,›s%ôȑ#œœFŒQpëÝòEsçÎuvvÎn0°ds`` œœý[ðúõë/]ºÔ²øzœ>{d§BÇ2&XõêÕñHãý„&„ôîÝ»wïÞ>LLLÄÓ`Ád2Y: ¶d3˲žžžÞÞÞ8›s­÷îÝ»wïÞ=>>>!!¡àfC£Ñð<Ÿ}²ùÃg³ óæÍË9?±±±…÷ä7!$333gW¬ã̈́†¬+SœœœÔjubb"˜hTpgÉfËXå`(çzwttT«Õ `œ+•Ê   ;;»¹à¹NÖŠŠŠŠ¥¥kÓ,×râo ãýjŽT*õ÷÷gæí]@¯ÉÙÙÙÓÓó#fóËëÝÏϏa˰žbY??¿œÍ/ã8.»SñÂ~š'“ɰ­ ã}. íçç÷.ƒ÷¡WÖä ŧÍ/¯÷üÇ|/¹šP(>ú‚ÛÛÛ™q#8Ž{¹Ãv„ñŒŠfBK$ì°· }R'ø-ë=çQExÁ‹äŽ×‹`<£Ï"¡±>Ãrþ×ê%µ¡éÉ¥_þ8”€Ö{G6íP'8Ït€x£6éѝ˜˜8•Op¹È)þlÑKðNv„z§t&„@òåçÍÚ~9YÂ?^2Ö¬w !ÖÏ Н:ŸýëÑãgÏ]qâÒ]!ÂxF¡÷žÎp~óêm·Ýöë;`Ø·Ãëp;—­žoBòæÆÓ<>@)%x3Ï €ug„ñŒBš5Q²O5sŒœûñIy:^³…0žBèìG¥±Œ}–»7"Bž5ˆ¿ø&„0žBè]P€bíšú=ݺìèT€Ôÿ}·DÍŽ¬_B.ðéÛ§õí=çoBHfRìêñƒÆÿr†Bˆ`4™R'¥gfê22RŽ:£Q ù\è>GØ- Bœ=B)R²Ó”þ÷-ÒvŸÀgªKÿ°u›ˆ&þéå wµ€7fÆ_ŒôPdéÀ<óøöÕßÏܐ)á˜Ó7®_ÕcòwU’ã9i„ñŒBï)Ÿ-­h2fU•/Ÿ€™ÁÉÕEɱ(ÃÚµîh€Ò­Ôž­Qbé [QœÕ€ªÍûeOƒ‰°%a<#„Ðû h°Ü`åàîî`yŠRËÚ"–ËzÉ~ @FÄ08jʱ!„Ð{ i’+±ÂxF!„0žB!„ñŒBa<#„Bã!„BÏ!„Æ3B!„0žB!Œg„*\ ãQ8šÕg;õD}Ž!›6mºråJ¡ÈñlÖëõSŠLÁxÆxF¡Ï¢ýÝw߅……}ú³J)ýùçŸq•}VðÜ3BèógFS(fU­V“‡ÙÀóÐX{F!ôñ$A0™L–œV(‰‹ã!„ÐGÆóü74 ÇqŸŸŸÏÏ!„>>J©N§Óét`cc“ÏÛŽ6ñŒBèƒ!„°,{ëÖ­öíÛBrÆ0¥T„+VÔ«W ã!„Š`%¬V?)…\OS’ç‡sÖbóªÑZ{>ÏïÏNèôôt‘HtèÐ¡ŽŽ4–e !&“ÉÖÖ¶k×®÷ïßÇ5Xdà•Û!ôb—ftŽQ(=BÂýžzþè ›4„$^Ü·lî”Uëtª6dÖV peçìªá~ ©$¢ë”˜TBˆùÀ€/§þqƒBóµmßµšö!DûôÆúoûÏÛ²cvÏ "Μa×9×ҀbVßYܵi BÉq¢ñ뀛É+›Š)¥vvvÞÞÞááႠ$&&†‡‡ûøøžžžàÚÃxF¡_͕ÉdïÄ/= ”7ݛäRyʟ_l<úçì>Ž+Ÿ±ïŸ[zAlñ„žS6뚎Ð3êÈÈ-›n(óÅŒNî¬ŸŽ€†ë˜32DNmÚz/Í2‹)÷ÿµ?“úꞥÃû}œÉ§ß–E}ÇŸ6zl2ÀîÉ7?°¿ëàßl®[&˜}œÙΟ«êøñã›7o~^ïFE6n#„ %•JÕ¢E ‘Hô–U†ILLT(/¥>€^ÚõœÑ°ø¿ÅÍ"$âEšfÀŠ',€Q«Kt)ÙqЏ:–õʼngŽ8|H ?”]¶xCD—?Îw+ãF³MvR fÁÌ5›ÕR»ˆï~;Õ/ ƒK}4ñ×kGî%²™gâ4õû/›Ṯ¯š@³,«V«;wîüçŸÀ¹sçÖ¯_/‹q«ÀxF¡L£Ñ¬[·ÎÕÕõíjDž††jµZ+õrãE¥Ãý%–÷Im%”ê€/W×R%‚Ä`$~>>*pòqÀóBît%vÙU[‰€²§§eÇ+‹©`ÖhmºÎ˜:âîW3j—øŠxËeËgw¯æÿ:k6›mllvìØ1sæÌ˗/¯[·ŒF#nE 6n#„ mõ‚eY–åÞJ~Ó5éAžûÀšÑ^ûïËÙeՆ)1ó#ð·ÔI™–LÔ'RÁü| (5Æßÿ“8=«†!bËc†‚Hʂ˜Á6lÒޓIÉG*/ô²ê£7ëŬZµjmÚŽÁ-ã!„Š8`Q¯oèY¡ñœsú6ö°ä˜"»N›US·-ÕÑ7äÀšíë\Wký2¹oRrýº¡Ÿ,ðf5wäÈы·®®ÙnŸDæ âD†„ÇۆÎ<ó0åÑÅk·ìPFÖ®"=ÿÏ¡¿_1Ú‹«äŒ˜’×Ú'[Æð0 åʕkÔš‘Á`žçqõa<#„PÑD aå%§]žÙÃnß/{\{ü¹òÛf险<#Ker±ÈÒt-iýóºåL‹[Ûª<ŸÜQeÕÙUÕmØ&3çØïý&2$b@æÀ5³êsZ”‚È鉮ގ_<ð¬1wÞ0àþ±¶oÕ0W¬sœë¬‘#\寜C©Tzá–e•J¥\.—ËåJ¥’eÙmÛ¶ÙÙÙá,2ðÜ3Bå¬=SJuºK·™?‘r)·Îø}“S…]ŽP»Ïµû@ö\ÄŸÝÌ=ífR“QàĖ+Ô(¥P,º_Šº¯ÉGvÞÄ3àÖkÙÞÅ5& œ%²©ŽÉܟ›Ìý™7 "ŽÉžB>÷V™Íæ°°0FóòEmõyì5 ã!„Š Á˜ŽÌß}|.CÂT¶üxÓ¹ÁÒEµ!G7$Yùg‰BbÉægg8î…€$zNwËöFf:€"+›Ÿ¿Ù’ÍÙSxÅì ‚V«Í+ž1›1žBšh֟±ËWwφü{).Y>ïHÝúÕ\åVk¥/<ñ<‰_z2¿}vý,r·ÏõöœïÁdEÏ!d%†ŒJ7mW:דï0IËl‚ËVl|FÏ!ôJ/wåaœ+±w Të•ì7‚ÃGb<#„ÐgTQÞ¹sçœ{÷xž'¯sÖ÷#!„hµZËÍTã!„ŠžöíÛÿóÏ?ÿüó!$33S£Ñ|ÊsÛ€I³ÙŒk ã!„Š2A&L˜ý§F£‰ý”kš”ÒŒŒ \qÏ!T”1Ì 2¥ŠŠŠ¥¥}úƒ>QJAÀÁ©0žBè³ ‘Hlmm EìYºÇU†ñŒBEŸÝ;ŽýÁBðBnŒg„*ú(¥b±žp—Œ÷Oc<#„P÷Š9g‰F!õÎÆÿýsó‘{D£îj:ˆEÖ#“xCòÃ[çÎßHÖ;5jWÝöƒÏ3ÂxF¡"^Ù&„€úÎúŸæü§ªâ|pǪzvVתv2–Rx©ëO0=¹wtà°y (Óžv»êXˆè•p@I„z³t€Ø#»wŸ£[uë?pä䮥îÙpþQ*@ˆÕ‹Ë•SP¯ŸƒŸhXBgÔ`µa<#„PA€sæ¹÷Ÿò"ÂFT¯eÏ<Œ¹—bà!kP«œFiëÛ°nå’>f»AÏ!ôŸÈ|—ôØÎÅÁ^ÁØùúË¥×cŸMÖz5!”RKƒ7Ïóx=ÂxF¡›̂Y u›4•0äiBª™ç­zÖðÐXpã!„ pÇÉáX #b³*ÈõôŽgY– ÂxF¡DáîïP,á^ZBº@{[¯öñt‹¬íQiV_d a ’uv{æDÏ!ôŸPej¡Ž·÷#š¥T¢R¹ªTϲ6¯š}Óç<÷ŒBoјµã!„ÂxF!„Æ3B!„0žB!Œg„Ba<#„BÏ!„ÂxF!„0žBš}ʰSO„ÐgY5a˜e˖9sŠ0ŽëH©R¥J÷îÝq=b<#„PQ³`Á‚êÕ«/^ŒpUCE"ѹsç~úé'ŒgŒg„*‚!ýúõ‹ˆˆ(ts~äȑѣGã,ÚðÜ3BèógNWç\§Ó1Ì {ïÂØD°öŒBÌó¡%ódòu'@ˆµ ƒÁ`2™RRR8ŽS©TÇaÑcí!„P>uráéãۏŸjßzIBÍLŒs;A”PëoÐjµ7oތ}ðà^¯ÇrÇxF!”?aOTŠ[oŒÓ4žî«W§ì¥Täñ‚  ƒÁÀ0ŒJ¥Ê§"Žëã!„€Ñ힫ámr1GšÒ»÷\Í<É¿’­P(6lØ R©ìíír°³³³··ë<úèðÜ3Bå H°šhùŸH¶Äjöˆ‚(VÏSJsŒó…§ y>9'b,Ӏü:>>ŸC‡sçÎU«ÕÇ ‚ ‚§§'6zcí!„ŠB(oJÙ4žùèõ{× ­Lˆ,°L÷÷Œ„ÍË£:Õ$„âßvØú'‚þÄÒþ_Ž]tåI&!„ry}ÿ&Ãþ§ŠÏT!áìî$Š_ÿ›YÅÀ»ïØi·{ü4ퟔ†Ñ‘5»FÖ ·oØ)™êR@ûtêý؎3f|Q»ŒWfýù•›—ŒÖ l©Tzá…Ν;_Ÿ|yϞ=_|ñźuëÞºdÆ3Bœ=F³eËgg緞BhhšV«µŸgd˜®Å²kÙD$þÉɁý.ÛvÛÃKIQVaLxÎîæ]gÀß7»×ø{ØæÒcW…;ÈžwÊÉe"ŠT eJ"1«tŠÂu†ÍÝ# Y»'Þˋ>Mµi* f# *áâ(eè›T›õz}DDÄ¥K—6lØ«W¯V­Z˜QøááBš°âyŸà&nŠ–x£fqœÿpõ¢É‡3üîД‡G~ª_ÜWg4"Ú}zô›ÞͧÞwêóE¹ô…ªY§&ü…[O,³«Óg€bË}É~«·Îö’;5hÖ1,ópœ2åþ`T_õ¬ÿ׎…›·_ õÇ7Pš€;E»*%–ÄTóvQ‰@â±ðÚÎv7GU(R­ó"M“µ7µV­Ûû&î®^wÏ.ÑŒ›õë~ý7[V6žÑŠzÝî·×nœëãí)~ÕšRêîîþË/¿žººùùù9:: ‰D‚«²ðÂsÏ!”+ôÀ˜5Çþޝm±AHü«õÞÓ;û™É+ž=8þ÷/z¶Gƒ0?™Èrÿ²šÃÆžY·2Ë}ª-;£[öühJ)SŒÎm†dOjê/–ÿ}ö»ýd³žŸ÷}ØZ­¶sçÎ3gÎÌ'¿±g¬=#„P©;s ~ñFuŽŒBrö™ã¬°îâÌ]ÊF3[•ôP}Þ³BHv?`YƒdXzÔ¶:)úBœÏþÈ?[ !F£1===Ÿ7àúÄÚ3B‰Z gÓ|ߊöî/f\΀{þHà,XS¬dq[  $÷Ùâò1ëë“z1J1X1žB=¯Ž°Ÿ¡åà5Z†)¥ŒÒ=¬Œûó:6f*ÂxF¡wKb*“É wm÷ *°äÞýþŒ<Ûã!„ŠN<¯X±¢D‰<Ï3 CrŒHñ)‰DçϟÇz:Æ3BM 8}úôéÓ§†Q«Õjµº°ŒŽLiÞŒ¹Á`À•ˆñŒBEŠ ÌþS­VÇÆÆ–x³Ù¬Óép=b<#„P‘’kÄˆŽŽ4µZ]èú©Š”bßÚÏ!TdÉd2‡BT{ÎnP(ï8°&ÂxF¡O”B¡(t}lQJ†‹Åž1žBšš¡”rÇq\¡^Œ–ã!„Š”· 6K"š_°bãÕžßšNߪ­bˆõn²)Þ€}|ûÒñãWÊÀæíªÙ|ìE@Ÿ2ìs!„Þ& !x~ޜ™'2œÔ*}bûâÁ+þÕy ÄÊ)lúëçwuë?fñêÍWn?à±֞B蜧38¿ó÷#ñ~ÇtjPÚ-ÌV=téê‹-"ÊS2„Zª™õ,^uúŽbgo»¢×b"¬=#„ÐûOgõ‰ëOœ"J•ôs!@B*אҞÓw3x¬d3‘­­{ù²Å‹ÙË+Ïã!„Þ7êÛqéIÅ\•ÀÑ/HÌ^ŸõØúÈ„RjÉlJŠˆ0žBš`Œ@^²Î4ó,Cž&€ ÖožÆ‹·Æ3B}")–“ˆQV™§þ~N¹ú#Cã!„> •o°Ó›‰)&€ÄË7Mú@/&»šœ£MéóÉDÀ<¶t#Œg„zO(P6n&ÙŽÿ¿+SÂoÓV€ ë•°çŒØ¬#ĬOX7¢]Çiû !„œ&.öþÃäT}†æîœ§ÉijÛŒQðÆ*„zs„P .Õ~’6wÙðͳ͌©ÂŒ ý}m$FCj:Ÿa$@Áœ&€ ŒwbþüzØ"£ ±ƒ;îoÔœÿ€^-l±0Æ3BœÏ€Š€l»on:<Ý`¶³·YªÕTÜjáîV–¶Ì¥çš}=ŸµaKƒ+wØ}²C®Z8Å«ÆÆ3BœÏ€&@)eårGyV֒Y›#uóL`Œf”<÷ŒBïјµã!„ÂxF!„Æ3B!„0žB!Œg„Ba<#„BÏ!„ÂxF}ŠxžÇB@Ï!ôiñññá8ÞvÌ'AŠ@!¥@Va§ž¡BÉ`0˜L&xÛ®º†™6mÚñãÇ ã²[:mÚŽi¿~ýpKÀxF¡OKRR’‹‹ ÃŒe+à† ÚŽiZèÚÉÅbñÁƒÿýwŒgŒg„úŽÞœ{·D‰oÏвeË2eÊÊ}7ËÆÆÆâfP„á¹g„P¡TŸ|ù˜˜KÅ÷íN?B C!]|“É”ëžäí a<#„ÐûT­Zµëׯ'$$XNÄäWќÉ÷é€`ffŠN§{ôèQRR’ÉdÂá²0žBèã‰D 6\¿~}ÁÇ!„è3ÓîÝœœfüDRaFsëÖ­Û·oÇÇÇÞf„ñŒ*:,UØ:Üœ{w˖- R›|`ïÈ=Ç]Íø G_ó}f³ÙÒÊ­T*ó/+„ñŒBÎR…å8nÚŽiK–,9zô(!€@sH°5Øûdxñ¢²päöÑmۏß„W/‘J¥ZŒx1!Dü"Žã†ILLÄFoŒg„úÐh—ß~ûmþüù{öì±äл†t^Ÿg@Äѳ·Œq •Z«çó©ó­ºµþ÷a^k‰ž>}úí·ßÆôôôŒŒ µZžžn2™T*ö­†ñŒBºÐ˖-Û²eËäɓrVß"ª)!„RããÃkBX7¿–ûï^újݱ•Ã] !œ§oOÒ!äà·íF,ÿc÷¢.r)CHõw’Îý6’¢°uZt ŽBˆ9þäÊ6¥!²š&ß\L¢„+gLš:{ˆ*‡:âà³Þ,ð|Zr•ŽßüŒjj 4Çԝ賹„®ºŠ@yÖÅ+bíçž?þ Á`̖ žH֔€ѧOuf}eBg/þ Aƒüüüp{ÀxF¡"ó`ÞjB±é#*µ“ïZ\aHNÍð¯ÑԆPžçÞ L@—*Ž Ù0ZVlPï(þi,øGUõÁÌg>(0YC=RÁlŠL©r-›=Ú<žþ°Ù?urÔ?ÍàÊFG‰@àŸß>Ey35€[„ÇÍï–lib[«|•è•Áüøñãžž8­VŠÑh®^œjcc£Óép…b<#„PQ@0Ï1ŽËÖÕµ-õ /7¿zS•“OP°«’€Rƒ'ÿR’Žž4­}s–7f\º­ršœD w;–9•)]ə‰[Ù2a"ÛRµçÝY;yh·^­6ošÕuPHt”²˜_ ŸÒF€Ä! "2ÓÅFÂT볺òŸã:··ëz¿2¶ùÌ0ÏóAAA¿þúëΝ;s]µîáá!‹qÖ#E<9Q4>|x×®]?üðÅgåøñã›7ož?>Å[ ]µjU¥J•^Ìg«b=o^Š”ZiJ§É=œ“¢”Zù”„Éz] YsN-¯9Úºuë”)SV¯^––æêê’çG÷IŽ ÞX…B9ë,„ä:-M)Íqê—BÈKo äÅ äzdùØËŸbrŒÎ䜇ço}1ª­Î¯^¯ÏÈÈÈwÆ3B‘ŒÎ/ß^ù†·›¬•W1]1žB!„ñŒB¥ôånI ¹\ŽWmxå6Bèóç)SŠøùù ‚À0L!ꡚeÙ³gÏ2 ƒ-ßÏ!TÔL˜0áÒ¥K”R‘H”–––ššZX꣔R[[Ûèèhœ^ëã!„ŠTÕ¹C‡:t°ü™ššzûöíÂÕ\l6› ®JŒg„*:r5 gddh4A ݂‚ ž‡ÆxF¡"H.—;99Ɛ³\àfïa<#„P‘bgg§T* éÌ3 cuÐL„ñŒB…¥”eÙžpØygƒ÷=#„>wo=¥ñaÌ÷c¶jÙrØ¿'̖ ÑR Œg„*RõmB$œ3{ÆYÞÿ«îÍïÿ»¶ÏÂé™f /ÒBÏ!ôqÒÎïÙõßÓÀ¯:thܬۂ!5L‡ÖÇ$šyBšÕÚ6}©ò×Ÿa<#„ÐÛ¥sú™; ö!%}À³L—s7ÝÄy9›æôž³;·ïº—B£:öô±Cÿ^IÕñ„àØŸ(7Œ4 !„Þ €Œžÿ³wßñUSmÀŸ“q÷íÞ»tA[@ö”!{ˆ,eoQ*_d‰,¡ 2TDöPŠÈ•²[ -«tÏÛ;“œ÷”ZJËl¡Àóý£Ÿ;3NÒüò$¹'·²’Cô*ÀÞ/D©ŒwGhàá³1J IDATlѲ‡’)ö؏C?YnãÖ¿ö»ßµ»òëÚ}Ñ,uá?Ñ;ÂMAïv„Õ3B¡Ç© )$IÊ/z†@ZzNI›ØrÒ.ùݯÓÿvìXÝÍ'iéèa$»,\·}Û¢Q^·“.þ{ 0›Æ3B=-NÅžS0 ›×¢Hƒ*ž²¥s‘ƒÕ”2:­CxžCH‹6=k2F£E,:œRÅS*b‹¢¢«6B=^å @4~á®c’’2,žžJH:k17õuåXFŽYl”U*8 TŽYEÂ)y–p»¶[÷ȱW¬”ú g”€œÿcë®#×ÓÌ%Ä-¡Ôœ}튷å÷…ì޳¿l8XÊ}¶hµÚ+VšÕjRœ7nàAo„ñŒÊ/×!C† ©Zµêܹså„(’Џ؄\X2x«ãSGEžYNíÙžzíw[öž¯ØëÇU5×ÌÚq €”PbŠ‚ ‚(J’<^¹ê€’$Š¢ È/SJ%Q’(•$ADQ”ò'’RJ%QÌñî«·Ÿ^:꫟çˆ@)P*MQ •,Ú¿ßû\6•(um0ïlÒú·ÝäI(øŒ<¢ü1I’<ùFé @VVÖØ±cé}ÜÝݱ7„ñŒú¯Ž”3¥ÿþU«V6mÚîÝ»F£(ŠÒ݀|@IWâ[ÂÙñ?ûnÙ¿u…;ƒÃ«Ìܝ %®êÜòûë™b÷šÉßý]l“cŠöiÆó<Ï;7è8óß$3ü»büž©ó6|;¹J°3Ï»|žô°ÁJ„_†Œ1lÙÎ-sßåy^­©œòÏɚø÷–÷^åy^Põ£ÕGrÌ1»çÄý™ðûæ Aúw>úæ¶®í^èçáÄó<ÏW›º)Z8·fÔÇâ ®µígH’ÏÍïÛfÆÁdB€Œó;—4¯ìÍóŒãk-¿ÞsÑ(ýâýæ®þ%ê# ÏûMÝt^€ð( BüÛo¿=þ<®„ã!TbBBzõê5zôè}ûö9òÛo¿=uêTbb¢Á`È)Annnnnnñ㍞àöuêÕ¯zbbÛ°YßÌÛoÈGz•+PIéÎnŠÍ-.¶Lf¡Z“÷£S q‡?PYœbá`€›»çí5ÿÚšUû7wZ2bå¹€<Κs*jx»ÞG*ÿyîiÍ£?xk õÌÎ!µÞ‰VMž‘—yhn›{vPöfßJµë5™ŒçÄ̱Ý<ÔBRš&jûñLc֖O¯Lëöc¢U j1`(5§|±þô‰î5ìÆÜ[ñ§/X8»z^ŸvSÞü6՜²î]ÍôÖ}¬ŸDž²ñ³~¿“Vþv|õ ÃŽn+¯ <ÎÁéU«V1[Œiš‚Õ”Wçœ_–.êj—ï9ÎßyÇ`ÐYD‰ïŸ6û‡Þ<•ž–§ý#Qú8õüÑßü«îß6ÀWŸ]>îú܊K«cèáu\ý”®!«‡xqРw¿ŽÔäìt#À_ ¹Ô×§j&àS5$$23@AX'†H:xùŸÜ–m¿˜ßօ‡öŸÌny í±ž©.XMæfÎü0µªŸÔæ}vù©Ä\äüðÖV*•çΝ0`À©S§þüóÏ?þøcŊE~Æ3B(?háîq׀€€€€€GùVVVÖúõë‹Ù4Øyžsö<Ïjhj®17×zî—y¡Ul’9ùÏC·ëœiWÌØÅä+G&µ+5¢‚6=Ç¥ G8!Gšä¥W€É˜I%‚0 eK¯w®ÂH¢`6fâ­d€SÛi˜µé†}%:¶ûÕÄAÕ9;ïŠ9ÂíýÛ¿§~ÕŸÞ"Bykώ}ÛöýÝeÉìŠ)~Ùmî8žYŐÈcÿn>uøDH›>Ն;7n9Öj_ÛGíúZýªü¹Ÿ¿ùn㟳–Z=뜊~ @VÂÙÏz¯W Ò)!çöÙž{7tá‹)ZÒÒÒΝ;B)5 ǎÛµk×þýûwïÞœwïÞ}ûömÛ¶ÍÛÛûý÷ß×jµžR¡Ò9†}ÜŒ:ŽsçÎ9sæ`S Ç’˜˜že˖#F- åNŒ3£GšpQ z³z'9>Žôœ0 ’ƒŠ¹¿Ê€”>ìønáŽÁ)ùá=œ…ßu8¥ôɏKr/b÷SLXa—/_^¿~}«V­Ìf³››[ddä£Ì#BO/ C·ç.ÿX˱êüÕ»î\>uâïkyœË태Ž| ÝvroÌô[RðjáÜ*xxO˜HþBŠFè»wãôžÝƒBfŠ~ùî0™{G{߄•Ô,‹%''ÇÎή€àʃ0žBežÐ@ˆgÅڝ*Ö~„Bùž˜{Òĺ/¯‹‹Ðû㎄¯=›a<#„^ž„Æ ¡ç¯ÜFè•ß `£T*±VÏ¡gêÖ­[¿þú«ÜG· x¹h„ÔÔTŒæ a<#„žGGÇ·ß~[Ÿ±ÙlŸuëVnn.ÖӅQJU*Uåʕ¹—„0žBeà.z2xîݔÇÅÅMž<ÙÙÙyîܹò籚ÑÓÓó÷ßÿæ›oV®\i2™žW,Ð-[¶|òÉ'7n,Ól–ç±ÿþ}ûö3f̉'äòñ¹Ì{ùé—4;;»È þC!Œgô$›ò+W®LŸ>]§Ó͟?_©T>ÖŠä1·;÷|ü¥ÙfɁäííœwïÞo¿ývÙ²eÏ%¡ èÆ§L™²jÕª:uê”i;ËóÈ0Ì AƒºtéòùçŸÿùçŸÏ1¡Ÿ¢éÊdµŽX,V«UE<…ÜFùÛV9›¿øâ ¥R¹páB…BQ°‰?þ|||ü6U„;;»Æ?ÎÁLBµXL@ %ûì¶Y”Ò‡tÈøðOR©TÏ~®_¿~þüùK–,©_¿>”}7Ñ =|øpAŠM›öùçŸ7lØðÅ $B(¥Ôb5P*•¥pë Q¯_¿ž››Ë󌇇‡œœ=npÆ3z IIIsæÌ±³³›3gNál€1cƜ?>$$€€c†6›íøñã6›í1oš@Î,ùú·ðwƵáÊv^(q ! €Ýž~#)]â8†pJŽÚQ¢`3‰žá•}TÌSOŒT>>>[·níÛ·/!dÜžqMÇҍϟ~úi͚5óæÍkÔš<«[8œo9r$˲óçÏ×h4Õ«WðØËÛí%šh::wî¹7\Ïãé‡&IRRR’Á`P«Õ^^^/J# ŒgT^\œzõСC±±±÷o)DQ\Ÿ|yëÖ­ðu†aΞ=[œzõÇé…9ŸMë[}L³`Ž)Ó !l–Œ¬¬\^ëê ³^8Œ}õ¯XìH֕Ä[ŒK€·NÇe%˜Þžœ {uR™9š|}}·oß®ÑhƍGÉÉÉùñÇm6[áæ•[»iÓŠaaa¥8Ï_|ñŜ9s7nüŒ7ý5ô|ýóÏ?W¯^òûï¿ÇÄÄÜÿyœ^ß»wïrõ¿@EãŸÓŠ,sêR*ñ ,Ër—••¥Õj ˆ’ÛªU«VžBÏšø­ªR©,vSÎ0ŒÁ`xÀwsss†áyþQÊ×”õŽ ìT„P ÷]AóÐDy¬ÃÐyçþYœn¯ë‡Óúè4¡uuw ¢ÇŒÓ•Fõl['Òɘa‹uç™üAÃC€ß7î"Ó,•ܪqqq~~~wîÜ}Ìfó TþòË/&L?~|).Pžçå#ꅧªÈ<œ¿µ ^‘$‰a˜ûßzÀW ÞÕjµiii™™™ŽŽŽãǏç8.((Hþ­QÁªµaƲç{Ö9KZqäk׀©§R–ŽpeéߟÐW¯^ýä“Oä¥Ï²,Ã06›M¥R­_¿^¡Pôïß·Bã=¬Ò,õ#B éÌO?í<}#ÓµC¿> ÃÝ@ (†ã?ÌÜz†8žDŒ÷Ao1¥ßº}žõ«ñïîí'͍ۜӶ~û›Žž¹U¿m—Võ_Ó(ˆÙÿÕOGSL‚OÏQƒ#]y*™/í۞ÒÄ+ù÷o¶^ð ¬Ý­_;/&óØöµ³ìöMg4­jÔkßá­Ð`Õ6pÞiiØŒM“p=\Ú³v«K“ö5| ñŸ_gFt{Ýíßsü«(.ïúéXZH•&ow{ÃMA #f×Ï¿þ~9É¥E÷Mkð„‰õ‚_ŸŠ¥¥Y­V³ÙžjÕª" äààPËÃ,²Ç0sæL9>õzýˆ#äP!„ÄÄÄlذA­V›Íæ–-[Ö­[W~‹a˜ï¿ÿþƍ,ËZ,–O?ý”çyù-›Íöå—_òxèŽÝëu«‘;§£~ؓm02|•®ÃÛVq·j¥`ÍMœxü8­ÔŒš¯ZÌMúû|¬Å±R£Š®rnóÆǯ¥¹¶{ÿœ×«x²÷-ýû÷j×®-/}‹Åb2™äîJÌf3^΍0ž_Z”ÒÇ<ï[”F£)\֔êŽBàö/«Æ­\“íæ«Mü{ìš[sŸ™Ú(Èñî'!yFÿ0&ŸVP¥‹Ç¢Î$™WÎëkM¹žqê»Ûµox*rNDûý—õÁ•ÍcöÍ ;ö]Ö¬YÖªšûÅy‡ì?ä[!Ü|þèÐ+k×LòW.žÀô†¯«š1ÜÙ¿nM\fà’ ®é†T$õõØË7Œ*¬Ÿ:¹’š­f=$Y0â·3•έ eˆéÚÌaÓßû­k”ݳß[.6ö °ÓÞžœoӏ1™“ÿ7ò]Ó¡­“¿^tYïêšuaê„k¶Ù“Z×ðe  ÅæCZZZjjj±b£ÑšP(J·Ù†)v\Ÿ~ú©ü@­V1¢ GãââŠM›&?ÎÎή[·nÁ[_ýõ?ÿü#?îÖ­[Ŋå·xžŸ4i’üº§§g=îÿ/Ã0‹%>>Þd2åææ>ƒÿ­V[쟎ñú‰¥3~o4Òããw*˜ÎùôOç÷kÕ­šðÛ®cçã=ž+Fº Þ¿¹Sá%aJ¿¶åë Y#êVóU‹7®ú6;bT£Š®I;Ö}µ2ÙÅÛ.ù̄17þ·prãŠn%-ý‚uÀf³ÉwîÜ7vìX9ªñ¬3Âx~iñ<={öì‚ÿÿÇݔ߾qÃÇǧl*žµ4êëÓL‹U_Ω§8Z/šãîÓœëÕ"w?aN<{¿ ];ªëŒï·|ùé€õšŽ­“TqÊŒq¯»Šÿ­ùÈöf>·gNÙpvÌÄz^‰ÇV}{2`çž*Ôr)Û`žá]uö'#Z{ÖN±0ê»fíš$oŠÚuÛýëŸ×µs‹n_­Ó®£mêWõu~àEnòå»iii Ðét`2™ ääätüøñe˖¥¥¥”¶F£ñ‰Kj•J•žžþà1DQlݺµ‡‡‡$I,ËÆÇÇŒµuëÖÄÄD9ç”Jå͛7 Þ0`@PP'…÷ç ō7Š=}Î0L^^žÍf³³³›2eJLL ˲`³Ù~úé'¹€ŸvíšdšY–EqÑ¢E˗/ÏÎÎaøðá:+„0žÑKP=ÛÛÛGFFZ,–'‹g†a.\žPVÓgÌLP)nüy\×h2÷Z&±pòH™·/0K‡µXËäeß1ÑT”4î!Ýú +ÐÙ&º9Wo\¹Mï7+»‚±ŸœÛï !+õ‚œœmû—ÝOFqLf0ƒš5}>ªyä%»{ù0ç³,¯Õ:pœ‚+áL¡²rŸ‘F.yøÓ¿:ü4f™O¯MÀ˜B9¥þ­îÃ;Gxˆ5ê4Ôl;póÆ ®˜õ~˥ʌ#1‰o[@ò/Uœ 6”O [­V___«ÕêääæææFQ©T_}õU÷îݝŸì°§N§S(>bµZ###å~38Ž+<"gggooŸV©W×ñª Q•Jå˜1c ¿˜——òÆoŒ²zõê¶mÛº»»?q“ët:«Õzÿë7nŒŽŽ–¯lÓŠMXX˜(Š Ã$''ïÙ³çÖ­[”ÒÐÐÐf͚999I’Äó|‡Ž;f6›EQlÚŽi͚5å|•$©iÓŠçϟgF£Ñää䄇‹§Wwò¯à_¡öš3†Ñs'F(•mÆ|ñÙ͊Âý‚Ã<Ýgm>bŠ‰ÃÂ;=„+W®T®\¹R!‘‘‘_ýõS^ÙWü¿7ÃY ò\ët:­V«Óé ޕèõz­VëààP83(¥*•Jþ–““SÁ‡å[¿×î IDAT¿òëzœÞÞÞŸÈÐ bR>~ÞªU«ðððÂóþÌö`)—6]ës,4jYœ’pM7RÏêÕÈß'0Š^³PØßºÒä[ÀXr%yÒºViRë÷þµ}›ù>7Žj˜gVº@Ý{æ‚1œ²fšæéâ¹xß“Dº8N:%/ýðððÈÈÈJ•*U®\ù‡~OÆ#„Õ3*>•åríþŸŽRJåë˜J¢×ëÔå'PJ‰²Bµ¡‹nzåzZŽšÔšÃÃ8€ŽßE7ÒTàYB÷o×7*¢zlB–•òŽnÎÁv ­ØlÒºƒŒ›(ƒZ/Z܀·sÐÕÞ²o¹œ‡; ¯ÙbúÆ#œâ’r-ŒÖN€†öÛôoÇ@`Žn>_SûC8…žû}«þ×4ž|5w«úº£þ(y{9>Ê+Žôû i~—T¢ŒJÛqÆÂÙµ€ø,‹«o@xHpÞ{ÏZS·ÿÕäLS©*FØsÅÔ¯‡|å^JöìÙS䌲ü±ÀÀÀÒ] ’$ÉWJ?øÎQ…ôqß*éõ· —ç4;;{Á‚ööö÷_Uꗬ?`= ŸÍì8ß\åìç!_6§™ôý©.W’^4¢WßVOWÎ~ÀŠ3ݜü@aïÝkúš×zÄYŽ>ŒU‚…*]€š2pÁOMbãS²E…FX)RûÀ„E1<<|ߟ}ŽŽŽ÷/ýÜ!ŒgTŒˆˆˆ·ß~»}ûöëÖ­³³³+ŒAW*•íÚµsww/)ƒr±œ”hœ_«X8Ÿ«8[„w¯PÓœÂogïdŸ_ƒªìýýó« ©š+ض9xFÔñŒ(þøãY³fõìÙsݺuòJy{±aÆcǎ¥¥¥=àä4ÇqúU+‘{+ŽºwkT4?î{Š{\ì`¡Øš¯Èîێþw5²E1ù‹ïÞìW•P€wöêøÝ7oDêïݐÞ×ÙÖ/ç?ŒtéR‹- ОqcùÊJé.(Ý­sƒ .\د_?–eÛ·oÿlZ…Åb™1cÆÁƒ‡ æíí-ϲ(Š‚ ÏϲÃђKýÿVžû»?+²V>xé? qŠ\að\a<£‰Œmqss?~üŒ3úöí»jÕª‚S‰zœŸE‹ý îCOZߟ¬þî£ö‘>WòðY·×ŽšÊñÜÝt^ãøz¯ŸÀp÷¹Øi.ÈæŠM›:Žaƅ{y6ÉÓРAƒµk×vïޝãžÖ­[—uBdó¬Y³öìÙ3jÔ(___I’Ê÷uO÷ì>xM)ÒtOŒÆ"ô(ðÒ0ô_m ®®®'Ntww8p`VVVA•À0 ÷0r_/ün Ã)f`ooÿ̎i—žã8{{ûçÞþr›<ž÷=„0žÑc'ŽN§Ã-Ëo—ËUÍ$O‹‹ËK?ïr"–·+³°w0„ñŒJ¹äB/Gë=ËéyŸóþ€±Ë)™³®]OÌ3Ù4Î>AŸÎÌ3ÉNüoBÏ!T|:B@Ì;ñëò/þ[)deëë~üو·B]0;QùW3"„^¹t€äÃkg­?U§û˜Q ڟŸ:çÇ“HK®¶éœO¡ä§a<#„Г¥³íÀŸ“ÚáœfÕÜ*Núè»ØǓÌÅælÁšcÆíÛIF«$?ËMKIÉ4B¡Ú*Exp!ôj!`KˆN37ôQ+9ߪ.ë?±iíŽÅÜU…Bjü™Í?n¹˜höoжK뚙gü~ìL†hWóͶÍk„hyBå!#„ñŒBO('%×jtäyVNT…΃áâ’(øç47ñØöõÛ£Iãæø¶UWÎpÓ2Ÿ!ÞI'Ö¯ÚïçæQœ‚f3*]xp!ô nùx ,á ^  _RÄZr22rMµúŒ;qÆÀ±[~Ès¬2èœÞCGuwÉÌÍHËÁEX=#„ÐSsôpãÔw2­¢|skJ’hz-Èó¿ãӔ>ÊMX†X¬†[éZ›Ä«ú„?öí N?q‹“”:%¶(Âê!„ž ¥à÷V-ŸÄßwœ¹‘ Ñ럿jˆ|=đa¬g~]±ø—BKæ±M+Ví‹¥³Od•ˆÜ]Ӈ p4É~èW_ÖwÊùaÖøq þ o\+$o솰zF¡§C€:=µ»:}õÌÑ»¹˜£=ÇM©ê¢"`<³)j••Ô©5g[uÀßœo‹0àª¶ì=Ü="!ƒ ¯V9Ä5+Ô¯úÙ+Þ³ZíÊî®h¹Æ3B=f>Jè+v=¥btl²QhÕ)ŽnœJ*T-Æ- —|9кwº€…ª…έJ£–Uò ppð Ã/Œ §€áŒ0žBèéšœGH#Q¢,CîÆ,ëU¹ŽP œ:àµ:p÷wÏp·¿OJi¡g؉6*+xî!ôJ4Éïí+?› :¹û~ᏒB}eßû ;ÑFÏ!Tê ˜²ã!„BÏ!„Æ3B!„0žB!Œg„Ba<#„BÏ!„ÂxF¡"!ÇA~G™íÉŸõrx•çý¥„z"„Ê¥RY¡BxÒnB!‚ $$$H’ôŠt4"§²»»»œœ=®?Ï!T&¬Vk||üÓ !%%%$$Ä××WÅW¡ÅX–œyóæŽiÓ&NœˆëÆ3B•Uõìâârûömooï'ˆ³³ó7^F›0a‚Õjŕç%ƒçžBåˆZ­öòò:þ<<ÅÉTI’^©F3™L sÏÆÏCc<#„PiÒëõaaa'OžŒKÅ##„Øl60V«oq‰ñŒB¥‰RªP(²²²bcc_Ò*ž©R™A†aRSS¯^œ›˜˜(G5ÂxF¡Òäíí]·nÝ~ø!//Rîú¡q[ä„bH¹~îß³·³¬¥RæBŒFcjjjjjªÕjU(%M(®]/Œ4 !T^Èa¬R©7n|éÒ¥å˗ðÁǕ„ÈMœ‘fÑúz:r,SìD›9-)QÒxz:« éÏ­ó֜hðyÔÀŠÒš†aŽZíŽ;RRRX–-ò{{û±cÇâ:†Õ3B=9ww÷ž={Š¥¥­Y³Æd2ÉÙütÅ-öëþbþ Š« ~Ɣ¶Ÿ·°%nQ…Ž”m£?›w=ÿ©shNÝ:WóRÝÀ£LìÃ[@£ÑDEE]žpA³ÙL±Z­‹E„qãÆáz…Õ3B=UM 0`À† –,YÒŸ}ûÐÐÐÂôã×ӄ0&Ç®]»îè™+@B; |·]ÃP5Kbw®ój\U:9#jŸ 2exM­hËù÷—Ÿ²"[¹Æož¹î\hµGvñUÈœý×ê•?üy!Ñ­z‹þÞ­â¬2ß82wÓæmÚŒq‡VÔ<¹ç!·Om¶l«H}£áS{Dè€vGMَɘæâ×ĻހёövN®ŽvŒ„@҅=KWo»•áýz¶÷æñüæïn„¶­lØ71ê°Ö±Ú°Iƒ#€}\]]¿ÿþûùóç:t())é¿°-N§+©C’ÄËçâo€¹†š³~œúá·ÿ\Ê€«{Ÿúl@§V·•lžqƒßÛel9ÇV|Ðïœ÷†­Žæ¹€œ‹Æ9ë,€ÿ±uRóÑ~Ëò óN<ŽxèÛ³]²±ZYÞUIyÚF!–³¿0hÜüœnûÁà£À±T4ó  T PQ–I‹Þ»|Å7nÚàúº¯GŽüßÉkL@°óÙõc{·_u-Ý@.n™<ªÏÛþ÷hà径 9(úðÖËË˓<øé›«g„zŠ5Ž··w×®]/_Ÿ{æÌ™Ã‡ ooïäädùàíýß5Å֖î¯^£^§ºµýŸúöFßÒ Ò^‚ô3Y•Š~þÑð–‘WbêùñºØ% OŽÜä#¿ž8¶™Kòâ‘ý×ïßgš¶kû÷»Œü”Ù_õšëñ×ò7ÚÍ^·¿Vµ‘­ºVÓßn3b|' €Î»£Ûú3`ڔ:¯ÇªÝ‰ÐŒRý¶ïTYŸÝÌǝŒD†œf1 æ< €‹Ö®ˆj±`Ö ƒÕ7÷L©ÔjÊÖ3 ?jb£é±† ?×»Ž×qç mfÿtÞò}„C*•êðáË/>~üxýúõûõë7xð`\©0žBš4khµZ]­Zµˆˆˆ”””ÌÌLƒÁ V«F£ Å~+==}÷îÝE“™!DEÒçL»qª›îD²è(Qزm•;ü°}m{2\œ²¬6 åßì÷ÁÛU|€,«ƒ“#I5‹`J²(]ê7jRלj6ó ™š›lк3J­J¯Ói XSNŸÙ«kžÅϞ6Ó `¯Óh]‰E¥†g(axB@ÈŸjs©Ö®Q•` øŸÑÑÅmVb¶A*äÒÈ^|Ð4šääâÁ+ŒØ1˜ Çߌyó€êÕ«‡«Æ3B•fBÃÝë¡ …ÏC¿•ššš““sß ,×ç}1þÀçOfÏ ÍÞÐ3ö˜|Q–dg;ØD`YÁfPÊ=3"qÖ«@”Q¢ ˆBºUÌòÏۀØ$ @h.É¿XÚvs{ëw?h>~yÛ ÏŒ?sÍ¡€$‰f‘™ÿ.šÎ?J-XE)Å"Xòû9#VA’/³«š$ 6 öÑÚME~ýúõêÕK­Vãºô"ÂsÏ¡òҏu˜Íf+þó¹‰Ο!í[TÎØþNêMPòrrÓ»x7¯óTÄ»AJ%*ŠàZÃÍç֞#Q’àÊ/³ÏüÁTöwP¹ 1‹ö_˰€áæß箥ÔjÔìZÇfð<#äÜ9u¬pw£TAÜ\§ßŸvÏîËypbÙèë)•ëzq@ î~üQz‘$I¯×ˏ£¢¢0›1žBš|s‰x§iÍø&9*Õk¬Êzy¶¹ÿj†Ùl0˜mr-Ë€!•,[žUŸ²šˆ“k ùðÏþ7Ð>ŽNö¡O7›ŸpÐÛ5@œžSËOõýuÓOÐWêØ¿*ô©íëX‹Òß7m}³ó,>‘õ;w;ýk»:m»Ïµó VA°Ž4êãȋcž¹8ëë̀‰«—·Œp Ö<›Á’ŸPbÍ%Ý^BT*U“&MÜÝÝÝÜÜŒœœÝïÂåÿâí˜b?2/‡C‡íܹsΜ9Ø/‡®]»Î;×ÏÏ›âq%&&FFFfdd~Q>m5fܹ˜kåÝœ=˜ì”Ä,6 ̏5ŠXG;Cˆ—q'<|œ8*äŠ%Yµ.ZŽJB^v–ÁŠtsÓ3@­y™wïdæÚÔö®žÞîzG@²&ÝŒžœaò ­èªa é7oÜÎæõŽîŽ9 ñÙŒGxš›Õqóú-›ÒÞ?È_iÎÉγ(ìœu €š²“o'ŠL’ÎÅÓËÓEÃ34/õvžÊÕM¯€”Ú )9Œ‡·c±ç#nj“””4räH£ÑȲ¬»»»R©,²mgYÖ××Wž{Fœ"…QhœüCœò_r°wö•—FŽpJ9­“¯(ÎÎÍG~‘0œÎÑE—ÿ„(ŽNþ!Nþÿý™R „Qxø‡xøçï è]"\òÇcQE>a®Ô9GÜ»ÚÎI]ðe¢¶÷¶÷€{†IŽ®>Ú»¿ðVè}ôw?]ò‘~I’\]]Ší×o•ñbÁƒÛ¡W!Ÿï휻ž^² E)üœ{RðqRð]Røåü]Zt4%uÌMJf ð°x¥”–t?MÌf¬žBš|FôŸ4ŽîËëû_.üêCŸöo"¬žB!„Õ3B• ù`±Ùl~fV¥RÛC ÂxF¡òŽQ㞬¬,žçå³Í’$œÜ¿O‘çîÃ?ÄEñŒBå7«ÜÜÜ çñµk×RRRæe>‘'ß8Òh4⠀ñŒBå4š ?5›ÍyyyF£ñåŽg„ñŒB/XZsÇóü+ϒ$±,‹×~c<#„PùÞÀqœ§§§££ã«3Ë*•ŠãpÎñŒB奔eY‡WsÞ±†ÆxF¡òštó)?ðS•ËWo§«|*U vTså31›1žBè•(G ! ™cŽÿº`íöÄ%ö5;öÖ©ž³’¡0 Q©Ã«Bèáé ¹ñÿl\·ÅàÛjá7KGŽñ;üˇÎ\Bh±Õv‘çz!Œg„z¢tã¯Ä\ÎriÕŸœŸ³sóíê9Мœ’!Aá[hÈ?Œ,å^»r'Ó,××BnڍëIFîœABÅÀƒÛ!ôÄìÛÉ V'ç _;;o7gÇnŠeæJNöÅÕ9”J†øUKWžŒxKX£y÷w몯,]Ÿ)‡Ñ9úWïòNû {†ìaõŒBÊf2åePŽSæ'ªÂA¡LOÎÌ5ZŠ/žnþ9µ›7QßømöÌ/—¯ÛL+Ô}œŠoڙ#[w\Ìf„Õ3B=uÍF,0w·šT¢Z­‚çJ,r2b\ÚLгrbžgÊà1‡­õæï΀Abö¡‹7°QVÏ!ôt”:'GOšiI1ÈϳÒ,é.^ŽvZåóœg“Ž¢¯Zl†€D‹—víûߟ8züâø`glQ„ñŒBO…RЅ……W0_8žç$ÚuòoˆóÖÀÕßÖÎ\¶ýf¶™œyᮕ‡ ¢oõ«™ümŸþƒŠGqԘŸÍc6̛ðÅÚۊÈ.í#±UуáÁm„z€xTiÔµÛ¥åëŠw?ìbˆ·Tmó~»&‘ ÀÍ{·ôoݶ±¯œêêo›7ß #Þo€#Ä.°éÇó<ãSŒïð?ÖâãÒ8ÕÌ{†Tpæð÷Òã!„ž*Ÿ ¥@}µ6'„6¹ž’£°ó ­àŠ#PsÀÿÖuWøžiàÍOWFZííX€ðî!UÝCò+pP:V¬Y¯âÝzœ†3ÂxF¡§hJ8¥]…È’” ,J)€ÎÃ?änæ:ø;ä§1ÀÝþ>)¥„*–±Gl„ñŒB¥Ð$?XÿËæ{S¶ð3ÿUÇòëÿœ‰ÙŒ^†Bр)‹0žB!Œg„Ba<#„Bã!„ÂxF!„Æ3B!„ñŒ*ŽÈÝBÏ¡çN¥RÉ}_Œâˡӗm0æßÒž튘LŠÌÌ̌Œ ›Íö€lƃÞ«g„P™#„PJýüüÞ~ûíyóæM:588ž”êZJ€€éÖ€Þ}¶ØjŒødp¯†!¬)ùÈO³ŸúnŸ•ymú p€”ŸŠ`F£ÑìÚµkæÌ™,ËIe­V;þ|¥R‰« ÂxF=#-[¶ÌÉÉY°`ÁàÁƒ###ᩏrS @àÌ·ïNÏšùï¶E¯9J1§çjŒêõ˜>ÁøeÔÿ;Õs]m-¹7Ÿ ¿7ñÅb*Ý{?ôÐo)•ÊÝ»w+•ʶmۚÍfµZmµZ%IR«ÕC‡5kÆ3ÂxF=»šÒµkWµZýí·ßÖ­[·sç΅gõQMR÷”³äìì×ÈÙOš„·Úð×NgiFóéÛŠ,_ÿûíÚíœIÑ/Á…MK.x6­MŽ™³9O »hâ’h=³kå'ó71œÞ;žýøYœ+êY×Î?yVxqçwkûŽŸð~c2sêÜßN]ïòÑäþmêk €pdi¯ÙÛÒ>eåWu=YJáÁ³B)íÔ©ÓÀàôéÓU«V•›bÔšQxœz)á¹g„ÊuB@»vízö왘˜8zôè•+WFGG xØ i…BQìŒ×OÑvS‡ù²{ö¯3pH—Ö‘>žG&‚“ŸV]1a÷•b‡–xrõôþo5ül¿wµ×t _ êŒ%€Jy1'ÏWz³}‡–™'§Œy Ì闷ÍéÓvØÔFŠêØe·šRíã˙îáŽÎýhö‘˜tº¿G§^[É띻Ôt»ò^§á±f äá'-‹ü`âĉ·oßþ¯G«g„Ðs©¡kÕªåïïùòåmÛ¶¥¥¥‰¢èææWätl³ÙÜšQ£û_¿õϖ›Ÿs!/盝èäŸ}Ãӟ¡@åŠÓxóÅ÷*J™Ù׿>áý×+%žymØæs¿ªJ}ë§õpuKŒõè̯NɄ†ÄjN”ÃÚZ4îõ?ßtëŸÒ»Y·észdø†Õ]3Ó¹ŒþeGí¹‡†öj$5qÚÒýൡá?:­R©NŸ>=iÒ€={ö4hÐ`àÀSŠLÁÒa<#„žgB»¹¹¹¹¹…‡‡çää˜L&Qyž7Åæ“R©ÜŒys‘>=d‚Èy8j1+!YÕÊ@Ž%§Dóµ«Xsì­iþNÅN†5ËVœ}÷î #íD§·È•wtUç—p ZMž ‰¢‹wpÍ-ýՌY¯TU«Ú°cà G˜P¥Fų1ÅÎ.ar×J3yB·À™Hâ£4…Íf«R¥Ê¢E‹6l8iÒ€–-[bõŒ0žBÏ3¡ ëõzœ^ÿ(ßrr*>h=#ë]ݘÍ)^ Éù`Ö÷™Ž¿õ¿>ŽaÀ¶o[÷g·µû-*‚^ÁQàDÑÀ3©ÿ®i?lÖ'ßhãnûcí„É»€RP0DšÈA~"QB0匆ÁßnïWÅ(p œOÀ#ýšYE…B4pàÀV­Zùùùẁ^bxî¡—SIe¥cÅæ•Ÿi{’xßüK7Sô-ÇwÎÆü3­e׿ÐnæâÎ~÷“PI*«öôªV«ªê¿÷‹–Ü”§ÒqwŸ0ŒJÏç—â*­“—ÆQþ–£·Z‚JÍåï °ŒFÍç‚pZy”RBx•ÎÕSKïŽñ¡¿áV(zœŸ€ÛW—«®ÂÂxF= J)aŽþÕßYýÞ.6ãîy±ÐRä•"_.üŽøAÖӅ+f3ÂxFœ%4FBå^¹Ð+Ã!¬žBϑÑh4’$ɗSœX'hyž7™LžÆ3Bè¥âêêú믿ʇååå †îg¢(ã¢DÏ¡—„|§‚§iiiqqqÒ=ýŠŒ$I²Z­ž@Æ3BèePä ¶Ùl–oüâîm` ã!ô²aYV©TŸÐñ\Òý1ÂxFœšxž¡ Pžç .J„ñŒzIPJÕjµZ­~9ækhôŠÀß=#ô’{™ò ³a<#„Bã!„BÏ!„Æ3B!„0žB!Œgô2ÁšÊmƒ<û)yŽóŽëaY{q{ªyàïžQ1ÛDùç+QQQóçÏç8îUþ5‹··÷ž={!åá·ÓסCBHM¥Ôf³Íš5«cǎÏqÞ !Û¶m›0aBÙÍ髬Aƒ˖-ÃvÀxF/R6 ‚0{öì¿ÿþ{îܹ®®®¢(Ÿ²µÅÑ£G5jŽyóf77·ç›Ðc?vìØÈ‘#ǍW±bEAÊb\,Ë&&&~óÍ7©©©ýû÷gæyÍûå˗}}}gϞm0ðß³Ž0 ;yòdl Œgôâeó‘#GfϞ]¥J•WŒMªT©Â0L›6mvíÚåêêúZïñãÇûôé3oÞŒöíۗõ===?þøc†aúöíûŒšR€ëa©³··ÇFÀxF/X6õÕW¿ýöÛ… ###áîFQžq;;»¡C‡BZ·nýZé©S§ºwïŸtéÒÖ­[—频‡\·nÝ  2„ãžÞœ{?¯„Æó£eA„"‹;LÅxFå7Šl6ے%K¶mÛ¶bŊJ•*Ác^›ó˜ÿÞ÷|Œn ιÚÙÙ 2D’€6mÚìØ±ãÙå–G÷×_uìØqÕªUoœõVY·XÁŒ×ªUkŊœ{÷æyŸ{÷îÏñ(7*õElµZ Cff&Ïó*• ›¥\Á+·QþÿªÅbYŸ|ùºuëV®\YÍò%9ýû÷'„pǗ€ãž   y›þXp3öߋ×2€'Þâ?ä.ÀO{“à‚9²³³6lX‡Ú·oŸœœüŒó‰rúôéÖ­[¯]»öds‘y¯^œú† &NœøóÏ?ß_r¡—Åb‰‹‹»víÚ͛7M&6VÏšœŠŽŽ^Ÿ|ù±cÇt:]‘žuëÖºuëzöìi±XŠÝŽçææº»»Ÿ?^>þèpšþ›ïûÉ8©™Š{¢>!RWŽžqÌ`Q²„VGšA¢T¢‚AÛsÞÜ&î¥YC7ÎÉÉiàÀÛ¶m{h@–n‚6mÚôßÿ |–G æœjÕªÿýwdddƒ Œœœ<X^¿@$I’Ïp‡ «gTN ‚ I’œÍpß­xžeq …|#Þ'(U™ú¶†jžyªÿ}ÆÑßÝËÛÓËÛb—ÎYrÑÑËÓÓÓÓÓÇ]¯(_Í4ÇqžžžIIIrùÅ_ܹs§t·h999*T‡ù,·•ãrpp°Ùlñññ’$Bxž/vƛ7oŽ›ò!D­VïØ±ÃÎήØú×_áÅ꜌òw¿©$I¢ J”0<Ï3÷ìRIm‚„°Ï2„PJ©$ ‚H–åXŽ TQ’$ Àr<Ë8¿=òÓ· ¡Âé¥)ͧ>X°$Ø‘åX(•$Q†e@’$ „H’(IÀ²ËÊ¿©¥¢`%J)áxže Øš’——œ““óÙgŸÍ˜1£Èg\\\žÍOÑ$I²ÙlrË²,Çq…ÎÿÙ;ëÀ(Ž/Ž¿Ù=»B,ÜŠ—¢E‹;RÜŠkq—âÖâ?Bq„!.—Ü]Nww~„\€R‚ŸÏ?Ù¬ÌΟ™›ïŒ·3³&“ɬ£”R‰D’}î²ÑhÌJA"‘díϞšH$bY6‡ÛÄ0̋/"""8ŽËÝ»|ùò Aƒ>Q•B(åys‘1"³ Hž£„%”ãF, ð<Ç ”†‰†ç ,ÃBšÀsˆX†8N ,¡<Ç æóYÆÒŽï—÷ÏQB(åy“¹ÎŠÄ"–!æ—,€ ¿8uH—iûÃã/m™ðëÀ¿kTÞC&³o5bM€Ò±€¯“L&+2çàCNB,›”aFž––öyƒW®\‘ÉdR©T&“ 0 {!¶nÝ:ëPXXXöCYaww÷ìû÷íۗuÉÔ©S-V †abbbž?žWæ£?žÅ)%€Š=^ÐÅÍÎF&“µ˜>kx£žòÀëã7 šÙkáú íŠ.ß# êÜÆÖd2™Cñêw]Sqח6cӓ€žšT®ÇÊhµÀž·OÍî‹vü1²¶L&³sšŸêBŽå<—«QÆY&“Édv^Ҙ«bʃéíí¬­å2Y©g¢Sò­Ý*Éd2÷  n#Fþ:pôN@ä_+LJŒ?ñDÚk[ôŸuòQ2@ú³EœŒìd2YÑy‡s(Ÿ¶µG!Z;®™L&ó hqàž €S?<¶ºI…@™L&“•ŸŽ*ÔÚøÍ£ÊûžÈd²£×_É4Q€<+sö®žyc÷îÝçϟϱAïùO­˜Ñh4™LjµúCêH€R©X–Í—ŒöüÒ£ÿöKmæn8Ý£FFT”]€í›§8Q‘3OËÚ%¬Pjx‹£ÝzF^9žlɅN§žM*%zžÂ;³ Û3jÂ)yµ?#N–2&+­|€–倈%>%ƒŠMšsoÀŸ’ŒêÆéCûO'/žHþÙ{óÏÕÇ}ÚNÿýÔôž?»öí7ÓÏy鰆˂ʏþíFì É¥ÙA-¿ˆhꕧ5†Q©TJ¥ÒÓӓRš`nÁ)¥„F“žžžÕº1 ó_Z:©TÊ0ŒÅldmGEEÝ¿ßÝݝçy‡ì·;v옵µµùõDöK(¥gϞ æ8N&“e¯9QQQiiiŽŽŽ¹oʲlLLŒy;!áuK.—3 c^&%«ã’e–{p+++­V›ûÙ €ôYÁU&ŵ<ø`v%Ù£áe‡ªêgò@šöðꊭQ%'¯ŸŽ¬tÊß«7 ·$†6xŽ)€k§nO7,›XŘüðºÒ+ƒ£`Ò<}rS$p€Õ§‡nûíÖ±5î/:1«ÇÈ&e|Ÿ*›zRžÞž?Ã0D÷çÈqgìêì‹<€OJ·ñ•HëYrvÛ?"Ò;&œP±~ƒàô'57†•ë|¥Ó–žs¢ö,ëÓsŽmK€Ëˆyð"ÜßH€Ó?Œ§Ôª@=«hÙñåÇߊëÏ\˜U²e£àžÈ]hF|èÊÝ õœsãzߍºŒé~žõÍÎw6-éÒk‚C—Y÷ŽõR(c9[)Ö×o0ÐTgïÝóÅ£ÖÕîX¢ü͟K¹ˆÞ¯ÛÄqÜîÝ» .\¥JsЛV”gä¿"‘H®^œÚºuëk !… ʯüeÜÛVtجñƒÛx˜]sžCÖ ûõ‹‹y¡f ÒÛ1 ¹5#ãO?Ñ¡@3ÿ‚ž¶R'O÷Ø»Ož¹îךJ!7)kŸå&œVÉ€"&+óʛ›ÌÛÿw mä€?4àÇ®‡Mx&šÝš³FŸÞ§éü¥‹ë×YÚÈW˹ö\œ»çê”Ù¥JYº§]õ"e<¬r™ƒ‰•[^!º}£»*¥šÞªsI)0,Ñ«T©É*9@Z¢ÚèêšK$6éií'œ]9¬ª$—cšæ!TË"û,Ò|&F)-SŠLRRÒ£GÌš*—ËýýýÍGׯ_Ÿ””€T*Y–MOO/\žpVˆ8,,,,,Ìo7™LYsáüýý»ví&‹5ÍT'©TšãaM&Sö‘hÖïŽØ±Âƒ<:wâF?…43òÈŠƒ¶f} œÎ< ‰‘€ZŸr÷F$øù€†§%$Éü쀂‘×MF  M<{ù°ÞАY¡ i1ñZ®€BD3T óqޱ+Õæ`f›\`ÊäÜz¯ÛÛ{]òŒ%Ç/ÝסV‰ŒÈQ£mŸìÎÂÎæ³Þ.€öÖÙ'Æ ’¢Ž˜§wDUxAkäô@P‡†þ•$2R€µÍP֞ziåàJæº%P*p: Ԕ©-ê”R 6"†ŸHŒxš^±Œœ`2˜©XEFZÓþË×ÌîäÌXˆ²Œ%PaÞèСCÖzŸ–- <#Ÿ‹>²‰R ²âý¶¹=býd[èØ48õijÕ®+û:Fƒ‘(ˆîr8ŸysªèéÞMw€böÜÅšš®QÛ×^)P'(%F[Ø' ÀÅ@ue÷ŸRš°CŠÁ.   µôuŠŒ”{©Ï#-X²~›ÑóS4¿Ìímvf%6Ò€.nžú»kFÍŽ«ü­²ÞŽªgÁ¢3›6íþë ß4ýj9*_Dø5PÏ×:·Y²[†rÿþý‹/fw"mll”Jå'(š¬ÁØæ5drœ@)uuuuuuµxm‘"E,^Â0L^©å®'NœÈÞî³,{ýúõOUE8U™Þ€É é“ŠŠÖg£·žŸ)”(¥œÉh(€ÈŸl…–u˜ÐéS&“v¥#άœîÒœksW€8ß°ã·mq=™rhãŸ:êùòédvÌõY3º&”ôN¬ž ¯ÛœwMg‹oO€š/ïÚóHÉ”ŽO5Øú*Dœ,l\§W—Ÿå)*P€Æ?/Òj`…¢µ{­2RÞ6øÎ™¿–îŒS¯Õ °qMŠ<¹kój•ÃÝm[€Ò`°­5§Y“îCú‡šûW/æ |QšÅÀÚÀéˇxAoàM šW£míyCg”:€)› ô©\»Qµrc›µé1kf—ðc‚êOœôü!ÐéË DDD\¹rE¥RI$’ôôôððp;;»žž8lQž‘/B•ÍSŸo¹V.—¿¥‡N€R %‡O[ÀÎ\qdñï'xSÙÒ?uŸª-jqa€:—éŒà×c‹·/œíà4ðà:¯‰Ë¬=Wy¬oì‰?·&ŒS±Ÿ&þÖ¯œ€AšsaÛ¡T`Jµ\Òº£4ëFÖŸ?4i^ˆÍàV8xVêì²?pdc¯—M›Q°/ãk$Ï7Ϙm„>³æÿ\¯(Ôݰ{{Í.S7®¹tX;¶ñ@‹ºÈóŒ9êËq\©R¥:’ÃVÕ«WW(ù#É¡ÐyÅÀßrèß^’ýÙ_ÚPêÕ«—#€o>­Y³fŸ"V”RqÓ­‡ tÙŒçÀ%»^g*§–îcˆ€€ŒHÍÄGˆ{¥Šó÷˜fŸ2uô~Æ­B÷%£6€R=Cz>ŸujËRáÇ዗U]sµˆBÄo¢.­JFìY¹WÏ9{WÝŒcž×ËYT¹s¡&=?·óèFJÙr?ý1¢¥¯œ˜4?ô÷–%?ÍØ¹ì„‘È­­'¶úUæUmÁ®ß“Í^±òIÙ²mÏ ÜvFÅøüПûãØÕÛVo¬ÒyðŽÙeØžÈDðÃæœÛkuž¶iõÅ} ‹Æ5DI`­ŠZ_k`Ä ¿r ~‘ØÕùé÷Ëüìés×ÌÈs…ùVâ*Ì\±µü°©«¶Ï9O(åFTïb¡o‘ žç *tá…áÇg¯‚ ž¹¹aÛøÙb¢øÁóoƒsçÎ=ztÞŒyœBXXذaÃúõë׬Y³K+7hÐÀÇǧN:YÈr ×ë p÷îݒ%KŸ¿Kž}}{òê A ¹âm”Ò7u+ÛVRØñŸ?51V»ztUó=þ1fäÞ°ŸÖìûÅ7Wyd/ûW–-Z”‘‘1xð`FãææôNO—çù œ>}ú¿”o£F7nܳgO++«O¹ŠSևRöîÝ»hѢѣGÛÛÛ ‚Pºti‹—‚]Žh‘““S—.]>8sæÌyöìÙêÕ«s ߟ÷Š›O™Â^ŠÈ««&üôw=÷·Ž‘›] –²XÚfL+$‹C?î[äÁ$ËiPJ-ÜñͺŸcæš™ÇmΟÿÝ1ƒ¿eŽã›ëÔ  µ6ŒåØ{ÿþý:uêœ8q"==ÝÞÞŸL™2Ÿ,œ† ÷Œü;GŒ1sæÌ””ó"ÛY?ˎ;nÜžñÞœ{oñÀZ·ný¶ Ì ŒùŒì. y݈œ>ð†~SJa ;ÍÿœN9kK0(bã=ž9­P@nèåNXƒÀ:{¹ÚŸœÚüèÑ£‰'Æ!C†èõzóèh•Jekkûv¯ô£°qãÆ.]ºÄÄÄL™2E¡P|šÓ|A–/_ŸiÓŠŸ}ûšßJBÒÓÓó’çOöÂ2æèæÙ銊E}47F):.ÐPšM ‰…JôºÂä®Eæ‹\|k{Xqo€ŒO}Î^sö³Ÿgä< Vª`ÃŒ)ÜY§ä®ŠÙÕýÌ†äñaKÏü6KšLŠŒæÑÁ§]¥AyF,4Ä ÃüðÃ<Ï/X°@„Þœ{›Ji=Ú·o¯R©ÞÒò ‚}2Ï»ç9ôٚ K§XŒÁŸcÕkû5عª™Ëk¹uoÚrrMœ£Y}y…Bñ>ïS¿œ8¥”0¬ÂÙ§ s–GN)¹£—Í{e5넧OŸ†„„H¥Ò~ýú™µÙìSB>§h.OOϕ+W:tĈóçÏÏW…ÎÒæùóçkü¶ƒƒC`` Í'‹”ŽnÝÚÑÑÑ<6B­V'$$üÇuN3 6ÌÌÌDS <#_ŸB'%%EGG›LŠïs !J©ÑhÌÃü¹Ž9GÑØÙÙõïß_«Õ†‡‡«Õê|zÌq\vmvtt 0kó':ðr.N÷äÉ­V‹>ßGAìë <#_ŸBg5ÁÎÎ΃!**J§Ó}çÍ¢Y›}||rÌ ÿ\E£P(|||ÂÃÃÍ_žÈ×vÜÉÉéksn]û ”çÛÂG¢<#_¥Í0Œù%«J¥úžÇ’Blll<<<>£6çv£Ío‚yžÏ¿QÜ"‘ÈÓÓÓÚÚ>ëà|©Têêêj0Pž?nùš¿ÿŠ@yFŸJ…vwwwqqùέÁ0̗ Í9ÚÎÎÎü9Ë|œ—9~þyŸ]¡Pøúúâxãü(_üúÊ3ò+4þ€á [à0K¡Åbñ7ÿì_R%|¿%h?þµßQÝFç=#ï)h„/ÓŸ2?Ÿ=žÿ…h1&<˜?®_Úµ~±ô^ŒÚ|À²xmÄís›Wü>vôÚx X·”gA¬Î„Hy°fɬó*¯‰£\U—ÎÝ–šB,4 BFü¥Ž}G¯Ù~ìEj ZAyFùøê C/ÿ/ÜŸMۍë6ž>¬Màóÿ„G±ä@ÆÖ£òÞœišÖŠ£ ”gAüPg͓ØDÁË»Hw°ò/eãÀߏJÍ4€…—Ê€emœÝ­% Á!mÊ3‚ ÈLJ€6)1%Zbmã€È\ýÖ1щœ) ð….‚òŒ ò Dš^àù—+yp„P•Z›õ?‚ <#‚|rDR±Hΰ„Œ\GU0™ø‚ŸÎrÙë¹m¯ÇˆÑ<&iE­‘° IDATãÜmåAäcA@âàígŒŽ÷I†ÚÇËÅJÆ5Êd¥†(!T—‘šœ®¥„˜tSA ‚d}L͉ <#‚| ¥¢²•Ë••=9·oÏœˆ[ïLÑT®hÃÀå%C~²>>Ó`ü{j×6£öé€3€\»x-ôa”>3ýÚÅ÷EXF† 9ÀUÃAÞSŸ ¥ ÷«Ùy zÝê­F&lɁÓz—+dr{"Ύ†k¯¢R;(Õ§=]·|•ÎÖ¶€ ýsé€ru‡÷—¡1”gA)Дx7¿¬‰^g”É%/ß%W0·2˜ÿƒãW70ï'ŒG•Õûv¿‘ ¥éBÞ·Aþ@“—C»^k3!ÙÅöõf^LP›”gAühx—#Ê3‚ ‚ <#‚ ‚òŒ ‚ (Ï‚ ‚ <#‚ ‚òŒ ‚ (Ï‚ ‚ <#òE ‚ à—äCÀE=É/<<<ìííáÕÊZÿöò»êëå{{^åAÏƒJ¥2¯ùaªCÙµk×àÁƒY–ý†u‹RÊóüž={jÖ¬‰uAyF$ߑËå:Îd2‰ÅâK!::ºf͚+V¬P©Tߪ•ìíí›4i’˜˜ˆAyFäSàáá–’’âááñÁž¥£££«««««ë7l(;;;¬-Hph‚ ùE```ffæ‹/àåG‘<{!9¢÷h.åAü¢`Á‚"‘èñãǂ à §·À²lRRRBBBTTTjj*š AyF$©[·nxxøƒŸEf¢ÿòt Ã$&&FDDDDD€€€àl4åAü¥L™2žžž{÷‹3{„_¶HS*‚ðž9$„Vµä@Lº1/—ŸL’ŸgŠǙL&“Éd|“É„Õ åAäãx—зo_F³mÛ6¥R ¯&YýW‘¶pœ¥)ÍëF–áÖΕë/ÆŒF2o]ºò8VeÊ3ÍÔW¶¯þózÒû8ÙvvvõêÕS(r¹\‘ ¹\îììŒ5 åAä#@1«Ñï¿ÿ®V«×®]oŽÜfùš¢Ó”R šQ§IINNJJJJRsÔ,ûŒV­LLLJNIQéL”Bo2è23õƒ:#511E•©(%„PÁ€IKMNJJLLÔyJ@àÔ'~ÔûjŒ^™šià)åõUŠÞ™‘š–®á^£R&&&&&Šfhô<¥Psù™sËúw€1S•i0™ôêää€äd¥žš.áùŸ]œ›š éÝ/•µZmBB÷&fkÊ3‚ ÈGVè©S§²,;{öì‹/Š€€hµZŽãà]+–d]þŠ—KӋ[«C:ðóóóóñôöÈ@MÉ7ÿÞ²¶»··± v7†%Qˆ»ºwÖàî3–/éѺª»»kË>Ë'àÅÕ=¿”)UØ××ÝÝýÿÅOþœ0@2~píB Ï& ªð?ýÐ{ÖÂ!mÊ7é<5"ñلîÝ=<ÜÝ 7íŸø^¬þ7«k×i›ž)981ªYÿ¹›¶Ìïï[°€«kðœ}á ¯ïŸŸ„Ì>ꔫ¹õŠú}ŒŠÕjÍ4oh4,öœóžù M>|ø?ÿü³qãF‰Dìïïïêêjgg§×ë-^šP(”J¥D"ɕ $M)Sûweáe'ÿiWÁåù“h73n+ßülɅ‘ýÄO mÑçÇã†ûw‰õýS{öŸL3ã՞tî¶ûPýŠÅ»XÛmăº#¯,ì圧rô ~ û/»8zê®î%Y;'£15éî?;Žé›Lßxžu MJlã®ãGìlbº4 u›­{÷4.=¬€!9,L(¯ãSضI}µ˜qþîØ{Ó+öl¿Ÿ\¿gOùÁø¹+Ö¶ $Öò÷ŽXZZšR©\±bEÿþýÝÜÜ€R)V$”gAüò¡+TšP¡B…'Ožüïÿ;vìX||ŒŸŸßÇ-º† ą…5kÖÌBŠ1—Vqº^;·üR§P¢¬3Pšüàâv±Ó‘óà *J59÷zƒ1+BÓ œÑ¿Ìðáf6óæÇ |€4$*T6èù­³»÷lX³Ji; ¡ u*V¢:Üq+â[À4ñ‚IfSiê®#œŠ€³ƒ­•µuäÛÉa*"ŽÍ’y`EŽ”1/Šf4˜äíÿˆÙÑÛÀŸîO°ùz"Å  ªÂê݊{xžÀû-¬-‹>W-ZŽèÞœ{–ÌJD™Xà˜ßÑ`eR/G³TRÊ1 "†A/x::ø8€N¯âL"1@ÒmËêÃ7Íè;ibðÔõ+G׳z­8úrŒ4¥`%—ò6/Xf »ºw̄¹Ã­Ëøâ97CÌwÎ Ÿó|¥š…Å&ČN“ÄAB@àõ™&ʁñÕ¹ïŽQ †nݺuëÖÍÇÇ'22222° }oà»gA>µH¿?ƒeY ä Ažwòv\ºtêtD$u2Ý=x- À}÷ K 8X pgȚ˜D)š®uŽíÀ?‘·Fdž™žæŒŽãF Ñ·â³îCÊé ™/öm]v ‹ºxbî  ™ÜÔÜãÈÖ .SÿrZ!T „‚>æ^òËNŒ{(œ\þ2Ÿf͚¬=žŽzÏ‚ _4”±«1·k§K Ç5ìbž =fÿV¬ÈëTž:®ŸC׺LÂíƒûž·o¿Š ‘F£A¯7 Pƒž7ðŒÒ÷.X.²ñ*ÀDOù2"†øW Ž˜2izùç­Ûv/H£^kà)+õvsœ>oÎï²[§ã⣌Ç.ÜíR“Œz£9mà Zœ‰™KA^àIlŒ‹ù]™6zY©þM¶(hýŽ¡p‚ lÚŽÉÝÝ]…B±aÃÐjµ8ïåAäËvÁRJª-Y·¡ìˆe‡n"iu Dæ5äð6ń_÷8È(\ª Û4¹W%°ö-U¯)ïã&‰KÉÖ];ù—ôPžÃß¡×ÿw™—õ¿µo ¹ˆ€jœ×v Ÿ}ãï¿*6îVÄÆ¹Rë>…ý­džÚ ŽK^rêäéÚ­OªYëàž„çá ~5;Ž2”v3ØžOëD €K©={±Î 02§†CWŽIYxíøé uZ|WŽ sçÎW¯^Íf2dý÷UÏ1`òmpîܹ£GÎ›7Mñ¥Áó|ƒ NŸ>ŠøæÌ™óìÙ³Õ«Wçö s°2O†Î}Þs¬_o @˜·œóÀ»óo$žµ+Ÿ‡†5nÜžB… 6ÔétE‹õòò²x AßH~/`I#ò5z„Œ¹€‰y¡’ìîÆ+M%o^ôj›\+fBˆÅEŽ É1ÛÂY–o”ó:K]ˆ7K­V›g„[h¯Q›QžAŸ~µsÇ»‡¡YT’çõ¹îö~wŒ:‚òŒ ‚ (Ï‚ J©L&ûæS"‘à0 $8rA/–e—.]z÷î]Žã!–ç@ýÚ|òäÉ2eÊ`äAyFäë S§NAAA”R†aT*Ull¬^¯ÿÆdŒRZ¯^œbŊáÌfåA¯C·ŒŒŒ²fi4š'OžhµÚoÏË$„pgþÔ&‚ <#ò¥‹Vö ƒÑh4 ßpX|  <#ò5!“ÉÜÜ܌Fã·-ÏöööøAyFä«A¡P(Pà{ˆ <#(Ï‚|˜×Âü8#·ßµtחóŒXîß38ïA¯Ã§üX²„šÂÎ ý¥]õjU:†¬ÈпÔìoñy”gA¯À '„ðQçŠÎ^T°ñ’E“%Ñû{Ì>”¢1!8$ AyFùâ Bÿ>ñ˜«<°c«²®ÛÊáúÎk *òøÜ•ù¥¯ÇT›ÿšù_h <#‚ü'@ê­J·~n6 ¬ ·ÒÜz–nñQæ35eFß>µmó¶‹÷c8£*þƙ¿»ò<%Ó|ê3’àÐ0AŸ'2ž'š’ìŒm­Ä €•{€Dú$"ž«í"KãÎ8ÍœÓkûNØcç(չ؞C+ÇØ3G¯ÇÈxõ–Ó?ŽÖ³¬ß#è=#‚üGš!„áx^xéóš@£Ñå£6©Óž^-Ùcɱã;úó»&Žž©*°jËΝŒ Tf<œ‹EPžAþ3Rk)+¥$«ñ3éy®p€›å:çÒi‘µµÜ͈kùjMJ+XmºòyŒŽWé9 ÃJÐsFò n#òœ@ˆÔ·Œ×úûáQ ςÖú‡—g²m}]Ä,š£S8[_/†réñ/2ǂTf+U(ì8ã|ïìŠÌâg—–MOrôQ’¢­\ЪzÏ‚ ÿ B)€šv“šE5ÿ;²è3‹fìµöj[7ÐYLøÓsúv»_ pû&öè5ë`®•Ú÷¯W(ì%ûLŸM׬Y8ö·>8e,õíÞµ]傶_܌iœgA¯MŸ ¥ (Ò€ï 톝'—/1ˆ¬ë›ÞÑÛFÀ»*SÃÉS@ˆÄ«p¹ª2WNE»M]Ûí•î[õ§éUzåS €+ˆ (Ï‚ ÿY )ñ©Ôvb¥¶#/•°¯T–­>hVu D6~ûœÑ«%ÆàÕúš”Òlÿá›Ê3‚ ÈGhòRX_ksv•}c“dßcþ÷õqÔf$?ÁwÏ‚|— š²Ê3‚ ‚ (Ï‚ ‚òŒ ‚ Ê3‚ ‚ <#‚ ‚òŒ ‚ (Ï‚ ‚ <#ÈwÇqhAPžäË"88^.Ïü!PüæÂ·%òþ࢞’ïDGGÃXœŠ²`Áœ^–üª…¹`Á‚?ÿü3šAyF/‡øøxNA¥R3F4æ×Ã0‰‰‰@S (Ïò¥@ žÿþ‘gBˆT*Ec~œ`ñ!ÿºW‡&@ü–çJ•*]žpðÕ#’ ¬ Ê3‚|fªT©òèÑ£””BÈÇm”éËä(¥ÏóÇñuÒьý·olî×ÐÓѹb›©ÿ;»%rÃþí‡n€\÷`2ïßxš y%ýN—ó-ž^®]ïãŸÝq€ÿ&K`Ò€]¿|睎·0úø®?\MњÃ3†G7€™še›Ð“1úöb•ÉdGŽ)\ž°¿¿¿¿¿@@@@@€¿¿`` ««ë7ð'ƒŒìÖ£ $¿&³,Xpɒ%“&MR«ÕuëÖU(Ùý€,Í~ÿd &ôøÎóW[®¹ÐÌ=åÊ_ç>®ü[u쌪ϟ3ï_}šZ*ÈI”3QbÕõؓÎ"9ËLŠJш­¬lmlÄ@€NŽÖ&µRc"R €&'«µÄÕÛÓÉVΠšÔžI*‚ÂÙ«€«-CšÀsêŽd“Ô–šÒMV z€^›®;žž¹¹Ú‹¡r=!tÉQq)”+²óòs³³‚É V*©•­ NŠKÑÛ:ºž»;IbP¥ixV.’“’5:ÖÍÇÓÑFÆÔ)q±Éj  pööq±a@Hrw}ÿQ—–VnእÎÞ¶"SRbBJº@jïâêæj+³†žµöôŽ­Q¬“ƒU³?ïýÈJY€S&ÆÆ§fVdëêíå  8}ŠZ£eår}zR’’spuss¶1„ò†ä˜Ø4­ž§‚»o ƒ•”yW1 †®]»nÚŽ)Çþ2eÊð<?$[Oùú9{öìȑ#Ñ_,‚ ˜7"""† 2oÞŒ;wî$%%efffz “'O¶°×”Žwåìjm·SšŒaxËú ºoÜú[YŸvsVFÐÌCÅ;-ýëv²…œðÊ5­‹tØú˜RÊëÓ¯o˜X×döÅ*•nß¶YÛŸ£wé(}ŽmòÀ]ÆLYµŒ?Û€ÿ†çiJ©úö‰QÍë8ºzž¹Øm>èàÕ4Rò颎Śü:¡K£"U~oМ\Ô·Rq‘\ê^­éÈsSó~,þԂVŽ.î®vò²“·?Š”ŠGÿ3§u™.æõëP@T¬\×£·3(¥·×êÛ³çøI¿V(í j9t{\†‘Ršq㯍kØ»ž»»ÚµvôŸt΀þ{ÎOŒƒ<žqåº;ïétÑ×·®&³³·9Wn2ùz ¯œ·£N1`Š•”Úô™,“r{»–jŸô’‰(5ƝÙÞœz+Gw/÷ê=g\~¬£”Æ]Û7Ÿ]~“еk\€­ØhôÕg™”Òg§7µ/èíìb%aç€ç,?j\\\HHÈå˗ÿ÷¿ÿýúë¯:t0ï_·nÝɓ'ÍÛ%J”ž|ù2þX3ÜFOçC€ŸŸßìÙ³]]]W­Zµnݺ#GŽœ?þÞœ{÷ïß¿qãÆMKÜŸ}[§ÓYè[kÒA’Q®sÀ›ïЇîØÐíçÎłÊàAáít'SZº ˆ:!,"hÂÃcƒ{L5V;¯Œ¹ztوÃç#â”À…Ú2ûïô~ËþºŒ¢î¹•;CŸ(bÇWl°æŸJ'n<íAw·š<"Œ† ʧŽþù·¡óŠc»~{²eî ßNW\ô\›tÄ/ýô¢e[šÀMYŒ&žR0ÊÜ«þ/,:îÅœnNíz@À‚)>ü֖U{Lug>ŸŒ õâºå—@Ä€\Ù·nöIÃȵ'.,ªò×âm7£ÕÑ£Ë5Þp¿Îù{‘a—:j·5©ð[$k]î‡=l~XºfóÑ?²NѮߌØtåãÓíõ—vîÛû@^¢UOoŠmÛ.ºvkb `3“>Ss€SßR·ÓC¯G±q.l.~cA³úsSĬ.üúÙU›/鹿îáaÆËï;ø@¿søäëÁ? ‹LˆŒhWÁOô~m*Ã0ðøñã͛7ïØ±#,, þúr·ù -—Ë»víÚ¡C‡ÐÐÐ{÷îÝžqC¡PèõúÔÔTs«‹ë…™tё·žÛªc’•)‘v>ŽªƒH#²P‡`¹Ì–µ¬ ,8`Œ‹ž}ͳô•ÍììÛÿÒïiÜö;,€Io€ò?m˜;¿K°­žüèæ°]i2B̍UŒí‚c!匭Šþ¶tñšÃ·­ ôN"/?qË®Ÿ‹Ÿ‘ô$ÂEdÿÄÎ8UŠ^oÌÌÈ4oÛñ~€^Ä ”ÓºVíбZ€T$«Ð€Î™ Çj„šTÛ>Jp§<ïèÔ°ÿƵœ‹B‚¢p ¯GBŽ€Óë™Ê]v,œûS+­¡‰‹õ^¥Ñ$D^[%¶Ys"$ØMPbԒã‹v¹Ÿ¢kB娗'GG€‚^Fý…ƒÇ2ÆqlRАÌCI¿2rGÞœ@B^ö+rb¢ ÝCà#(TgèÌ¡›~YóOÊÄJ/øë?xõÔV>³x¿ÀK.A€2%jW֜8·f™Sƒúõ땱(À;„–eÙÄÄÄùóç_¿~ýÁƒööö3fÌÈ«ô”gAò]¡áÕx"‰DR£F5jŒÏ…ÓŠM³ðë•Ú8yً€ÖÖâ SòÍ{ É¡û.? /-mõ|÷~µ—¯­‹]žoµÌù¡2 8ÈÍ¢Àé3RÒSxPÈËÅÕZZmºÀ+$„1';†˜Å‡'` @åbQIwG^‰ÄŠ”žÓÇþŒ*èûÒM~šç.æŸÜŒ~áÌ?J‰˜à º2¶§ Í ›>lÀÖ;FÇbîV~,°Rʃ ++àƒÖhàEŒBÀkÿÎr1h3•Œ –‘18ÙŸzÙkb$@–P×kM`ó‡Ât·Ïn?ceDŠ_Yo•ŠõÂ荂xžÏjÍ6a%,€Ó«ŽÀ1RBD ‚Qp±¶-èåzœÚddÄDlÒ|áíèi[,mµlëÀÅËçþTF!~·ÊF77·5kÖxzzµk×ðÅ3‚òŒ Ÿ_€ÿœgÆÎÙÎÖ9æø_Þ㚖»xgßÚEÞÄXÊÓ!õŸƒ¿ß{Ôw`ÓÞVouåXk[[‡žËV_ÚÄúÞ±5ºåR£Þhâ9@b@ÆS §"ÆÈ§4 ªnKLÎïôrS ”R“Þhî2Øi€MÑþÓu®h–8jâI£IóMÊyûŒ[{§m8s0Ž6÷0înWùOàó́Ӳ:Pó$nÞ`ä9þ•©@)ȝŠ˜¢¶|Ô$°ŒôÎퟚ—ƒˆr„3š£Bc¡¹+dÆÙœ6Œ)öOèVùùÕ?œ]jb +øØKÑJNo–ŽÜޛ>Ýt*Šf0$=ºôC‹žÙ@AàyÎ`ʖ1@SRåæ,ïÊi·^߬€B,ygJ$/Ïùå—_¬­­³\jüu (ÏòuCëTº`ÁB«®ž±sä¬eׯ>ñ®T«­úʑ“ª¶Ýë”÷•KÂ)5fBЉù–m:¡éñ F%_s5*Ÿ$éW0ð‚Q¯ÕSN0{؂FÃ9#ØV™3ŽGϵ£‡¿šé!Rž:ÚŠ÷ÒZn —ÌŽGûšºuÚ5|^÷®¶š.UÅ{UkÑŸu3/Kº#±÷+嫯»l•ÿÀ`“vyÉâ«#Z3F­Fϙ; ÔšçµzJx£N§7ŒÎ’–7ò&p¬6opç^+~U˕$Ÿ:z«}ÿå՝€Q9øΚ9`ºÿ N-óó:óëÐáα÷Õéñ綌Ԁ²_2fí7,mȔ©-‚=MZ]ЁJ…êÏéØtøÔ®CnՐfDœ;—ÞgàìÒ,ƌzmЁ§æŒéŽŒÎD€ 90Æå4£KÉEœwíê%äâwK,!äüùóóçÏ×jµ‰„Rj2™¬¬¬îÝ»‡yÝ}žçߋ“¥,åî5äîä™É÷ÎþÛo… (Ïò+ô¹`æ¥F…µK¡".Ùe5AŸp<‚ ®ÿYG>¹\ŽF@Ð{Fo œ^¿lÙ2ó@N£ÑÈqÚäëê ét:žç±÷ƒ <#È7ŰaÃÌ~|=Ü IDAT+“‚€ ýW‡X,6™LhåAŸ(¥nnnYÛ:Îh4âúÌ_c9Z\ý APžä«$»£,‚ <ÏãŠ_¯HcÙ!(Ïò JµƒƒyŸÙµÈ—ŠD"‘ÉdhåAŸ)yvvvvrrBS|ՅˆF@PžäÛÁòŠZÈW^šb]‚ èu!XšÊ3‚ ‚ (Ï‚ ‚òŒ ‚ Ê3‚ ‚ <#ßžlÂhŠOŸ“Ïøì_` Äò‰Á‰Uˆ…fÈ<Š4***<<ü»]³6_¹reÖ¬YU«VÝŒyówkÈÈȎ;FGG>\"‘|F…ÎÒæ3fÜžqãÆöööùzÇiÓŠ3f̘1•+Wþ\ -B˖-÷ïßÿÙkœ{÷:uê„íò©»†h$·6ϝ;·jÕª£G†ïõ•¥ÔÏÏoÛ¶mǏŸ3gŽÉd2«ÔgÔæÉ“'ß¿÷îÝöööù—sÊãÆ«P¡Âœ9s®^œjv©?˳ †/¡2dddäxŃï¡”gä3hóœ9s*Uª4zôèÛ(ç}òŸèù*š6³5üýýW¯^}éÒ¥©S§~…6—‹J¥;vlDDĖ-[ÌaíüóeÍÏÈ0ÌØ±c˕+7{öìÐÐÐÏšÐÿ¶êåS&yžµZ­ÕjyžÇ¿O·‘׍rhhè̙3«W¯>jÔšì!ÍC‡œ}8!ÄÓÓsèСy(!ôÑ …B$úBJé[WEüïfN!00pñâÅ#GŽ?~üôéÓÅbñ'.µZý믿ªÕêuëÖ999}‚8sv…ž5kÖÔ©S'MšT¡B…/X“!‚Z“NÀÚÚZ’©kµÚˆˆˆôôt¹\îããcmm‚Þ3ò‰ˆŒŒœ7o^ÓŠMCBBrŒn\¶lÙíÛ·¥R)›F£qذaJ¥ò--xÔúÕ£ﻙö‘†ùBˆîÖñ£þùçî={ö8ròèÁ}{÷îÝ»wçŠ}Ó…ÿ®%YþbÑ¢EçϟŸ’’2sæÌ÷ñÏ>®7räH›å˗;;;²wÀY =zôèÆϞ=ûŋï|4A>_ýåN÷ÐÿLL~¥ÎqJ¥R©T †·h3œôž‘O||üƒöîÝkÑõËüì,Ë8pᅏ?öññ!„Œ5*&&&‡BJ–,9f̘ÏWùÈó».T•Ö`F&“…††Î˜1C$åPe‰D2oÞ<777lI”gäã7@æÈmn „ètº·\«V« !,ËŸ-Pã)õÓZ9È䯵¢¶(By(“u­N¿iM"‰UÜÁÛ;n—ZÛÿ; ËÙoq–+óvI³#Ï~»,…‹ÅÇ=þŒ@7oÞŒyóæèÑ£µZíëÜX[÷ìÙsذaWžÅb±Ù°YYÊm AÌc—²6r?KŽ«òڟ=‘¬g—Ëåϟ?OJJruu;wî‚ €Riöê·dɒO$ÏyÔY1(*¿÷y•üÛ*ŒX,ŸyófxxøÐ¡C333¥R)Ïó<Ï[[[wïÞ=$$åAyFòW§ó¥Qå‰X±× 8°ÿVŽc¿3»Ô*À ?>¯Íœ£™"y陛•w!œA}a÷òñ+‰DÎÅ*u5¥]!…(ñö™ÿ=M÷ò³?Ÿ}í¡+\÷1¿umRÞ+ ˜8=ðfÝJ–)mÇ@Úáyâ+ŒTÛLš€KGw„Ù6é\Bsæü-‰—ûƒ#ëw^6µì3|`—šöb·v œŸùvŒÊÜ‹š”p$„P YfȒ1ARSSyžW©TU«VíÞœ{Žg4G¿óËͱ'>>Ÿ[·nVVVF£±víÚ!!!fbf͚5ûöí“ÉdjµzÕªUæC„:˜ÇBK¥Ò;wfí 4hµµµ^¯oÓŠM¯^œrXÚ`0DDDXYY‰ÅâaÆåš$ϟ?_¿~ý'Òf èÓs['.Þ¯ÌàL×üRÌ€ÞìG3/ï]1zé~‘Ø©pÙv£§w°ƒ)ýìú«6‰ä¹VÆöéÔÒI Œúٚá“<‰Q›Œ#VîoQҝeÞqsAªU«f.úž¹¹9;;À”)S°é@>.øîùÁYý/)XYY™‡§æ2«€Ãs;ÿq’«^ZzoLú{o=0lÒšÛ9×ÖœºWrҹŀHxCFôÃØjmºvhêubúÌÉw 3öÆÎ©êý2û.PÞíúüA+.ÞJ £ž ŒÑÄS—è^Ÿ>dq"ÿèôìi+µvn\Ê£Ãsi9bÞ9iɺ…Œ›'w\Œó/À?#zýŒ*®x«-+èwì%N'P „楔ÉÉɉ‰‰mÅ󌕕Õǵ›Åºjµúäɓøë¯¿Ž=š]Gïß¿ìØ±œ>}úúõëÙíÞœûÀصkWJJJÖ~£ÑxêÔ©;vìèÑ£™™™¹»h ÍÆgϞ ‚™™™ãšV«}{ìäË幍lvn¯ ïÓ®ÉX•s©¶ÛÕ®ê@˜7rËU‘÷¢«¶îÚ±yáž³ÓŠŽ»·ölX¶ö”{óÎÝjæãâF)¶úg‚M“®?·¬WG.•Œ¬Lïê-e-“²jÕªk×®eçFÐ{F, •J/^ŒØ­[·žCIMM ÈÇ„Îå[oä°±!?”P ¬“ZžÎš¿7tŸÿë_çl˜ß«m)Uiñ¶’=ÏE.ëàÞö·Öö¶Bò©š£KNßþG e h£‰{탎h. •ouðыØzœ%¯‚ЯŸ…QÔìÐ'qɬí÷§ýZDwãèþGš†ë«Ú.hâÞÕ:Y׳¶ )oÝöïÃתé2óØa&³zµëámòß±Œá¹°yÝ}˜<šZBˆ F£ÑÖÖvçΝÇ·±±€ôôô .888L™2E&“qg>ßÖÖV¥R}øïS$rpp°(–YÛ¡¡¡r¹\–eccc³ 4hʔ),˚Çye÷Â˖-kkkkö’³‡è9ŽËÌÌŽØÉ „èõzJ©T*-^ŒžY;)¥îîî»w ‰7çV*•2 £Õj?Lކ‰ŽŽ.ZŽh®<š¯N9ž×ŠÃø¹SzóPèµZ‘œx=äP,wi2£›ƒM»ûׂƒ·®é¡|zDØ¥§)]+6P·å)dF\º~!°èä»Ôô”seÈûþÖ"##CBB<žyóænݺ͟?ÿ£÷NåùÁd2?>{Sûþ°,{ýúõßÿ=sh0ö/Õ Tq;™d…<­m"2 `Ð'YI otbK]xŠAªœ²gNç1[mmœˆIâQZÏp™&ï"å~lZÏK ¹µDÊæ5H–âT²ÍðJ×ÿrºß1Ã+.U™~Æ à¹‰wu.PŽB%W+1€§—³«>ÍdÌÌTÛٟ_:ŽâŠq,ÑÅsâ¶Â{5Ò:®e˖… 2·ËÇ)RD£ÑtêÔ)KºD"Q·nÝÖ¯_ÿÁz­¬¬víڕûòìneÁ‚Ǎ—žžN±²²ZŸ|yZZšùP=Ì}©TÚ»wשׂŠM›ŠÑhÌEÿøñãŋ›÷ †·¬²nÖZ“ÉŽuëÖ¬\I¥RFãää4zôh³S.•J÷ïߟ’’Ò·oß·ZÈ ‰D²oߟ‹/ZªI\¥å+—öqµa(¬lrεƒó;þ¶ÑÚÚU$ˆ gê*uîÙ÷ڃåõŠlšùóŒ){Õ.àØ{ãÜÐö£[[¯hüÛá…CƒÝäïù[óóó[Œxq\\\­Zµ $‹?ëšuåù‚ÁÖÖÖÛÛûƒSHNNþ°–ô}œgJ­­‰¹ÊÉY råµ*Á0~Wh×" ^±ÔÆÝƒtzEiÛç:_ÏúÅöù“öÆ  e³¯,𥠁Œt”ˆäî݆ XðsþCk^méR(©Tbe%3k ˰RVƒF•žÚnÚªQÍ«X…»·ûÍóŒL&«X±böÇùøøøûûgwÿ‹Ý,FÑ *tóæÍ[·n±,+“É‚ƒƒ‹)Âq!€Y³f¡¡¡IIIàââR­Z5…BaVÖzõê]ºtÉì1ûùùU©RŜžÉôöî; ‰óøóÞ]6„œ‡€ˆžPàÀœ7nѺ­£î=êjµGÕºêhmuתU[ëÞ'nPÙ$!ûÞßAŠ”_ú|þ$—äVî{Ï{ïÝéûöí{çΖe%IVV–éxê;e͚5ó>óèÑ#‘HdggggggzÆÙٙçy=á®®®Æ\<ª Œ®€ãƘsë?›õó7û϶’¿ÜûýìÍQz -WçËmûû?ŠX=}î€yË]6|ÝÉÏÆœág;¯7{prb÷‰Mܟ/î.²…Y“ÀÍÍmÀ€nnn€§T!Œgô޲æ7E}ðLb/‰Zžc¿_«Ú£êÇ ßËMoVÅ:@:Þ‹zokÿ« qJü“„,IVÂƒÄ œoyææ©?7ŸdBÛòŠÆkš÷êcÔðÆ¡Bš÷a9ŸŠ}{ÀÚ͇.ûÞÔ@  R¯EünWŸÍý÷wm=w¿bÿÁ[ ¶°7A```•*UrOPfÆ4JvvvmÚŽ1ÏóB¡0w±z{{çîÀ™Nš2•þB¡°N:Õ«WÏýŽw{þŠo ‹·ÊGžç‹j…tª?ÂÊaÆçsêx¬܎ܳûwÅ~5=€ÿŒ/#á~bº®Œ‡àÁÅÃ?ž`Ú6€„èȵmPí6]œÖþ|!-MCÒ.œ}ìV¥zõf¡™'“Ô|!FØt•éÿáÇç]ô˜Ðèã®aÈ|qðÑé2uZG~ÿԞîBw›…]–¯ØÀ‹€Ëâøë,­ëm-ŠËUª¡UiÐ3Ô.¡‘“°ÉøµFôyºÿ›¡ãþPIz­Öț6…œV+Ê{® 5y™Áє#±­:xvsŽáç j“ÙÀpŽÆs‡¿©Á²ò*ýžŠœ§ •‚pÄñcK‡Ý×ÑS(Z»VØÿ •§ffHîéD£ 6ˆÅbQb±øáÇoûQGþóÜLc" P(ä8.w©™òU ‘H”w¿Í”ë&Š›|äÀ‚>-ÿ.ˆP(œÉÝÝ]"‘ÇÊ `9îôÑù=cŠu®d!“úN{š©œ4z@X¡n¯î.¯š¹ˆê›Yctÿ—.:ì—苇U÷ Òxûã#všd ×fŒšm/ ¬Ç‘F?Žk-°ïÝ –J¥«V­Ê¿èŸ,,ì×_5uê1ÕÄ;wîœ3gNrrò»+€ü§ÃænSóß›¯‚ 8³ƒôþ7ž1űĮòï»5jdc:Wlšµž»¹¢]y©Ùï5[Yš²yϞ=SŠLYºt©——WîSïNž\‚ƒƒ>Ü®]»œ{÷6iÒ€2 ÷r%ϟ? èÒ¥‹X,~oçäbJ&s«FžkÈŒk 3«Îãü¡S€ÙŒ0žQ‘Ô$R©tâĉ:nðàÁ?ýô“§§§éyJiåʕ ¿eÿ仄°V^A¡^yË`»x‡žxr$sëæß~ûmÜžq+V¬ðòòÊ{OÉâŒ5EPPБ#GÚ·o¿{÷îŠM›æ?úðѳâââLçeõèÑÔÍ%ûž’•5Ø5 œ‘‰dƌµk×9rdll¬éùÂ'AIšÌÕC€À"ªà1eóèÑ£óg³© Uq.—   C‡õîÝûøñãE:ŸMŸüôéÓáÇ»ººöíÛ7o6›úFý×jD¬‰VÏšD$ŽX,ž;wîìÙ³'Mš4{ölGGÇb8YšΊ3gÎLš4éûï¿+›år¹T*-æÛ;8p W¯^?üðC```ašÙÿ́㒒’æÍ›gcc3`À±XlêfšXOOO—"-ßóNµR©T(ŸpMIIIžq@Ïš€$ô’%K/^ÿÕ/r¹|ëÖ­‰$o6[ZZVšP!÷r˜Å\ÀÕ­[÷üù󁁁:.·7õÇeê§=hР~ýú †·²ÙÔg»xŠÝÁÁ!22ÒËˋaӅT?IÓºéKCBBðº`㕈„&„L:uêÔ©OŸ>5]$ò¿–ДR•JeºWn6ûúú6çŽ!ÄÃÃ#%%%---..®è®$£ÕjMq˜{¡âÌfJi‹-òÖÍQQQYYYÅsúV~ƒA¡PàÆa<£OŸÐ¹yàèèšP(ÒÒÒþ³'äÍf++«O5ò.…BñìÙ3ÓÞCÑ}©é6žžž¹ý‹­=?ïÃÌÌÌÌÌL…Bñ©â9Æ3*eŽL&+_Ÿ‘Häããó ³9ۆ‡‡!$!!¡šO²rqqñôô4ÝðêSM;Ã0"‘šš÷E 37LwâÂxF%%¡}}}MWäøoαX,“ÉJHûAÞgKKË"ížÇ²¬••Õ§Íf‹ÅžžžEÔîÿÛbr\ñ\Ÿ!ŒgTš0H$ÿñ­R‰jÛÏ­¡mllÊüŽ›.nmm+ÂxFèí0À™PÒfBñ÷/±Sj KUÃçî‘WµFõ*9˜ €€A£HMNxp/Å«v { ã!„>n)KÑœŒœvù¢cÉNµ¬Ó6‰?kr{_KJÁLŒÈ:Žÿ×§Îßœ¥³v©ëÿÏìã€*Ýé ÀGlYŸ+ÆsÎŒ9_NŸÜØêÞú5»Ô„ÔUÂÀZžVò+'±€„ðX#Œg„*‚t†€'ŸTâmcáRuHFYŽßȄ7î•òÏÀªC‡Î_ ëèb/Ƌ Œg„úøÿâö [§ª åÅîU¬Êۏ•ŒRÊÐé0šÆ3Bœ2UCš0ŠžfE‰Þ÷"¥ @Ç~]ã!„Šˊy B1›SN Ç2vv2œ3ã!„>Σ¢—žF>ϹªQñô•ü<r ü?}Ä(}}q†!D@˜ÜpV"Œg„ú((«ôkiueÍÊjÝóœËwåšžƒúÕ£­Kæ­üã>aHòýS+¿Ûwå9!„^§EjšÞÈggª2j=å))ž£7BŸd¿gBšô"”!'-¹7~ÔØeÄšU~³õsk€4EÚœ“§Ò Í #š^ÆÝ8v÷iÁúË¢¥O^JVéâçOÜ€·žµy]ãr¶,“FÏ!ô‘ò™P  ¿aËvµ‹{¡d„ήîN6X—«5sÛ>*²÷=Wîî$Z€mŸ1Ó» Ó†¡”RžÈí¬°!a<#„ÐÇhJ$r;ߪ¶€!Ät$™á„r;; ”r"©µH 9‡˜Y +‹·>…RŠºÆ3B}̀&9þ¹'6É÷rŸÿÍ}B%¶è „ÊdX#„ñŒB!Œg„Bã!„BÏ!„Æ3B!„0žB!„ñŒBa<#„Ї(!·Â»X¡O¯†*q!‰‰‰'OžäyþS]eÄÎήmÛ¶ž,Æ3Býãôéӟ}öY—.]t:]ñ»N§;qâ„Ñhā0žBè”ÒΝ;ïÛ·ïS€T*Å¥€>!<öŒ*¡>IÝl’‘‘ñV£:‡FX=#„Ð{ ëüÙiîõ7‰Ì;L/äÁó<¥4++‹"‘HÎy„ñŒBïÌfCfÌçJÎÊÍÃÃNÆÓ=ŸßYBèõj¥2[,¶’Hž7_P¥f¥621Ç /ŸFã£G”J¥@ ðð𰵵řŠ6n#„JBhãfŒÒiNø˜Ží÷Ý{~ëà–×^ÔÁ;íò¹E#f¯ŽRŸý‚2rÆø~'î=1‚™l6ídeeeee©ÕjKKËwì.àBAX=#„dÝØüӆì!뿚ß=˯¢íÙ1Ã×t:Ù¹¶«ÙµªçqÏ3ù7Šoà3Ox\sæéÊ0Œ@ ˆ:u*Ã0ù‹øo¿ý¶~ýúžDÆ3Bè?ÍŠ‚õm4¬{oK›õÇkÙWsMÔ@d¬µ‹Ø0÷ˆ3XÉ€RwŽœ·XõêUttô¯¿þš••%!:ÎÒÒrüøñ>ÄxFE·B¥!$+r_ïÙ^Æ.ZµÜÔMµTsñð…G/Á”͆Øu#ý||Ztœ~/Ëé@yàsޏÕ«Y9¯°ïWýŠaÂæ{ÝÝݛ5kZ©R%WW×ÐÐÐæÍ›ûûûãAÏ¡RVæ …Âù‰Dböª "çÊ-žJÔuŒ ñwæÑ¡U?GŠoHXV¹ùleïåkæÖ±Ÿ= ×ôd.§Z&µvÁÞû Î€ï—txŒuw|bÃ*žy>§mü̙3;wî4ýo0pA£¢ƒÛ¡O*•®]»öäɓÿ®çÃ0 µk×6ώþÝBjÌ­bÑ©ïÀZŸv€7š¥<Ðô{GæDÇMZ3¬cˆÜ9;ê𛯥‡×f Ã<ÛrápvãæS&­íí*‘£Í7 …:µšã8…B1|øð]»vñ<çΝõë׋D"\Ðã!Tšh4š6mÚL˜0!;;û_Œ]$íܹóðáÃù‹rBÃé@D¡c‰éˆ³©f©QÆðN~K hÕz[Ï6R€˜ú{óš4œœw¥òŽb¡TóòûFKKˍ7zxx<~üxÛ¶m‰D¯×ã‚Fϡ҄R*•J-,,,,,þÝ'Èåòü­ÇŠŽ]x @ó%«^•¬xíµ€Þnz8¡ÄÊž_fäÁ˜®IÉ6€  S‚QoþœªÈd²¶mÛ&%%I$ÀSªPÃcÏ¡ðï~=_:ëj‡5Z-‹1HäR&-)ö¹XS¢ó<œk;ºó€B©MãÐ~1àåy#¥ës¿êSM1§•¿Så%MBº:{ë ï¿'•P(ŒvíÉgïÞœxÛ Tt°q!TʪjûvËRÚåVØdðq~pÎeŽI¹Æ«ÎÑ%Š ˆ,-%(„ Üð×@ÓÀ¬sÍ-ûÏ®ÏÎæ…2©H0oVn^àM¥ CõêՓ““ííí ŸOuGj„ñŒB%EÞ,Ìÿ¿),ŖÖâ|ÉIJ)+”X ßÖ÷¥+¥4÷»'˜Ê IDATĪwB6n#„Êfx›IÎ÷ŒŒÆ3B!„0žB¥».^‡þÐ'†« Bš„fsRRÒãǏ³²²Š?ª žÖŒ0žBèmîîîmÛ¶eÆ`0h4³—à.ºƒ:uêç7"„ñŒ*é(¥ 6|üøqî3ÑÑÑYYYoÝt¹Hñ<¯P(pY Œg„ú§xÍû0333##C¡P|’£ÑØÊ0žBÈ †a$ ÏóŸ$ž^¿a<#„ÐÛ$‰§§ç§:LÁ‹w"Œg„z¥”ã8¹\þÉG¯c‚0žBèŸâµ °Ô%ÞÙ~è|–ÚàØ.Žaù"MPÌfTÌð²$¡ÒWQB õîêå‹÷^OЊ=\ºtñš „ìŅ0žB蓥3ÜØ¹þ·'®ƍ7yöȺš]«zÉ!æó™ŸÙýú­ÎØØ7a<#„ÐGIçô?/ĔoÖ¡Ÿ“йw÷¶4þܕÀ|K8BÀ˜þüþÛ:žŒ2öîÝš„œK’aB£’=#„Jé÷î+µœ(aÝ*{°ú돒:{ž˜žÅåû×mڟªc›öŸþYc›7FŸHII1Ôë3yD‹JCÍf;BX=#„Pai:Ê3ôu  XgñÉ ®‹»uîÌ5ç&C'lŠœ±kÒ“­ªúbæ”î^§>Ÿ˜©Ìf„ñŒBŒé%\Nªò pq±*hpœ2‹wp©Ô°EÓncûúj¢ˆì|*x×iZ‹ÉÈÒêØŽJlÜF•BN~~ŒèNL&Ô§2¢ž‚.ÄË9÷õ·N²bĜþÉó—.ό>ú+OS‰õÙ KìÃ%vœt¯/sX:#¬žBèƒP·>=b·­9Ÿ ºcÁ:¥ K«Š"£6å÷…cƯ=OQ&ÞÛ8orøžH”iߺjôΑ [Ïe{ÿrt{×J’ß—Î]qFM)}ýˆÀëǘÍã!„>F@“<Þú÷͹ƒæ}XÀû*)°kB!„ñŒB!Œg„Bã!„BÏ!„Æ3B!„0žB!Œg„ú`”RJñ.Pa<#„J©TjaaaÊé—î%ÿ—2*RxÕ0„ÐÇ'‰Äb1üÛKrBbcc÷ìÙc4KÚEœ!͛7¯U«.e„ñŒ*e4MJJʇ|Â¥K—f͚5|øpFSrŠK(>|øå˗Ïã!TúØÙÙÅÆÆŸzõÊÑÑñß}¥ŽM›6+W®,i“æââò{{F}|®®®ðôéSø€ÃŽzœŸd6 0 ó֞.q„ñŒ*Œœœ%Éýû÷¡ÌÝŠ’­×ëSSS E <:Ž0žBÈ J)ÇqÕªU‹üøq«/†IKK‹ŠŠŠŽŽ~ñâ…Á`À%Ž0žB¥Fpp°Ý²²²!ŞÐoœxýÖyØ22„N§R©”J%Çq"‘š ¯Çu}ì†úÈLa,zôèŸmÛ¶aÆqG)-Æv`Bh)£žpNU*º[@Vâãèj7?gчÄ>!„"—ËÃÃÃϝ;÷Ö¡h°¶¶Ÿxñ"® ã!T988Lš4iÕªU?ýôÓ Aƒ„BanŒ}H:š=šMò?©¹{ï§1ó՛þà¶å×/¯«‡¬ ï‘óQðÖœýLA_àêÕ«ýû÷oÛ¶­V«•H$Z­–R*‰q飄Û¡¢* ÀÕÕuüøñIII³gÏ~ôèŒÙSìÿo6Å¥æï-«ùÚZۄý°må Aß=Îæ bWöw°±s«VgÈÕTՋý¿/^~ýâκýzþóô™u—÷ݳ}š§ççÓÖ>NBŒÇ—¶šâmkcÓ`Ëå—@õ_პŽN³òþݟ’wíH˜FŸJ•*uëÖ}øðaµjՂƒƒkÔš+ÂxF•ô„vrrš8qb£F-Z4iÒ€ÄÅř^zGú‰D"žçó%"!ÀÿÑ­}Øe/·ÚzzôÌÍ¿œHÒR€Äp· ™dêÇv N kõyœÄµrùÁ"û“' ;šr%ïkÊåýz}óMŸž-Üm G:·è¹ßkÊæÃ¿|0®} HŒºu~ŸVŸ%¶ønñhËBLŠÑh4ý3kÖ¬ììl\îècÁÆm„PÑ&4!Ä¢uëÖ 6Œ}ûöÕ«WÿüóÏ/^øùùݹsÇlÍ0LRRRHHHŸȺŽàÖµËvŒìÝÖABjJÿ­æHÖÝÃs^¥Ì ëVËÇZÖ±Ùæíß]O†æµk× 9`Ñ Sãú6YdzŠFÔ²kÓÊ2ÈŒ0ÿ~d“~CWšæä×Ëoʆ‹Ñ)ÍÜmµ]åÏÖ Žg 1Ûbþ&©TúÇŒ=úÙ³gööö“'O^²d .z„ñŒ*54Çqr¹ŒAƒuëÖ5”R†aò×ǹ¥óÖ­[wïÞm®\åUFÿ*Ü-Å$NrSÎ1Œè×í|çðìÜÚځg(Ïß.Ÿ9 eY&g@nóûÜÏÌcxžºôr(4 ià$ärÊõ÷(W«Õ]ºt騱£Ý™3güüüp¡#Œg„PéHèÜ c†a@ðÞw óGŠõFBÅ%eè æàх‹<•€>;»ñ^öŠŒÞH a9^>áµFPä¹ø˜Â@4Š]R‘öjø'ŸíÛDÎ)0,ËP«3@N_³÷wbËÉ)SŠž¹¹™º¿!ôáðØ3BšøBúQp çîõóÐáóVlœßß®Fß5<€Ryõ.“šqdiâ2ÔÊÔè7Ÿš@"c¯|$,\$©^ž|ðZ&ph2ÕÃ{óÐowüy7+[õüAĝ$Õ#\ÈQ¢xžŸ6mš••UAía<#„ÊnÆSJA2ôܱ]«º>Þµú^…Õo™Æ€Ö”Œ–€ßžÖdEˆ£•­K‹nb4`åS·É ~|Ö6tÐÕ,(ßlx®Ë§72Ó3à³³ç6Ï|õUÿêvV¶åꝊUPV(°…Ý0:99uïޝaŽãX–å8Žã8ÓC\Xèc¬íšô;}úôáDZOJIÓŽiÓS§Ná|ø¶oߟmÛ¶#GŽäIª4ˆR™ˆúÇdq÷Sóž]æ”›©ŽŠ„òÏiÌŒAÏ3Ž1õô¢zϲ,Cr^æõZˆÄ‚œòœäÔÄ•ûóæÍ‹ŒŒœ1c†B¡puuõ÷÷/šªÆkq£»x¡RæL—Š}S-:ulğ\Ÿ;’ûò·^Ž„P0wE€ÿsõ“œ#ޜ€ (!DÀ±“Ý”RÂDâ·µÉª×ëÕjµD"1Sú`6#Œg„Ð ìùýòµ{1‰ºÁëÇ·ïè!ʍķã1oHŸ˜¯ÀDEÏ!ô¥TjãÕš­W£Œ¡-ÉšÌÁ®a¡’ºybÌl ÌÆpqf3vûBX=#„þÃe2!111çΝ3ݏ²„ÇR©422²äŒÂxF¡bUŸ|y[[ÛiÓŠ1 £×ëU*•Á`øä¡hjEïÕ«—Á`Àe„0žBÿ-”Ò   óçÏç>m*£KBY¯Ñh4 .&„ñŒúoy+†333322²²²Ìþ„ûx0„ñŒúïbYV&“•Ž#Ÿ<ÏËd²µÇ€0žBšøˆÅbOOO£ÑX¢â™R* s{„0žBe ¥”ã8 ‹’<†Ø‘a<#„þ[ޛ|ŠtÌxxrõ®3FVRµIX·rÅ™˜Íš(àQ„Pé®® !ê'Çç-\~+ÛÚY˜Œliø†+ɄŒÝÂê!„>Y:1œùqÝ%ÚüשÃܙd±nöž¿ôžbCšÙ»6SJóŒØ4°zF¡ŸÎ@_º–ÚÞ×N*¶voÕ2D‘põf Œ3›ÕO#/]ºõDojšÖ&G^Œúð¥:g„°zF¡A ÏoDéI/'Óc‰‹Ÿ£þàíÇÍì­Í Oð/·­\³çϋ"ré0iY˜ÝŒéKtVÒøE«qKÆ6ö0_t#„ñŒB…gÔf>§ê%a ÆÄWéÖf‡WÞüëÜœìnS¿ó}uxÑÞµƒŽ*›Û=žBú¥ï§,;5šqKœ§šÀÆm„P)/28)D$Í)6ˆ‘9ÖÕÕº áõÊ A¥€ŠþUê‡ÍüÌÝ"óE’¥}9OG‡êµ*êSÓñRÚã!„>Ö«ª¿‘^~˜@©6íA‚€©èn“;À[‡“9™Dsñ泞eô¡ÃÏy+éÎÙc~9z|ùŒmê  œ¡ã!„>â;ž«óÕáWӌ ˆÞüÍN‰cïfΠ|¹jêó~œIyyãÐì‰Ó7ŸŽËÚ}ûµ”íýºg³Þ[›ŸÿëáÍ­4[Ÿ·ëEàw“Ûà5ÀP ÇžB¥¡ ¿zȳ“»¶`•ÉÛ®ØÚG­Q'?z’î mVúˇqŽ L·™’5ú|~Ý~j 8¡€!0yËïÃÒÕ"+K1ǘ"»†¡’°nãYeÁéÓ§>ŒdÉœ%JÓŠMO:…ó¡šKhÓ©Ëé/_ª££ðÍs›óžÙlz^?C)ÍóÀô*BX=#„Ї—ŠHµqv¶ÉMc’ïåŒÿ¿~ÆôðŸ×1›Q‰ÇžBe2¬ÂxF!„Æ3B!„ñŒB!Œg„Bã!„BÏ!„ÂxF!„0žB!„ñŒPÙT6®¹‹WFè_À‹z"TrBΟ?¯P(Jï$T«VÍÝÝ%BÏ•)ǎkÜž1ÔŸ†.ŽãnÞŒ)“É0žÂxFšÌýD9®Y³f¥täU*.A„þ<öŒP‰FÑëõ¥täFã[u?‡F«g„ʺ7njüžgßûþŒ7Eþˆñœžžž™™©ÕjÅb±L&cY—BÏý¢9+z÷–mÇnÇK«wé߯IEBhᲖœ:9%Y,q¶±EõüêÕ«šš(NgooïííñŒP!aã6B¥2œMÙuô‡j¡«b¬Û††ÖrŒÛ§ÚÔÕÛU@!…lEVFß[Þ"løõŽ"Sœ^¯ÕjÕjµP( …îj „°zFšÔ‡3!ŒOÎîì?lyÃy?ÏïYÇN&Úº–Åð™»7:Ôß«2 ðþÆjžÍ6ȞXf“"WSomm=a„‹/æï‚nggwïÞ=\ša<#T*gÐŒŒ·{ӌ¬‘¿®Ô@›õ×ћŒœ_œ3føìPÄþ»m*Wµ"oç³Ù&o–-XY-áæÞ‘ÿØöûv³,{÷îÝå˗7nÜX¯×‹D"NG)eY¶\¹ržLÊ·*e!@³ï^»Žár·SÓÝܶ C£Ÿçc#ÖLùúûµÏÛL{ÂHnG%ƒùlNüun?©D"•ÚxùÎOÈ{(X9õ³æ„–ø6cgŒÊ@Q¿Œ6­^€œHLYq2JÇBHâÍ=-eb©ÔÁÅíH<)LŸ2J©›››»»»··÷Áƒœœœ===q"„ñŒPé ãüŽÊg4ž0Æ6æØßŽÙtrÁ˜þþ~µ3ÒÕàìÇ\ÕdF¿},™B e¡•߀¯o|œëDÄ士¿«Ÿ'› €§dVîvâNôñ_jFnZ¿gÏs݆Ÿ#Î{wÝs-âÂáõË»0qsBú©Šo¿wïêÞ <¥…=rÌóŒéŸY³f \žœ6n#TŽáÚŽiÓývJ©³³sþžSmVÔ­?nمŸŠœwQ»0ç=gdd¬_¿ÞÇÇÇ|{@\î¡Ò·*M(¥ Žî=}[ÒÕߚZgÝð\äêYÁÏ]øî·åüîs²™æ E†äí!Nóf'@N6SJÉ}’Œ~æ}áJÉÎÎÖjµï/„VÏ•‰„&DäT©Ç°Jo”¢…Ì»·‡Êû˜˜öõÿùÿAa<#„ ŽF L„ÊlÜFšD£”r\iݍÎß !„Õ3BeÑhŒˆˆ0%ŽÑh,E÷^±±±,Ëb=Æ3BeMœzõbccMÿ§€€€§§—–Ž3íITšPáëŸ „0ž*í(¥­[·Î}WŠŠQBˆÁ`0ž(ÂxFšìțĔRF£ÑhJã]žçKQ³­VkÚHHS ô§¶‡OÞùâכ7· o.ç8¯aûu~pkÓOG”@HŸïàDÙJ+ZÐG0Ž0Ãæ{ª€É4óyŽà¯.ô(QB šó+Â×^OÍ}*¿Ä¿÷­Ùyü©2ç¡0[©f8JÌOÿŸ{ÏQŽã®]»Öžqã®]»†††víÚÕôO÷îÝ«W¯þ÷ßãÂà,@šš h++«õë×OŸ>]©T¶iÓÆÙÙ9oôÿ6iš~ùðÊOۏvßv£“ͳ¿~=“žš®ŽkÑeÐÂqUfވžú¬e3OQŸeZ¬<"±Fœ;£9 ¹«§—T¯•xû8êӓ’³ŽR QblÔ³$Þ§j•òîöB =þÁ­Gñ:œÑÊ; VEW¡”7ŒzúPeé.N¹•jQ¿auNýêÁík±©"çrŸUª”’¯=g ”¯b¯DFŒ<+p š[ÑQ*ä šW1Oôö‚ŽÇ×£Òì]ŒªøZ°Dš˜¢2ÈdÜó˜è„ð šêãjË€Žç÷n=z¡7òÖÞµü\8ʧFGüøå·¿O«Õq¶šäa¡ýàÁӗ cáäYŸR%71Q^XœvV¢·NÈt¯_ÓÛË9øë-UX¹…¡1Ÿ|ùä0œC…^v„Pœ:+9!‘Ø:ê^FݍU¹zUð÷÷0ŒêØÈ;1IiÞèXßËن{ßb4Í›7?~üø[ÏwèÐÁ`0àïa<#T¬4!D.—/X°`åʕ?þøcpp°···œœœ\.gæÝÙlþUCVlôý»²¹w‚ ¿ÍŸºá‚åà/ªþ9ÿØËÌàU »œ8ñøAR3OÏ|oÓïÞ`wÛý‡‡Õà Y×ֆOY²(Ö2žœÄÓÑ&ÝèÞeË/#Ò®ìYº~o†Gõ䇗/žY¥Ýœµ«'Ö('M?»oނuGâ_I CëTkÔðÅ#z—g é¿Ïh·MÖÍ=ëB‚²Þ¶ß<ü~îW~•loëZsü7sÕ/hânìY=lÍßrŸ­j?kçÆéÁ:EüމízöõP\Ûÿçu+yõikýŒóó³[—o;Švó¿9â䭀ЅëWªì&I=¹{΂õG_ŠJI†Þ9ḧş÷ðˆœŽs€ü—•s/²Vìs{Ÿeñ¬õçcdjµÔ­Í·?,kãpå°"Ñp?íÀ”ËI=¥ë¥™VúÌÛ5®•žý¶qjøæË*•«âŒ[LóMï–öÊø[?N~Ý«³,éÊ_]w­Ðé›Vu¶‰>Ÿkþ—«o«ÔЬ”¡«ÿÛ1È¢TNgúgïÞœÙÙÙýû÷€Üf„0ž*Ÿڔж¶¶sæÌ9zôè©S§®_¿îèè(—ËmllX–-èž#Çqiiiù›Lym¶23ªbXϬk_Œ=xë^1·÷T„8:>×2iJsãšÓâ^š€f>;;vÜBa¿Ã‘[Z+/ìÝuf,IåFyÿڙK)•Ö·ó»áß¶ëyäì^5ÊÉŸêùÙïcv›ì¡Ü>Ÿõgacjµ:PÏT‰ñžG ünýáQ'~š0ó·Ã·7ŽÖÎî7xݲê†,õœVÏ¿ž6žN$0DoUŸù±Ëá>rº¢°ËŒ} Š[>#-î荳_|~cFò·ƒÆmZñ÷6ý9Vyùø¿J?.Û»ìᗭúŒ8¢Ge72»kØ!—YûM¯á˜¶uLë=ÇÖÎüœJ«¡cíz0oɏ}*…b­Â²ãàÙ®ÇßYÒ»ãw»·õm¿¬yŸŠŸÏìý'}5¹~yêô§‰J=,šoŽí>òAãõçÎ qPß[>84¬#_G³Ñ‘Ñ¿ˆ{x0ªÂŒ%Ë¿™tnTï5»wFtn~|ùÚÓÒZ.km©}ÅËą;TȲ,œ:ujýúõÆÝÝœY³fŠ'ÂxFè$40 Ó¶mÛ¶mÛÞºuëáÇqqqñññ„””†aÌŸQ¡Päž×k^Å?Hr×€€Š<¶êe JUAªÀ^ `ø‹DöB³c°`K€ÏŒ»wEVáÜÆvVV :ŒXxÒŠL@¯Ñ ª4ûzηý‚ltâzÎî‘J£RžíámÆþôyo }ç…÷[ÓîJŒ²~𔩫œ¯] }©¶f‡–V«Ž~?}李ÝÂZs ˜Ž¿weÐh4—.]ŠŽŽ6 çϟ ÂÒa<#ôÉ^÷'"„ÔšQ£F…yã… óo»¡ÄÖ³†È °¶”éȋ#g&GmÝõ÷ÅÎU[<Øv&›“;úžô9•8ψž×Râ_0Œð:êlmåd%Fa4 D,eˆHB™œÁ ŠÓX–T²·0 ¥À³”©qÊl—À6¡-»z‰h”Z§S*•"!`ÔiŒŠ}„ìûÓnjžšt­âXÅÉ!€ <ˆx®¢èôFË`Ôò®vÖöBÐh²ŒF‘8`x–ˆÄ@xöõ(<¯Íց–ášúÎÙ_§}µNãRÛAÆÉ˳8Î˜M©‘sûÆR @X –ŒÞ2–Ç Fjɉ¬Ýl@«ËÖë(GDz€àÑÓÖJöüyhá˜S§'-Ü4ªµ£ôý[TƒÁ ‹gΜéêêªR©Fez#ã¡OÒÿ³·€dÄöN>i+~àöMêÖóÌÎ=?k­CÛ4ŽxzlݵÌ=Z…”—œ³”cdnŸª»‹gíýjh¹û‡V,ù銬ÒŒÁ`ÐçŠoä w­e|öËþ+]êùxˆhäU*ú:I(耂^«à„¶N4
³æ†9OõZ=W³Ïðš}†¿õõšÛGWì<·õAögþÂ]v‰e€ ”êÕº<{”BŒzƒQoüg”š¬ÜjéŸýøûÕεB9ãõý«*WpS`tчB/7ЊGœÜ}9Y~÷Ô » Û:m;c2 €À‚OŒýò¥Üy÷Zk÷j°|cj øŽ+~€úÚÞÀ+(åyƒFŸ;,@’^jjßpÈšªÕœ†Œô²ÓÂÄsîåÓ»u떻p…B!þ:Æ3B¥ Œ¬|…Z- #'­ê°fÎÆÚ×"%Ÿ^Öäñµó/ZÕœ$æ;„S­Z#±­ØbÅÄ¡ßZ>穜Lе²wÔ”^§Q©”:#xE–Q£×ólà‚_ ýaá>œÅê+מ šú}c7¯ã5 £JÇi•Æ}f„][6µÞ•ýõeš”r : =ª‚¹+ ˆœZûÀòÑœþ°TYiìu'&ŸgÃwZ…*[ϪӲT<àµÙ*•Ê4J„æŒV_8wè†Ùïrª®\6tæª'Žè,«4o|ÿ«¡ƒ\úŽž4œrÅÊNÉß÷éÔœ›®ÏoøeG«zm›u$߆OèÛ.i͚¡Í ªL…FOy#8„|?û‹akúuœTÓRŸrã>L_\S©z}¶2 Š šlƒRC„ »ŒvÑö Ä^w¬Ú÷¬çhñþû’BΜ9óÅ_h4Žãr‹é¿þúkàÀžn£ŒØyóæá\(bcc£££[µj…³¢Œ9{ölHHHÞ®CŠs•$6ÎÞŸŽG6­ÚráA¹€:n‚ô;×ß jŠ “µˆÜÕ- N}?G)ÃÉüZwjâWίN«Ní1»n@ËÑœjI,lÜ+Ö¬V©‚œ”eD֞•ë׫âh#q®]¯ž @liãÒmâä±M¬ „³v/P;Ø×ND),íªµ®ëWN ÄÚÉ­\`í ªŸå$Œ¹Ý ZÞ"ÜÉ«jïi{9KìŒë5òwr¯Pœfo[!áD¶njÕ«SÅ×AdiçY©f@Åò¶–‘ØzU®Y¿^%;+±kpýº^b$r[÷†=&MÓPN(a„.ƒœ]$ö6ÎÕêÖ¯ì]¡‚—›Pl_»]çžý:{Ù;xWö­\3د’›œ•Žb W[+G¯Ê5ëú»YsŒÐ»i£:ŽDö®~­?›]¥J£ÑhiiY©R%'''{{{{{{GGG›Ö­[·jÕêCÿÅÆ6ŒúnÙpúôéÇ/Y²gE³`Á‚iÓŠœuCÉ×ékŒœu|ÏáóZ±Pkܬu‹qUwndS ÅË¡ŸÿÕ¡WᵝówÜH[1¯³«™¡¡€J<Ï Í”R@Í4Þ¿qÍw|Z¯çùšBŒÒÿQ̂>ßÜø¿9ùƒØÜÄdee͝;·G:N*•V­ZU*•ŸÂÑ6n#T w«sNÖbœjŽžR¹þ³ž™£Hféàè |כ^ÿ„€N!ŸLìíq:EƒñßôíÝÖ5o茑9wÙ(0Mÿ³ J̎HÞ}…œoÌ}ê­¯63æFÉÌsofknœŸ•¢oNòƒ’ïóÿyðöWòþl5*•ª xÆlFÏ•‘„BˆÐÒ³BÅ÷•poi„ɛΜ˜š©ÒER+kywõVpPý¿œœ¯ð¯Ã© ì/ N 5’€ðaYàW!„ñŒÐ<¡ÿU –s™¡ÈÒÑÕ2o¬cÆ Trà-1*Ñ(¥ox.¢\Çl."‰gÂꡲ†çùððpSvjµÚÜ+6£RŽ îý Œg„ʔɓ'›N¯ ”ÆÅÅ=þÜìå?QIFÁý*„ñŒPÙA)•Éd¹¥R©X,Æx.¥‹gÂxFšìT]y·ï¹e4ÎLh„ñŒ*)lll°t.Ý\Ž+è€g„0ž*­•Ž­­­­­-Ί2PFcO1ô^ž'ŽBÅœ§…3a<#„BÏ!„ÂxF!„0žB!„ñŒBa<#xýœóÅ>&ŸvÂËÆ ?Û2Ï{Ff~äŠ?nߟ}õêUŒF1àyŸaÆþþþŠ»8òorÇá̙3ÑÑÑE:>b±žoߟŸv !û÷ïOKK+¥ GiРAŊñ§„ñŒÊ~6Ÿ;wî‡~HNN–ËåžW^€†IKK;þüšQ£‚‚‚>yB›ŸRzðàÁM›6éõz‰DRDë!$999!!aÔšQ2™ìNx—.]:tèðÑïÝY „Bá_ý5nÜž¯Ÿú MÏšŒgó_ýµråʎ;Ž9gKñX²dÉ×_=uêÔF}„ÎýÞ͛7oߟ}̘1;v,ÒoLLLüüóÏ.\(•J?Մ‹D¢?þø£”®<3fÌàyDemÇg2›Í;w6e3–ÎÅ0ç`òäÉ͚5[ŽhѹsçLeeñÏùÜuàçŸÞµkWn6ݘPJ]\\Ö¯_Ÿ0yòdµZýI&Ü4à E)]…Ôj5˲ùW*„ñŒÊN6ÿý÷ß+V¬ >|8ä¹KRácý‹`0Íÿ &ŽlÙrÁ‚.\(þ„ΛÍ{öì9rdn6]9kúd77·+VdddŒ;V£Ñ|ª„.ô|¢%m'„dgg †ŒŒ •JÅó<^7Ž ÀÆm”óóæyþäɓááá}úô:thîv™²iÓŠ?ÿüóݛi//¯%K–”økýSJÿ¹âqaÇö7ýË! ™ÐãÆcæË/¿\žpapppqöË3­[¶lÙ¹sçšQ£:uêÅróÓWž»»‡‡‡Ïš5køðáëׯ‹Å%ø·jM–:›·Y ElI'–eSRR¢¢¢ …­­m¹rå„B!nÖ0žQýÝwߍ;6ÿvyçΝ...M›6Õëõfß«V«Ç7iÒ$ggç·o @W÷/FĪ+…øÚ‹ œA6f&EÚöWš\&&¬X(dxJgÔféš=£wùùûRbŒŸg±oùò*T©×tîåd5š“ì[üÍ¥3Û[4üŒïçâ ÙÏnŸ9{þyº¡w/kY¿†—§g«©c Š±Õž ûéG7vNõöö¯ßlü¥$­@$w÷.ïåîâíéjmkméäé`çâãëýòøŠ9Ë~ºûRmªWâO|7êÛý):õùe“–ýuãºÏýüük þ+Fo*gt¯.~ÕËÕÅ­Z÷¡ËbÕŠX2?ÿM)•‘‘Aiߟ}Ûõ àÊžþÝ:ìño;y݆ù®g„x-É2Àó«§õhØr“fâ—C|R֌ìq„7J£7rO3µ¶T[·þðه:€—ó§,Ia%b¡()rë·œ7?o7eƄºÜß:Ôœ®Müµµûíp™úˏӬ“ŽŒÿ}!Ž Œ4 Ož<¡”æ_4:î£w‰Dfׁ»wïÞºu+""âÁƒ·nÝʍR‘Ht÷î݈ˆˆ7n\ºtI©Tæ†GVVÖ£G"""¢¢¢®^œš7}oߟ}ýúõˆˆˆÈÈÈK—.”7ééé/_Ÿ4Û5Úh4~ôë‡äÿ"SA֓‹Ó‚‡ìóœŸyã$QÜÁ S~È`É?ÛÏÓC{ôþ‰†Î]·hŒÏ”^=U„k›fvkÒòšÅŒé­"ç׫P¥ÏŽ—Óçö±ŠùeÞôßõ±»Ö °MÝq銥]OmøvåÎ <€"öèªáM«O¿ÔrÈèŽ|Ñv[¢Ú”¯^ rÛœ'M¬æöþ_„Ü>"“'O6 žy,¥°q»Œ‰D'OžìÔ©Ó¿;ӃbªTŠnÿ¡R«^…•hóõʳQiÊ`ëyE’ïг¿Îr‘G*þÚ0iÿ3è ŒB@ÚÌøó§Av¯"R/GžŠœ¢Ÿ_Ïý™Õ¡É¢oÆÔq!í|ž¿±ïJhÝÁÍڄÖlúY3 ±€tšúP"˄݊]'ÏŒ€~µ‚7Ø+hÑ«]k{žcÐ Œ!#ÍíoΞš8eþ€±}Œ¬˜Æ.‡ZSöEöœ‥EÀÌÛ;ÆWë}žýÝgà ÐÅÃ\Žž‡t³uÜœûü…Þ¡×7ŒU}ŏÕ,€ÑŠ)R».ZÔÏËZÜ%Äé®_ÕE}iõçÆtuxXÿÖÕ é·Ï®>pâAÆžÖ䜛Z†a¬¬¬LyÌ󌿿ÿŽ;RSS7lØðÛo¿}”nº Ã<{ö¬M›6ù_Ê{Nm˖-¥RiþH‹‹‹sss‰DŠÂZ­V矎páÂU«V™Fža˜ÔÔÔܗT*UAN)5 –––[¶l4h\.7UÕ7nܰ²²:zôèòåËÓÓÓ?Jc˲¹³7Ï8ՏnþE¡_Ü»_ëjº€k§:yò¡a€„!¬t7E\šÔznhýfåÊWÝìBTR ŸrÚLUfó¹÷W(/Ö;=9ü?öî;°Š³øï9çdKB¬ öVÄ­ªj5jF5v­Ú«5ªUj¥T«šñ©U3!D"‘{“»ÏyÞ?ND$7€HBü>ÿ$w{Ö}ŸçyÎsžsìÛZ‡b«“Ü3§ývSÚ?.ýu×ÉcuÇnm=ãoúåökÉИã41îÝ6®×³nùxõÙÿ£ß JëŽõa_ýŽ]ûTŽpE: S(ûöí›8qâœ{÷ìíí'Nœøõ×_c!‰ñŒJ‡Édª_¿þ¢E‹òž¥ûûHñÕW__aփ“ƒ†ÿ퀹ràýZE<XÒ¹];×÷t”0DÄÃHðTAlZ}ÔÞCL̬ˆe",ÙÄÍ£|•òå¯Jr¢7)•Fb±XÌ2ÆË{ç·Ž€Wöñ…ÔDˆ„ˆD9E`„ó…Œ9“ú7ªZÁٖ¹_u±T§7q@µÐŽÇ‡ÕÕŒQ˲„3fýÈšJxšGŸ/OF êqø«­nýŸhàç œ…6¬T£‚³ U;:)€déͬ£ÍJÛÌ}á F>šÅ(EÑ.ÌáyþöíÛyÆ€@ãîËo1ob×˧ôSŸjæb+æ\f£Èù&VÎ/g9ƒ6u)ÿËù;œtz K€E¿Ÿ7ß ×û÷ï µ=GGÇ7µ¥”J¥Õ}àŸþ9{ö¬pä'“Éš7o.Ô§)¥íÛ·?uê˲„GGÇ6mÚÍãíÚµ ‹ŽŽfY–eÙÚµk»žžù—˜˜xêÔ)£ÑXô6gww÷|+R©TšO_ã6博4‰{ÅÝ7Û:fë-D,‘)\åžv4feŠ%õ]ºkþ€öv¬…‚H®T0`‰…Ï™.ÏCO÷fBЬô'úÿüÓÕ:#ÇHår€… ¥$gÏ煟¥”§Î±Ïvž",‹°ÚÃÂÂüüüÔj5–ï"<÷\FŒ~_ñŽ”ªÉHÊ* q۔_kêÌ„’æÙ÷Rj~Vå~ö4Ç[xÆ»œW•›»Ž®=|—Ãѕãoß hXE öaoÎÜy%Akâ!;åÞ`–ÕÅ_Z7e¿HfÊ+%–ÄVþ•)¬+aªœÔµú9»o\µëàõ'<Ÿ¶mÆ  ]çÊnÄÊ,€õ#Ꮁ{³ÏÝœîýýŠùÇÍ«yÊ €ÂI|òóé¿^Œç,i–N8"®=üÃêîm:'ÅLè±:–“ŠiV\üÃD]‘†JÎ7d£ÐàQ›ÌZ{*•J›7oÞ±cǎ;¶jÕJ, ¥¿H$rttìÒ¥Kǎ;tè,Ì*˲b±žjÕªÂKíÚµsqqze³,+—ËCBB„©µhÑâÅû€Õóë%7Z‹HP­]›ÇwÂz¯ã¥"^ûèqlêÓ£HʙÁŠÑ(wŸ}ã¿Ûûw ‘J²žDG¥è¬Æ=K|À±Mņ¢?-šó§F$ã³î'&›”>÷f3€Xé —Ã¶>ŽPŽ'…õTÈ»Òr»¡|ýõטÍÏšLUÄßüDÝ}Þ­ñÕuãÝmË]ù e7?ÝÐæÃO'dpy²@$QSªAN·X!VĊm‘˜ZÏ]ºnŒÛŽžY"oœ@6yߊ^Í} Å°µvö»šøÚ-8X®nÿ‰MøOj•ómÔœÆÒ÷7¶¯µ„ hÖâÓ~{7ëÐ÷¢€lNá  öûoKê]ù¢žË:öÝÛbû¥ë»)ò§ˆX¢P>kh¢bÉA•Óo—RtšÚÝޕ îÕ¬¢ËÓҐR#kf]O‘ر÷‚sëÿ9ØH¶•Z~e{˘ ¶2¥œûÇãf>¡ÌK׿D"!¿Ázó æA8 Ìä‘Û ;·3v®Ü m°?’ºV?’o6T*ÕæÍ› .{ddd ŒŠE—šíÖ_ü¹fö(™ÊÁ£ÿ€¹I""쥀è“ÃG6„g΀–)<*Ö;[gä­Ì5fgefdY›>ß»ùçg/÷Á­Ÿ[zÉ>úõL"¥93±©­€Ùª ”RF£+ð~œ63[oÊ÷tî?™™™þþþ[¶l9yòä±cÇñÈý"³ÙüÛo¿ùûû_ºt騱c.\Ðh4%³ì2™ÌÊwåÙfzmŠÎ`.ž‹ 8C¶&3‹ËyÖÊòÖðS¶FcŽð/Øósþ3ekŽzîù·åš0aBߟ}ϝ;÷÷ßGFFZ,–XcšžaíåšQ£ÆÐ¡C›7o~çÎxþ~ žžž}ûöÆÊ°ÊÑÑÑÉÉ©Ðj7ə˜DАŠ €J•BÆ0ÄÊ5¯ÏÑñ|«+¥D™­Šä|–ä<ÍÊÔjûŽ2+W«E@)«P+e"J)% #S(ä’Œ7[xúa(”6¶J(0^Dþ o‘§W(G]›à7öÃ:՝€ •ós²³Ù¥jµZþtÐ òŽŽ(SÙ(dâ>>¡¡¡qqqPR÷äÈ]pœ^¿aÆÏ?ÿ|ÞŒyBg4žç_Т$j„¹»€Le#—Š„ÙÍ·PJ©Bm£|:&‹•9$PJ +VšÕ–œlžó'”€X¡VɘçßfÏó…õ˜Ã:ô»»†¡gç‡ f6› ôÃ?TªT)·tþñǧOŸžœœü‚s~”ÒŽ,–§d(,€ÿã‰Që)jík ùX^,âÚ3*gÍþÞ±r»Š 4>Žç„mæ…ël&š IDAT3›û 7¢®_¿Þ¯_¿N:µnݚeÙŒmÈ%°šTª¹sçNš4i„ ‹/öòò*;Oçfó–-[fΜ¹|ùr7Õ%û Îá v‘WۇŠú)òê?„ñŒÞyB),‹Ge6›GŒ±jÕªªU« ÏSJ}|||||Š^z¯Žl@åY¿¥çÓ9G5õCþcõñʕ+C‡mÑ¢E‡X–n Xb«Tø.…B±hÑ¢±cdž‡‡Ï™3ÇÇǧXçA˜²Á`زeˌ3V¬Xáîîn6›ßî{J"T°qåOèñãÇ·jÕjüøñÂ%°ÿ©_É{xpO¬Ž`þ·ž8›/]º4jÔšúõëwéÒ%o6‹D"•JU’û€\._Ÿ|¹D"™1cƃŠu³ ÙŒqãF¡Þœ7›…ë§KòΒ¯9î^i–ãyzØ!¬=£2›Ð"‘èË/¿€”Μ9sȐ!...Å:Ø'bY611qåʕ5kÖìÖ­[ÞlfYÖÏÏÏÅÅ¥„÷¹\þí·ßŽ=zþüùœzõR«ÕÅTúBΝ;·|ùòe˖ mÚ¹õf;;;???¹\^2íÇEDD䎾òhªTª‡⠞1žÑû’ÐS§N]»v­Ð֍æ% ƒîر£Ùl²™çy±X\Ÿ|y(Û;Êåò~øáË/¿:th‡y5jµúûᅲJ¥ù²9 @¥R•Ø‚·oßþ‹/ŸŸÝ`0ë"¿YÂ*2dˆµQÏл\cÉ[6œ8qâàÁƒ‹-zƒ?xáÿžžžäädŒ‘{q3 &“IXÏ¥˜ÍV÷áÆYÅT§€”feeå6”J6ç»ÍeZZZLLLÉ ~ò&ŽšôzœÑhäyÞÅÅ%  $O ¬=£ýµçÐNNN&99ÍK†0b¥¯¯o)fsŸ}ÀÅÅE£ÑdddëÑŒð]%ŸÍðü0d”ÒôôôÌÌÌwñxTèȉ?"ŒgTöCZ®¡|ùò„W»ÙzÂÛ¥Þh!ì*•* &&Æ`0ë× ;[ gsAR©T¥Rœ‹ñÌóŒL&{‡êýãœVé,—Ëýüü„Á€pwí‡eYµZ]’—T=¡‹ûŒ¬T*-±Ÿ`/àèèšT*ßÑÚ³D"yw» #ŒgôŸKç×¹zµrö퉇ܣ4¹\^æœR2Kúþì?ãc…+á=_ç%ÙoüÍBsâ-ûOŠj ^µ:†¶¬Tº‰¿Ù2OQ „Ðk¥3!Òn®^±è×+‰Œ!öÛe ‹!„๠„ñŒB¥–Îpu׏¿ÞqõùˆÑŠmÁþ¶æÇGf(ìÞÌùzWçëҁ=<Æ3Bœ‘tÎ<üOŒwÓÖ ÝÄr§îÝÚ3O"Î=2Zœ7sΞìÀgÆßºøod†ÞB>ûáë·ŠCIÝ( œýðÜ3Bœ:™·niuýÜXጯ{ewéö“~ÞVÞO@Ö¥Ã{V®ù%ÅHœ›ô™Ø¿ÁùÝ?‹ŽOKçju3²C°”¡V³aí!„PQ³Í”{–ŠbFIHl|Jao7Çßúçd„C“!᣺J¢öM9Âà±³§}RõҎˆGIY€ÙŒ0žBèµËQ)D"Ë©<Ç v…œÝ¢Ïæì+4 iÜap¿†µØ˜; òšâïYœi°D§3š,ØŽ·Bèu9T+nÞÏŽ4§ "uC}\s_Ïw‘‘ˆ,§üm®";÷‘Yæpþç?JuöW÷Å:ÖTª$XuFX{F¡×BÜB;•²{íÿb22~™³&“ùšm%ÏeîŸ?bø²ã„]jôO3ÆLß| dÞµÛuj”ôû˜Š­'gù}øóß¿|RÏõÐÊÙËþ&CwôqVáZEX{F¡×B(B*òõç±£Wé±‚ç³3ª/Ú3ڝ%Œ™KŒöo޲pF]Üå+±Ðd•Z XR¿§…™J-³œg¬h—–EdJµRÄ¥€‹à®…=øË„7{CI„К@S (Ï¥%$dXÀÑÍÕF"f¥x‹™V"f)å9‹…‘XÄ@ŸnÙ€äi§”â°_kÏ!ôºµáö% ëàîá9Ñ*€-+–°9çž‘XO¯{†§aL)}úèi6c2#Œg„z3MòüÉyªÀËÏ¿5ïÃg¯c6£§°kB!„ñŒB!Œg„Bã!„BÏ!„Æ3B!„0žB!Œg„Ba<£·õú®¬Ÿ’Ÿ“R\ö·j·Äß*n8j²Rî#9sæÈ‘# ƒÇpÏÖL•*UzöìIrFq$oɖº~ýúîÝ»Y–-Öï5j”££c).;!äÏ?ÿŒxñbéF#!€mÛ¶õêÕÃ_ÂxF¥Pâ]* ·M{ƌ¡¡¡Ã‡‡bŸ¡°Œ‰dÚŽi7îß¿ÿÇKåÐäµWý™ZÈ;!:Îl6§ŠŠjµZŽãð.Sš8`ã6Ê)q8Žûã?/^ºi÷ùˆò…,™ÅbÑétÙÙÙ...2™¬6:ÂxFï¯ÌÌÌÄÄÄŠM›,Y(¥7nݺuaŸ5 À¥¥œv<BÀbÊŸwíb¶]Zv K|':NíYÕ¿œ²ù®OJ|ðP¬RX ±ç·^ŒoÚý“Êæ £­Qm|C ±¹‰dccsùòåÐÐP†aƌsðàÁ‚%²‹‹Ë™3gÞà–2·oߺG•pË.“ÉúöíûÉ'Ÿ€§§ÛÛÛ§€€4mÚÔl6çÛgxžŸ1cFÿþýߪý\÷ Y`"pïço–ØŽk\?ÈVþ\ šº/r旭 [[Û¹sçžZoV¶/|F恞Ã~ßxáD@ö©³+luߎwŽð*†ä›<›„ÈÈ̹:`Àš9¹öæ©ÝæÌê©Ë4Š€*¥•yç6ßlæ&ŽX,NII‰õöö>}úô€I“6l˜w]1 S³fÍ7Ÿ¥„U¯I6ßBå>“¯þšû|ÁäŸ³`•7÷ÍyëëÑÑÑŸŸŸÇÅÄÄDFFj4šÜ÷+•ÊÙ³gGFFÿnûl9ò7·Xi™¢bm•")h¹òȬ­‹­(g'zº€vJ992Eøœ\ºtiøðá:t0r¹Üh4 U«VÅòœîÏW²R}ÓšP+>¿e@ã* ©¬Ãœe þæB\&GŽM£ŒœÊyv<cNwjÛä°Qg;¶ìÖžõ濯ì=ºú§³Ç×UèûÉøˆGCàâÏ*€Ò ».8 „ž\:ìë_ÏúŠ‹Ël\]]\œm”"Våš’Ùºžº˜Ÿ3nØÆsIÂÙôÔ+»Âg,ù;*õæ¶ù 6îýëǰ:•=ml,ûë>ä”Ó k¹ØÛ»”ìy2^èÿe}-QJRRR C•*U‚‚‚‚óšQ£Fñm£|G «W¯vvvöóóspp8räHn×-†a6lXŸ|y???ŸÜç !>tttôóósww1b„p1·ð‘™3gºººúùùÙÛÛ_¹r%oG°Üï5™LÑÑÑ jµÚßß?ï‚W¬XÑÛÛ»DúŽB4[ǵŸŒ/ZØžf}êï‹NÞy“ž¬›ÒO®PØÚTþpȺ»ZsîñœàÖŸ5?<—aà”-ãÜ\]m<{WÄš‹øõ+V¬Zµj­Zµ._Ÿ\±bÅààà*Uª`1‚0žÑ³ÄköO‘ÉdÅÔõšRBN9¬O¿ Õ?Þø¿ã£Ö®úi߇f²×ú ‰ŒëøáECmC}tݬðjÖäG7oFÝ*Auìܻ̚9|ô€@/úÏā¡ S;,=ò×O]W1|ǹ$ãöïËû6m­Î²oÝX¡"Hyžš³DJ•­æî©Í«vgdîX¿éâdW/GCÒ?[Çtk·#£ß×ßNï SºUÛz- u©[õ±úñOüª+íÕ¬×] „Œ(iâããõz}Éô]—ËåV¿(###%%%&&&==ýÒ¥KysôáÇ<ˆ‰‰‰œ~ýzîó‰$---&&&!!!22R§Ó埀Ñh’’’bbb222NŸ>m4­·™LȘ« 'ÇœñNs,ËZ‹|ÍòþËå2îŸèûÍŸ Uü ™éReÅ þoï]t§¿]>ÿ<_ŸNŸòûÈX­Ì[*Õž¯Ñòí¿ÿ²ªîžaËX‰Žˆ³ÄqœðÏŽiÓt:–EèMÁÆí2B*•=zô§‡_J«ÕV®\¹xj7úë.Ÿ =tâ˜^þjšhéÞàïJžž¿Ÿzôxä܎ÕÝÊtýÈsæ'gZ5nÞXr§vÛŠÍË€¢f•: ÿ hܹi}ÐÝXsã‚[ÝnªÖ²•Õøê»+wùšR³Ò;/ž³vTy¥$OR<+ŠUžUª5k²jóSñ#:›Nü}ÚT1Žu5œMJÔfìÁ¹SÚWp"=/ÛÕ\(º‹ô~ø“” œ»TsssìÒÞyÅĈP¡üK:@QJêׯñâEáPÉl6 9Ú¯_¿„„¡Ê0ŒX,.,íŠÂd2YÝRy'8eʔ3fäV² CîKÁÁÁ¹©™7êN:egg'ä!Äl~vîÕb±Œ ÌóŒH$Š÷ôô‹Å‚‡‡‡»»»ÿøã?~ôè‘0Y©T*¬“W[v†anÞŒiooŸ¿mHƒãŒÓ?ÞzqNX°ôÒok8~|· ©Œöÿj!vý’«øî£Ô(3Ï͹EÍS–AÂþq1¿Ü7«Û>"Z;ðo­WûEœ+…B±ÿþ#FÄÇÇ;;;?~ɒ%X"!Œgô¬ÈnÞŒù’%KŒFã+|\,Ÿ>}ºGžâ©žóõõôuš ”Œˆ ,Ãr2يë®Ê_¶–£”P†çDÀ09y@ʋhNè2ŒØÆîìÆÙµ7Î!„Rj.W³ ×€Q}¥LÄë燐êµ[ýׁUçlÿN‘¹|ܵ9ŸN9o;B@!!ŒÉ‹YÖDÈüª~@(íš9JŠŽ”éééy7C›7oždYöÖ­[ .Ì}æ"êÑ£G 4xA5ÂÃÃ[µj%|…J¥jߟœV«^:tèðNBH\\ÜàÁƒ…çëÕ«·|ùòÌÌLá#óæÍûã? ŠžU‹ÅÃÃ#oÝQ.—‡‡‡‡„„äî“R©ôÓO?8qb•*UòÎê:mÑ¢…0‡yK@äÕnM{óØ¥'Æm¬°sƙþ{¶0dÞ_=sü„G€W†ˆyÆÚ¡#ޘM«Öós1 b‰ŠÜ,¯×ë»víÚ¥K''§S§NUšP‹#„ñŒòÜBöŠ»‚HTŒg 9ž¥1ñ)‰Yz°•Cܹ ú,BˆˆÓkLzÃÂ3I8 Å%Ðì'ÔÂCú³ð¢z d Ý­Lú¬Ô'Ÿ\µvÆ(/9Ïó@#2cæ€ Á\ ›)÷ª!M»ï_ðs§cº¡£›WºŠ#“œÎfb°‘‚Y§¡”~{%kd 9ÏÃ:Ï0Œ\.·-¹GB¯¹¥Äb±Õ-5uêÔ>}úÄÄİ,k±XªW¯îàà ŒS£Ñœ:uJè³Æ0LHHHîéçž={FDDˆÅbžçmmm4h ŒtðàÁ[·nÅÇÇ S+Ê×<ߒ éD"Ñ+7z[ …R DÕu܌ÏÛ̘ê]}·²í¿ÜÁ’qü—ßü÷OŠ®~vĀϊÞ2˜ ®Ù̐È{é&á;Œ™ÉPäMž;?_~ù¥››[I^0žÑûå_«CˆMÕO+ÖølќICé‡›o¥ë1ÔÂúwùÚV5©ñøJ—æ4ñ•'>Œæ}êVH%¢Ìó3¶Çöã%É䆹Ûë'7éálSkH`ð§ Ÿ_îTeÂà`cü Û Á^/™]”QúŽ j²wéÓ• îÐÖ.òëa«·úTŸ8žÎŸÆl×zoîTC])pºø‹ÑÁã*ޘYǕIˆ}@|ëT¶œt- –·YžX/ù-xý›¿¿¿¿¿Á7PJ…Kæ >¯V«ÛŽicõ¥Ê•+çmEA—ï§gÎ{ ñjUäWÊl .ô³,¹ÛfáÙ Ôb6jS(Çe''žÚ·÷÷ƒ'ý>땝Saλoå)øÖìšTŒ_°¶þŒÞü•ÍM?þZ©.êhóÂbšÍæñãÇSJÍf³ÐÐëÖžp ¢TP^k‚”Ru\ûãî_&ÁÅíç_lÝ0ÛI%1Q³l'%Ý^Ñÿ·îõýœËÕiÞ!R+’Øz¶9;!zbóºÍ=— vÍûuüskÏîiIÈê-ÛWü¹€•‡ƒ“_PƒÝî™D2¥LÌä[ Vê¬(Çæ=HšÒ€v{¯z5*t«çù4Q‰ªrï”^ÞJÛæ#wÏ8ðK׊6®³4·æõø©M5/Gg÷fB£ Ö³9wEQJÝÝÝ[¶lɲ¬<©Tjkk[Á\pKŒÌÜg ^)÷_?’ûLÁlfY6)))߂³,»páB—Úi)Q¥!«º©Õª)j‘94lÝ7D~µU@¹ üÓ}Lß×/œ³äŽÅÎV!•°„+UÈ$"B-U~8¹ÁùĂfA[HÛœ¡HÄ¥p,W®\¯^œ„e—J¥2™LXöWnAkÏ(?©T*‘H’’’\\\ ŽE•™™©Õj ;]š••õ’À0€A•Ï~ê1VBàÄ« 2‰˜åêÓ/fÄ"”>­*2,#4RçŒ+7›éó—ÿB ‚sð)ûÞŒæÓŒÏȚ@ €èÝÝdKJ¶r²™>Ÿ‰8g®HŸlމ‰4hPvvvǎ…nØF£±°Ã—7[L»žž,_ŸŒe˖Â`d%vk aÙyž?pà@‹-/^,4æSJ_pAQiD”pýsÎZ!9œ0b–±rõvÎÿ”R ‰äY›yùŒ›L&œ^ÿÖ,8ÂÚ3*s„û 8Ðl6=zùòåuêÔJ8Jéʕ+ÃÃÃSRR^<.Xa#r Õ‹mésñꭇÚÀ9WwjXÑîYÚådVÓµ`™—÷¹"—‚Ô"ißuDãî.•\ %@ pÑü_v6¢Mîés¹Ù|ÿþýððpa]Éåò¢t›zƒ[J$uîÜÙl61bÕªU͚5+:tn6ïÝ»wÔšQ .¬P¡BI.ø+VšŸþÿòý…äÛ ÂxFoGI&\’;tèP³Ù~üøÉ“'¯>Ÿ˜êÐy—]­VWšPÁÎή$<߅ééé%66™Õš4ž÷AÏšÔªÑR©Ô×חa­V‹#-ä–Ë„OOÏRÌæ|[J,{{{B222е·H$òññ)ál.H"‘ØØØ”âQ#ÏóJ¥²XÇmEÏœ$¡}||ŒFc Ÿç{›1 #“Éކl.˜ÐÎÎÎź¥D"‘B¡(õ·±±ñ÷÷/Ý}R$áÛã•f¹/‘H„ÁQÁjô[µ¥D"‘Z­.™¯+Ý5ÿöì“Øª„0žQ©•ûžމ5óþl©,iNXRîÖÿvoüý¢ÒÅ¿U—ž Q @@—ú(:úÖÙ³i>ïí-ÃՎJž5A•%”ãýÿmš·ö'“vuÖÒïÜË"„Xo'>múŒ¹Ëwì>œŠL!Œg„zãé zíãC[~Óúõ™?yôðœˆ#ü~Ä@Ha'ª•z ;°9ˆŒX&"Œg„*Žtæt"ÑfZډ§òUêy<|p3Fyç3àÔºeƒ&Áå/”BÏ!ôŠàÌqWÅò*žb•£³'Ÿ–“h,ä3”R†pðÒ„ñŒBÅT…æLži‰ˆ!ːž™UXŠc×.„ñŒBÅ^…fY9e@*ˍk°µ‘9:špÕ Œg„*%¬ØÆ§J9­áâ=-§MÍžo¶Uz8JŸÕ¯óôáŠ4瑘!@ÄށÆ3Bœ ÀÚ:VéZ×|vÝꇀ\>ñûÖ{~mƒTððäæ±cfüv1žrmÇÜOÇ®ºöXC!Ĕ–¬‰~”@$Å&>IL1‘Â{y#T"pX„PÙA(B$6®mÇÍŸ?y|ï2œ]œVƒÆÑôiÉwëµfÐ=yœt×`6rôAøàqQš,žÂœÏz‹ÄŸ+þØXëDÏ!ô†ò™ã†ÙžÕ ûáï!É)œBéd«b(¥•>³õCJiƒ1ß“ó?Šk÷ÌWǑ:Æ3BœÑˆ&@)eD¬c9W«Q›÷Q!!ŒÙŒJž{F•шƚEÏ!„ÂxF!„0žB!„ñŒBa<#„Bã!„BÏ!„Æ3›0 IDATBåÇó<®„0žBoWWW‰D¯z;š÷-ÝñŠYï9Ô!TBX–"öÕFñbfûöí'Ož,Û¹E)•ËåsçÎU©ðÕÏ!TüŒFcjjj@@À+²¹~ýz‡ X,–²º–ärùرc¿úê+ŒgŒg„* å˗üø±Ñh”Éd¯<‘Áƒ·oߟl¯šY³fá0áÏ=#„JH͚5oݺe0à5N¬êõú2¿¢xžg˜g…3ž„ÆxF¡bÔšQ£˜˜˜ÄÄDÀ›Hœ!$)))999)));;ׯ3BJ©X,nÖ¬ÙþýûM&SY¬Ÿ±b&&&&::::::-- wŒg„*^¡¡¡>Ü¿?¥”ò'4Í;oE›OB÷Ϗs¿;ÅñôuŠI1™LF£Ñh4*•ÊÂކבc<#„ÐëÂX*•†‡‡oذáäɓðV7qBˆÙ œ~ú¯¢Ò‹<ŸlÔº™+Ï<¶žÎ@!ºŽø §NFÆj_žœ~×÷zMœ}øìÛ¿NÐzâɏfþžzxöüÞ?ÜHÔ<žÑ€oúøM·î^ùsÛ¶5‘4°nǎ lñõ¬o~ú®‘¯T¯M8·~Á J.™8 iRtRèš¹Wî=Ø;_÷íg›®Þא€«¿‰Õòhʝßföú Ï‰J¿ZÛZºkt·}ÔÖ«^åÆMíß\ÚñšVŸàíál«©·Ïšé,b1È@”ãyoW—êŸ^Â2ĝÛÑç³°3×E+&€òU¥ªýLŽìÕX`j1P‹,Äb&<±rÒܪ… †……ŠŠŠÀ¡C‡p/*ó°q!TÊ9]t…U7 —Íd¥ê„÷ð<žòÆd£ñv¬pÙ°1ÀOg„P“ž»*‰P ¶Uzüi2§\ß×äï9õ–^°Pššõ읔㚅È8?bü$¯îÓ44æúÓ=•6«Ýµ Šu}b0ÓL= ŽËµ­P(r·q Œg„zÛQyP·Ù6ꙭ?ùéÄÕ{7¯9xô‰Ø®ZP›ZqÃíŒIŠ?¶cå‘ñ «tõ°p<…<×ó`†åî\·ýÜ­F…cHí•*`%2¹D÷ÏôŸnedZˆðe£NÊòúÔÄ{Q—–Žßšœ“a~þ‚>÷5ÀQ°Èì•|܃SËvÇdëL<S}±ÌÌÌÔÔTƒÁ0pàÀ””F“™™‰ ñŒBowœR ._=ùwv· £;6©Q/d̔#€[îëÌõþµOEO¿¶_]ª5cëÜ©M@€vt²³‘°$j7wÏòj9 ¬èÖŒ mëU«XœãžŽá'G7¹­wÛÑóÒâgôèØó Tªì”àÚdl¿Ž æWjÚ÷ã!Ô3ºÎü÷‰Fæìé¬Ú¹‰ÊÉÝI)ˆÔÎåÝÝÜD¶Í[ëwöаA#ŠÜÌ~ùÒ¹ººzzzúúúúúúzxx”/_ÞÃÃcÀ€+VÄMÿìØèÝwâĉƒ GÐÛìöíÛóçÏߎi®ŠWвeËQ£FuëÖ­@ úé)\úŽ:š÷‚b>·&òÜÕÐyßRÄ §ŸœTäæç®l.p™³Õ랝œœ„[gRJƒ‚‚­N9ߝ3֞Bèm«h<­i<—ÍOkLÞL%y>”÷ÿgÍÒÂ?$ß £yþ'ù^{áPÏ¥oiŸŽc˜V«-ŽøÆlÆxF¡·> I֞+žœ³°0Ï÷øïzñŒâ d„ñŒBa<#„P±ÉdïWKz_á°$¡wɎ;=zd6›†)“1ŠT*SRRpC#Œg„Ð;£_¿~G=yò$Ã0YYYŠìÝó˜RÚ®]»÷¡‘a<#„Êžç8pà@áavvöÝ»w9Ž+{KJÉÊÊ*{Gã!T廎(##C£ÑX,–2P‚›ã!„Þ2™ÌÞÞŸL֞óR(ž­1žBèacc#—ËËüž‡b±·5Æ3Bœ(¥b±ø=‰.«"Œg„z댩ž’/ûëöŠe™[׫öÛ‡˜Íï'–!ôþV !|ì‰isßSTm×È{×ú¹÷Ü&„à­‚֞BšÔÒüïçç¹ë†÷®ä,r¡áá?­ŸÿáJ?µz'æ|·±ÊWÏÆVh„µg„zé täzJµVË;«X±¢~ó–Œ6òüó ³ÙøøfÄѓ瓳L„0ŠÞ8sæbTžBX{F¡ÿŒ@ò{z}'á¢j¶\€á.G%ôð¶ò~B€O;Žuýòõ À(ö›=Žöukîj²“bÓj|ý».“L"™„äT¶q„ñŒB¯ÐT2n]ÓÁ GœìÕ(¥D,wýlãáÏ(¥¶Ÿµ§ìü-7{áis7¥Tx$–IàécŒf„ñŒBo"  PJ¥66Î9õáç"6ÿŸ>#<|ö:F3z£ðÜ3B#:Oãê@Ï!„ÂxF!„0žB!„ñŒBa<#„Bã!„ÂxF!„Æ3B!„0žz×PJqqzࠞœK!zœþÀ‹åÝD’R*‘H>úè#‘‹ „0ž*L&SdddïÞœM&Ó;ºb±xÛ¶m]ºtÁ­‰Æ3Be‡J¥ª\¹ò;œr¹·#B/€çžB¥Tú0ÏÊ< ֞*ӄ›“"=[ŠL&SBB‚X,T*n:„0ž*ãÑüøüok¶ÿz#ÆP®V»±cVŽ!„PJéۓЃáþýû,ËBŒœœ1žÊ·*;á „H^öiŸþëLUºŒ›4º.÷K/ŶˏxJ!oO2¥Ôl6[,³Ù¬T*_tÀ֞Bïp8B@»bð€ O|Û=§}UЬџÁŸ¡MšÎŠ]YÍAFx[*ЄBÏóÞÞÞf³9ß«f³yذakÖ¬ÁM‹°öŒz—à î×i›uò!_ÏíPÕ!êìÛ·oýãäÍ ÛWTÝŸæH”™Ë—Íްº©Õç_Z‘¥ÖŠW”ê¯^¯7 iiiiii™™™iii:îÇ|øð!nY„ñŒz‡@ïÍÛÅÔ¯ñ٘úÌÌVu&¬9ž»©O›ï¯Ý7X3éǃw Ÿ`õUóèÊڑœìØ?wHBD>œv5ÙBIºò{»z!„Ž\~8ÝÀBþšÔuâOü¹¢·ˆeDâ¶GâÒÎý<†bïæóéDŽB,N.ï\™¢ ùø›š Z”u¡­T*Fãºuë”J%˲R©7+ÂxF•dM—ÿª(-€Ö›ëÙ€J‹Ž­£Ö~Üêãù«1ÊÖ¶ÇYØò5ȶ» O­ÌŒîÞé]“ûþËéó£»Â€ç¶-Ÿ’ ýÖE=I9ºJ¹uÜÆ 73À˜ñÏêA;œ­vüŸ¿FW>ÜÆË¹Õhӑ Ç6Œ6p]:@졍ý[-6OˆHˆÞç¿÷«ékR…C‡¢IJJZ°`î!ž{Fš€r"Qddd˖-_ý˜šaêÖ­[ðy]ówïÚ4KÒþ©ªæàhª§@ĊjÁ kíhœò\–mœiÛþ7µ1ñ{­SÑÙ×2¡QÕvÝÍF3ˆ5™LtùaV€£)Õ`è¿.mÃgö ±ùáŠ/ªÞ˜ëJõåÍ\1âŸLÿÞ9sÙ×um7‘X^ÕÏ>"éNœÕEZ®1cƬ\¹<<<Ö­[§P(poAÏ¡b±X‚‚‚6nÜøÊS0 «V­²Û2'W£‹B”!â³-Œ…ƒè'Ž•9p·.EÕôS±LÁz,µP;‰ºQê`¶Ìfž%*@̙-ŸŽšzúŠ€j•ä'–ò2ÀÂsÍ«W’óÂñäƒ ÎÀS#Ç 02…J{ï߁-+àLF‡^{ً‹º\+V¬˜4iR³fÍîݻ۶mÜa<#„JÎk^,d4­>/ó Ðãc¢ÍœCª|÷Ûß+EÝù—ñº÷ßÇ÷®µpé_7ä"Öúyž3ä ßM+&ƛaáSÛOÔ]-úß7þÚÅ Þ`úôœÉyZË Pà-YZÏÊÍ6Ÿ<ùó³…-úåÖjµzúô鹍ž« ÷þ*‘65ZhÎßÛµÊÜçÛ-£»ºªëžt_ÿx¶ùꝊ¯}Ö œˆ«]«yŽËYž§ŒÎA)ʊ‹>}öè¢ð)ڻѷât<Ïq¹ÝËxÊš;ÎÂS4š÷QÓ[Qc> ÿëüåˆcüsé‰áåÙÌq\lllTTԓ'Oš7oõàÁƒGáfEX{FœÛ¥@$Owªÿ’ðIë&M ý¢¹ ˜4ÉlõðÅMs+²£’•ªÜªémDÀÊlœƒEöJeЈœ¿úfCö[G͛<Ú鏟'¬íÔ©š­ njar§5ê:Fn[.š*Cœ}ôímÓŽq#úvÜH-úN£Š}\û¥3ïïïßšQ£Uz~àÀžeÑûü£ÆAyʂ'Noæÿ—áŸ'MšÔ¶m[á~ÏÁÁÁ666V¿ˆçylåFX{FœËÇڄPJ‰}Њm'oE;u#]/©Ù"ÈÓNÎú‰g˜çäI]J!Oþ Ï>ûdÞiBòÕх/kÜNOO/,ž1›Æ3BšŒ$4âV¹áǕŸ¬ûâ)=û×zž¿ü“ðvÝ$ !Œg„P)&t‘ŸEœœ°á!ôÖF „°öŒÐ»+==ýäɓ‹…RÊqÏóïÖü‹ÅâÌÌL܎a<#TvÈd²£ÑH1›Í æëBUµjUìö…Æ3Be¥T*•æÙÍóü;w’““ß¹šŽ-þÈba<#„ÞæTËûÐd2™L&£ÑøN×Dqô„0ž*S†±±±¡”ŸÓñŒ7§Bã¡2E,»»»»ººŸÓMÄÂØa!Œg„ÊáÄ­D")3˂Û¡\Øs¡wUYÊ3Ìf„0žB!Œg„Ba<#„BÏ!„ÂxF臣p „^ /¬BšD)ŠJ•*aº#Àþêã¡·‡Á`žwïÞëLA«ÕΙ3G¥RaN¿»©¬×ë›7oÞ®];\ã¡·‚D"±³³KNNvvv~åÚ³³³sXX®Ìw×¹sçq= ÀsÏ•(…BáêêzûömÀfê÷Çqºpµ Œg„J¿¿ÿùó硘N=R«å<ÅÒÿmÃó<X,ŽãpLS„ñŒP)“Éd•+W~øðá“'OÞx‰ Å<‹.#>öþݻѧùœ#ßõ\fc~?]%Q£å8.))éþýûwïލ7›ÍžæQ>xî¡’,ú)!ÄËË«f͚۷o3f !äÕœ(BðIwÎï;pèläÍÌtPºž×oѺWç6®J1!”RÈóU„àLúŽ€d°+笗ÑUþ¬•¢UýÜ{¡”réñ *ww;iñÍVFFF||ŒÑhtuuuwwÇ_ÂxFšÔa¬V«?øàƒÕ«Wïܹ³wïÞo(¡s&ñäòïãFÎ:mÿÁÂésÛVqºté°/:]¹ÿÇÒ°¶¶b†xo|n²ev[×2ºÊÁbÒgeÄrµR&*ì=zMŠŽW:ØÊޒ±ë‹îÝÙØ7 XçŒeY‰D}÷î]©Tš¯².‘HBBBÞé;y#Œg„Þ1~~~¡¡¡›6m²³³kݺ5˲ðz7UÌ©'ýoÒÔùIFD.¬6f?g/ž µŸà«­=_Ø$€íK[öGžÛÝ·°¥„ÈE³6XÝ­2–óðusVY›ýœ&ï"ÎØK·©Z­ž2eJttt`` Çq"‘H8-‰Nœ8a0€R)þ^0žB%T&„Ô­[—eٝ;wfddŽlÙÒÅÅ%o9þ_£šÀí]»éw‹Å_Lûû—-7›¹Ø»qõf-ê¿%lÅç¿ßìTÑI.Î_“9y… G]¥@²“¯>ù¿šç `™Xäæ]Ÿ|9Û€ÿ$*Ë{1qO\љZtm]ÁAN0FE=v%V$SWhÔæƒ@B@ŸþøÁ£F)|õ2õšÓ²~`úœãŸ‰LÐØ7nß®Š¿#CHÌ#„Ï™^øól$Ã(œ=kŽh[ÃAÌd%ÆÄ&gÛ8(£¯ž»ÃÕú YíÊ^R†<¹v6ÑŠ‚7<Øüª‰wmÙ-Äß^ú›gŽžž'QÚ6jÓŽ‚XŽ—lÿfþ_ô6Îmƒ*5hdo|tøÄ™ØÄTÏí×ðu2'_ýqηk;¹5Orò m௬7jzU š%í‰cn?‘;yÖnÖ²†»šdÄDÆeÎ*ó….¯—µçøÍK&Öõµg¬-œYŸ~l˺5ç’ʱY ñ’ÛS~š2À?ùÊÁ•ËŸ¿ïT—ÍŽ>{ÆfçÈo×OišŸ¶éË÷ܜlűq#þÙw~ÿîuíeT{~ά°MgMåÕj.M·óذ ú…dÝyr'Ŕíòû/ûØìÁÁ uÿÿyÓÎd#—qóʖCÓ·m¡Œ>sJ&¶œñ[zFíòmëûr»Çv<Ú÷ÄŸO*˜3š>{Ο‘b_9cÈØ±÷҄±Û6މ=±á›_Îiôéñ1§Nn9žxóOÜ™?æ~µð·{jmRºK‹O_϶ÖjµÂÿcƌYŒx±‹‹ þLÆ3B¥™ÐÕªUóòò:vìXTTTttŽT*eY¶\¹r&“ÉjH›L&NWðyK\_ŽžVsÿ{ñ`hØkä=ŒÍj‡k ð`ãåýà¬ÑêWœY§I̲ˆtÇ~]÷Ýï©CwŸÜÓõò†¹=‡ÿ–¡Ñ0ɧÏF56ÿ§¥žüкÙä-1«:UH?3*|¡â³ƒ‡×u$]Z<|À„13[v_gÃbïÝ¿W³Ïš£B«ZŸéÞcOJð÷;׎–¯W!tßÙNUœ0&#y63OdJËJ{Žëœž®2ý䀮ì\êËþ,“}çîõ[ÒÎëÌ­|AÛî'Î^ý€a`5`’þw:Ÿõèù[–µ~žºeËi›|ÛÞ+þ£§/±qøàw­™øˆyŸ}6qü×Íï¬iÔò£ úšßlÛØU$ãSýíj\ïgÓ®ù›î‡í8ž0Ô6+#M$)âþ ‹cbb8ðË/¿Bzôèѹsgü™`<#„J-¡ÀÖÖ¶k×®:.***...99™ã8³Ùl±X¬~°°çYiÚLN”q+šS:šTàá³7/UHt†:ö2«•VBÄ,«b€Ì»)Y6¶þ€§7 ­±í&XŒÀ€5yt [?µ¯ Të0p[kó“{ÿ0>G—t°%®Õ?ú¬ÏüóëïŠAm 'ó­=lԄР{0DF1|æã³ë'Ú-ÏŒŸ–^;Ë"b’·|1ùHJ†… „¯;tٗm|E™„Išhµ¹4MQˆÊ‹’‹)¡¡"5*€…€euù£ÄrQbÖë• Ò!–s2¬]<åÄ3º¶Ww_ѱ4Ðh!7ob;›/OXŽK ‹X cm*“4ê†R€ô êº|­šÒîK×7ü‹öîíëQ–š Õj]]]'L˜pÿþýU«Vaç6Ë3óµˆtÙ)Ö³ àäis(æ²K¯qsZo9|á¯kö­Ç/uœB Û­ê]KH–ŒD‡eŒ«Z˜e­:°|e›^5ãÿܺöÜ=ž/_€@¯Õ1ïÝьžU/æõìßÃ[Œ­9їþ}þœb IDATØFAóÊŠ@3,Ë04gÿÙûðD7#Dµ–ŒìQ_ ÏTÑzFÐjL`«BÏ׫ž œŸz÷êÔÚ¯® ^ŸLߑFOÓzú`²4 ŽF÷n%ËEIdåæ¡‹Ÿ³;"ôWÈzzyÿnÙÁM `³ŸÇF_uÜ!-ò詳}Ö®˜þãõ1‡µ:€/W?Ûy+m\‹Æ.ßÌÌÞ"nóÊc¯ƒ»Ûib.Ý>}ËÌy¢-q,0z=C3¡LFÄ3u»€ñí »r³óº+±e‘gn­÷{íÚµfffø¥À`yÆ`ŸXŽCü*[²yÛºé3g'$)Ýì)ȎžóBììáb.€â&„3Ž^™™«¥D-úŽœùZ·oï‚E·lªØ×v0‹ÑèÕ,€.7SÁÓpv5Á2 04Á l}ƒVLþemûººóŽÙ)tíU›æºÄkÕ9ÙYj='œæƒg-};m쬜–[Ù©Óz/ßП®ŽH?”m•Æõ€;ü}ºëLªWN<œõ·ÕŸƒÝXeŽB£g«È¢Õ4€.'3[•%Ä24CØ¡Åú%ãG-o]÷wR“•A4Z±~Š#€®r=gùú±MzÅô!m{4ªŽnËD¯?WÔ¯ìàÏ&tšï¶Œ^ßÑYçµlppڎ³}*³êlF¡Š(çz=MŸ=±~ƒ5ι™YBû>ó§ 2Кr9|@“©dt@„b¿îÄ"±@óDÞpVÏ:,8‚ H’7nÜæÍ›išæñxzœž[X…]ÜÿõŽ;ÞÉïûàÒ¥K§NZŸ|9Ί¬¬-[¶þb·V‰Í¹º/xÆÚyÃî}üE9ï¥ÖëÖÎY·kérÓc? +5ªnÉ­¯Õ%<‰È6rǬðs©çì Szx€=ŸC9{ºØŠx„úÍãK÷u ÛxÉ)tö£+gÃã•À3²¯Ñ°I-[€*=!&ö•È¥®‹ ‹TvÒýÛwžŒNgxBž—ow[3 í[°Œ&;òNèœè\S[»ª.ÖQ7žðÝ||ÜÙØø·&®^ö2ŠÎ~uû^ŠUÕ*.ÖҔG—âî^.Ö ©’".‡ÓÚyÉ]փ+gŒT!ÔÑ£aãš60Úø®ßz`^¥v£µè„û7ïJ÷±0ùÁÓI0˜oܚãÒÄ`yÆ`0 ƒåƒÁ`0,Ï ƒÁ`°}ºH$ú² mxú³gÏ.\š×ëíííiš.g‘’’²páÂQ£F5iÒä *ô‰'BBBúõë§V«q…’$###Ϝ9ƒåójóþýûƒƒƒ‡ Ò»woœ-˜Ò‰6mÚøñã׬Y#Ÿ”JžûôéÓÀÀ@Ÿyóæ•wLþ÷¿ÿ͛7oúôé͛7ÿR Ͳl¯^œ.\ˆ«¢›7oŽ=ú[Oö[b ·nÜŸ}û°aÃ8mÆN3L)uœ-Z”››;zôhFéTÅG†«œ/^Œøõ×_7nyòäʕ+'OžÜµkWƒf#„–/_~ðàA(u[`WWל{÷~ÝÛú³,û> Ÿ+ª!Ð)’S5"S¹TÈC,*ƪc2bn?xųtªR¥’”*%%F’eÁpùGDŸ@x}ºŒ*…ruu9sæ‚ ~ù嗍7 … ®À±±±={ö0`ÀèÑ£Ë[› ¥}èС$IlÜžÑÇÇ盚M‰Z‘™•+127’PE»ìy)U§'€€¥£ ÿ_g+BˆQœMH%¬MøEÞ.JjuvV–ÊHj&SŸö¥RùìÙ³ÌÌL‰Dâììü-~ Ë3&ÈÈÈÕ«W¯\¹²Aƒ…^ÎóçÏ·hÑ¢cǎZ­¶Ø{•Je×®]/^ìääôË-B’#®\~˜âÞÌÏËNTªác$0÷ñäQ}G.ض b֋¿|{ŒzcîY7-qðGÌïÒÔíÛ¡ºqI‘|r|Û-ª¶K/™Ìw‚¥õŠ«¿oNòÔ·žåÇ4¿GVn‹ÐÑ|„žÈ˜Ò§«t,¬VÒ~L€·ÉgS)77· ¬[·nöìÙK—.eŠt¡úŒ Ú«W¯3füðãͅÒ>pà@{{û€€€óçÏËåòÒ#ðÁœ©`RÿþkÖÚ•VÍò–¿ºuêÊ+¢~‹–næ‚%ŸïÒyî–Ë÷ëÈùõSzœºW'ýz,ßQCPüÉGÍØyÝkŪI²OKMÓ*•J©TJ$©TZ1•Ë3Š\ÈÎÎNMMmذaÑ*˲lœzõš5kVÒœjµš ˆÌÌ̊•g„$=ŸþBc×ÀӑÏ+S{÷ööß»÷<ìèÞÎË®Äö6þÞÅx²ZS/›öòr iŸ?‡êšÏ óììÆˆˆ×^Xd(:æ+æ¥ÏéÞ¡z‰!GïZºÚbZ«Fž2!ù*üR,Tñõ²AXòæ²É'»~„<h33“Œ Rïm:}¯nߟkS:†ÑÈ4ìg+ .7ìííkÖ¬¹uëV bãÆ‹-"¢PuwîܑË埱6„……q3u+žÁåÒN’d›6müýýãããkÖ¬‰ª]»vzzzÑ:Ó£GU«V}UHÓÐÑ€ àMèþ­ÿˆ%5›¹™¬äŒ:ü!©Ñ•`+Ҟ=yJÚxÕp”–å•aiuD¥+yNœŽLÑѱ”êÓU”óüI$’#GŽøùù‘$Y(&$I^¹rÅÞÞ[Ϙo®G_ôEà\ߥœÞ:Bš4ƒ Xj1¯\‰ŸÖb¯„¢†îÛiéóڕøPŒ£¬0•{OÚÑI/”p¿¡ð®FÌ»ðÆËŠÄf!/šïŽËDBŸ1xÅÆ€1ú4nìà Àè4sþŸÇÈKûHs›ÍWë‘23ü žt<¹–-‹€Ë¯†J­Š‹>˲Å@˜ûŸÑ‰‚äœØ’Ô~ö¬a„Žà™™îû€‹»hÁʃBS•››ëììùÃ?Lž@¡šžÏd/ùœ'"66¶I“&K–,Q(|>ŸŠišŠ===óW˯±Aƚ„)Š3\mÒ?=·©yí*R™"üOÁ ;eÆïŸ>,èôÍݳº Ò²eÏy4BˆÎy¹ý—žUDb’$&l<œ…PÆÍM£âž'ΙÚLl4aç=©þšßÖ¡k‡Š7±uúá™F{dÙŸ@(•:5ö[tÿ­ÞÜÿ{Wðް×J@("déªí‡®X×€V%¡šÎªSôâOÌœ˜”üëfóOŸ,~x!„èçggvô"Õd€œ‰ D<@uä7o+©‘Qлo¡G»Çz=¥ ÿ±‹û²‹ÉlVì± EG"2 ñöÉÍË9sxtϺˆpµôHŠàÑþ•ÿ;vSA£Ä³‹†ŸNH ü¥‰‰ÉoG¢«]7}û­$@r“nNéUŸÇãÛÕn³üÜ3nŠÀÓÃë×lÞséÔŠv Üøüš‹†)u„ÔÄÌÜÌÌÔX&#ɍeÆfff^º‘fŸˆá쌜WaA §üïLLҍkW­Ù·g¥¿¯3IUt1K˵ӹ§Ô°µÉäM<ÈDšµ“?¯ÒÓÓããã³³³käÃÑѱüFŠ õ®_¿.•JLLL/^Lײ1pà@+++¹\žœœl˜ÒŲ¬µµµƒƒƒœœ}£F · „Ž=ʅ&—˃ƒƒóÏ3<—ŠéØØØ7oހ»»{þ„W©RÅÕÕµ¢^bÝÉ9œƒ¯æjh„Bìµ5ý‡lžXÍÙ q"‘X.³­ÕdÆÍd¥AᾔŒŒrpûž?ŸŠªåÙåͫ؋„"ÿ ƒÿèh1×W¿ñû ™TjllYÙs̅„È}sôðâ5ï®çéß±ÿÙ:Ađñ-«Q¹MÙx![Ç՟ìój9XIŒ€}7Ÿy`Tj£x|:éΖáí« ÒåçE'³AuíðKÿHÈÒp5öñÞ1þÓOšX}šù±¶¶vrròððˆŽŽæóùööö‰äk·—°}pŸš‚@ (§©×\?þê„_:·`ìûËñóîýÑÍFLjwõš=§*–„œ9wbñŸ~Õ¶)^ùüâöÿ% MþØ6„gë‚i·àÜÊÅ{™ '/^?}ŽK£Ú$òM:¢Ê;LÙµ§GcGPjøÁÅýZ÷OëŒ}Ë4‰ú­Zk|öú¹CS‚~ øT¯_¿{ëY6çó ß;ÅßwüÅ“V.ðŸÕ-82UcQ»M†šÚ¯ÏÌ]¿·÷,axàٖeC~8(évkŸäÎ¥èèH’ÇìkX¯ßæAg®ï_\sxóÎWÓX»F='÷r%`HàÎMœÅ¹Ù©ožžžÊ­JžŽyz÷AKÒëláxzþæãg_ÀÛý™ Ð€¹w«Î,éÞËÆîÝ?x›ÑzmÔõgty~œm‡C/üBÃo­ìg»œs¯qsÃ@ŸõøÐ¬[÷±xÙ Œ¥ý·>x™ÍB^ëË0 Ë3IšÉ©ømSןPÝ=dÏ¡»•<]˜¬ç¯×wÅE‡a«¶Mšµj«5G/Ó ßã]{À}¿í¡×÷ÌqäÛéf& Ė¢iiiééé%ÍŒåóùð^šÕꜜœ„„„ÌÌÌGiµZƒŽŠ§§§€€$$$dggߟ}Û ±¡ää䄄„ׯ_ÇÄÄ$&&æ—^.Žììì°°0…BQ’ÁSl|hšþìÝ_Š¢Š{syn°3 ("SÅ@歎ÓöºVs:'3]ŒáĥГËê‘Æ÷¿MÏìØ.„?x•‹àLçŽ}—ˆG®9såT¯ëÓ7²Ày”I¯Ø•ÿŸøwpW‡­¿üð7H,jž7h"0k?{öøÙœ\áá²I}Ç߯5ÿâ­ã#O-›²ùä}8ÒÈwÀ¶Êsvž;w ã™€u¥«_*ÊŒqnÖÊt÷E{~k~ay煻.ÈÅg—­œ™¢:20`ƒ¥geAº*†üÙŸ}{DDÄ·Òªcçöw‚P(¹³­P(ªU«V.=yPÜßòðªéà‹fŽ©nAÒu‚$áå±ñ1ñSN†öoíÌCu‚v$Yøù©—1›#€­ÛНzsÿùé§ÞRCc&Gþ2±žZò³_gĹÞdŸÍÿžÖmÞÞÏLÂPk2uú;R6”#@õ™1!”Ÿb/NŒ˜ž M0†åùäsݺn[³vHÇT³æï»›‘ëY¥IË[÷M{/MgÇDœyçªc€äÉ,*Y Ž<Uth¶~\_ošspå…Ëu4 ™—çÄÅôœÒÂÛÒÑšsw÷±[nD¥ûÖ«ïW»òÒçuýš¶€ô ÉÐF,×X«SÍ«ü85hçpu8»kïÆøô—,82,-e õ|Ëú-šOk4nÝއ$ F“ Œ^@õøÎévÖ»ŽÍjêPiæóç#Ž<Ø AˆÉ}]©íÊÅëǵtÍpŠXr&.+ÇäTQà‰Œëw’žcåÁ𥁕b®žŸCÚõjc//f'y¶;c㬊 ¢/…Ÿ RK1;!~ÀðV5Íí…]zTïw#*«a]yé]F–eÍÌÌ×®]ËuišNII‹ÅÓŠM{ñⅡÝäóùÿÆÝúàŒ‡?þøãàÁƒuÌïvîÒ¥ EÓ&'';::ÜàùUó‘–ô,îJ†aH’4$Ü××wõêՉ‰‰+V¬8zôš@ ø÷/Añññ#FŒ(:HSµ÷h"°]ÈõØÚÝ=Ÿ]€Pöoa ,ÛsÆ‚@ÊTÂYššt' ړùêÃ2b–|Èœ5ïéÃÎsöüøC3s!쟙ûg,Ëu›Ÿ 67®²‰úmĵ×Ðݹ–wƒ&RžOûFõM@µúñMäY£»—W y“ÿ=}•“˜9-úÙ°ÕÛz·®+¡…ü£Ôþ«ˆz‘Äæ $)5s°–ó™\ujåz¿NÜÔÁ YâGûþ ¹üG¹ñþîuòqPYs1£ÇÂ.е„BaDDÄÀïß¿èСޜ{ïÚµëëŸ`åù;A£ÑŽhÑbŊùê€_œzuÔšQåæŠ耒™I$äú€OSŠ ‰¥3€VϰÀ°bŽhßX e†¡ –¯è0}Æôž_þà¹Ì¹ýò U£ÛU Ј&‚È›n -Ô3! V§z³wÉğæí32r1–K\ŒÂÐ]àä9SW«^}O'kÀÐj€Ñ‘€ ˆ €Éys{LÕ6gÞÝ"¯RÎだYcacêæÀM{ EËIñ€Æ»ÇuÙ=Ž»ÜõW ˆ  K†–œ‹­€ì|êV'F˲ y2ú>’$ ‚& ‚@Àäb€HùBOwn‚›ØX 7¥St €.[çQ«f-7{ÀÐÉ%ŠƒG‹i5'íuŠÓ2ÅÍ+Ém÷÷hhЊ‰©;7. |IÐ4C$%‘jœWGª˜ Ëä­ÉÈÈX³fͲeËòæ±,ŸÏW*•³gÏ633ã®Ñjµ;w ýŽÚËUà’Š,~ûûûO˜0!''d2Ùȑ#ïݻǝ ±ŽŽ48·Û¶mË·°°8qâ„B¡àÜK§NZºtiþ›j'· <¯?Äã9sÆÆÆfâĉŸËtþí·ß^œzUŽK FŸÁ=…=¶^ßÝtËϧúì|T €Š3ޝ™Ò}Ò6¡°ª@bɐïÜÚùoF€€Õ(™ÊöÖFR,€<ç‚òÂæ™­G®¡(77RÄcH–`ô$+ X.Ù#ù£][|Oléè‘ÊR2Õj9Z(„b! ,hÓÃÇ»7=ñîÑRg¯i;ÎMkf¡g'™ÜÓÂ"/çHŠÑirŒënjÚvÆÙ„!uöŽ ñ™}Ôˈ*‹3B£ÑxxxÜ»w¯]»výû÷8p | û4`yþ~àZb€²@’d9n§@«£ÕªiZŸ¯iS) xôò­†eE S&»ÙNˆe‘6KdRmÒÁ‹ã²ž-èì?iÁF/÷m\dAº˜|1GZ­yrníÏë/†ŠÑ-©ÿ?*øeq;+éhİyöÆ{݄·j®¥&ŒìZŸ.š-Ê4‚y–kžŠs@N­U#‚uNnæÛ ïÍïæ-2È1SÚ¬:Ä0HÏhU‹Ž•i*–-Іr݉Tþibž›èsm&BæyAO#š}gE•hÜ ‰©KûŸ]ú³ÿ€ õ4ž-63Ë;Å#äDdYÂH€XMŽ2;}Úñ'³ýª (»Dq•ªš+› C]5ž|?¹ö–ôèÖ­[§¥¥…‡‡S¥×ëmll FöÝ»w9-!lå€1bi`7žž.„`ߺtöBxŽÈÔCjlL`RYò|ùÞ둯² ‹„8µeMv lvâ«{'…Ÿ#(u”ü"#tÀ&.‚Gӂo'œUéKHŽØ²®SµÈË7WŒuçX[ÿq7ŸŸäXŽ™åàŽ¶çô=g&§&? »|?Y…òG«è­ô®³wÂØMøxÖΛ¯R•Úü$q«ÞÊ'þõØG“s3ïžØtr_„·[÷Êzš-Ý RIJ<£ju;öÒÑ·b³+ Q‰ó˜_;¹oõþøÌìÎÿý™ºCë:v5ºÎ²±[ÚyÊŸÐÇ)©ožÜ¹ž¢.:“¹èc8ƒX(Ïó‡ÌMÝ233kÕªU³fÍZµjåäädž€eY//¯æÍ›7mÚŽU«VÜjiCŸ£E‹͚5kÖ¬™Oþ[lllZµjÅÝbcc“ÿT1RšÎŸp†at:]…u×YžWÏ1Æ/—/ÿÃcêoõ¥À² ÎJ%›ÿäâÉ­«NS|U^À°ŽŒ«v°²Ý°%äÄ?ÃÿZgÛtªŽå uV A€")!úöéµ3ñ¹ijÈDLjÂ͕Gõ4HªõñhœŸó³Ä¥ŠÅFüs7. l<:™[,ZþôöᥖMg”¶ ™/$_ºt`áÎèôìÈ¿V؞UcgSÛÖÓÍ-ož» }'5·€ý°6*¡¿¿•*UžJøõ[ÏXž1…›¶ÏŸ+!bYPë à+}®¯÷¯â䨠Íoqz0Ÿu{ÔÚÝÞÖ¹ÑjåœñKmD %21‚Hä6R‰\DÚ¹Ã[y›,{†óŠMú©‰“4ºÑ­Êín>.«®Ÿdñ%2‰€D «7<ØýM·šN}—ÿÞiáÄÜ3[Æ՚š‰Å<)HDÎJä‹ÍäÆÖ">ÁŽó»±|WSgû‘ªdMê7zêD»íƒšV®·ºaǟ6l„XZ ÄOwoïš3­wm;[{ÏzÍï$k)°‘;äYfˆ€„™B@ðø"±„OP©Tn# %”J„|Î]ß&`§¥ÅÁ.6[f“Hdb>6>·_^î°§›µ‘IÝ!'w¯Yސ@$ 9«ƒ'2•ۈòy¡IžµÌ‘Ÿ¯Ç€L=:Ž÷±Ž°˜Ô%oæ«Gb£;'703®Õs•ߌ¥#üjð†?Ÿ¿#ðQ`·Zv,IšŸ IDAT¶^ZßK£ UƒûÚpÄÊÊjÖ¬Y<Oš—››û/g2–âC*€ÐÅ:™J9õ ·ëE022 …ù.ºtéRa{ –0ÿi]?S™hÞÐ, .‡ŒošîçãÚ&`AÛ5s¥wvïñ»ÊÄÄH,HŸH"QH`3oÿŠÆšK?5õðö»»ù÷ÅÆÆŠ$06õ‡Ìj/ÑŒZÝÎ#›l]Q9öhŸŠ«I—fm~÷°Î݇Ǜz3VíÝ×îٟݝ-m\<ü~þŸLp^sz{õø}ÝT«ïsðÈ ™LL”,¬¬ŽoTÅ.áîï-äÕýf×þuêø-ÝVúóùháЖÆ||H¹þYPPW %‰‘‘W “’’*f~â¿j‘1ß/^œ8qâ¿ !,,¬N:¯_¿æþ2 c8Õ¶mۍ7Ÿ}û6±ž?NÄÇK =_p:}‘ƒ:NWô¿Y:ï7­còÏû­×qÿó0\¥§ßÕéKŒÀƒÞGªÈ©¢×3úNèuÚŒŸ¢[†0t1Ç ùS8å,«×èŠ;\8Q “?ÚïÏeœŒ:±)¿adz†ž>Ú6οïÀÃ/Y–eéb‚Öëށá˜á‡B¡XŒxq›6mîܹúèÑ£Rªœá.µZݺuëù ØÚچ‡‡ëõú’J­œàžÅ0LttŽ““Ó±cÇ.]ºtñâŔ””2Œ ŸY³f;¶,zÿG¯/ûKAëuÅòþÍ_7îm3CÞö÷¯ªîC9Q8Öú‚g+HQ2ùŸTÐÐPWW×{÷††‡‡Ó4]1eñyÁÖ3&š5kŽ5ªsçÎaaa…¬êÕ«ÚÚÚº”@͚5]]]Ks!„ÞÙU™ßÚbY€¢(ª˜Í1 X$D^|Ê`¢!C$Åù§óbÌ-ôÌû“7:€(²ž…ª…ô>RPüÖ%ÜõyÑ% ž6ß'“€xysÕPŸ»Jzhß*ú .2lþ Þý'ùT )!Qå;bøÅš^<ž¹%±öØõ- †™&}“ÈKÈÉyç^{¿ K^Òž"(b;Š€€Ìž=ûàÁƒcǎU©T!NÇÍ«*e¶ÄçâôéÓ~~~ǏçâS1ߥ0€ýòåË-[¶5j”aÿÈÜÜ܊Ix韄‚8†—‚ÌûŽEé/˲÷vœ»—›™øîõ@yu“;IÜ[ïÞVҐM†ÚSÐUWÂ8Óû¡D*!䆍Ù%ðߨÓÙXˆØådWÂÏ ž†É«û<oРA:.00påʕõë×çÚ8–eW¯^=uêÔ·oߖ²a˜.Œ),¡2ŒiÅü.M‘ò¿ðó6–âÍü𳊈ýçjb GŠä‡~D¹“Îíχt©éB°ØÔQem'ø@fÔ§”””+V\ºtiþüùr¹œd­°o7±,[³f͓'Oúûûëõzÿ øú²!üóçÏŒ1¢^œz†T•ß­*ø¶|°ò_ÅÐBx7HPê°Ai%“¯Â>ÆÐ;¶¬T§Šˆ‡ 5ö{Ë3æýˆAÆ ÓëõÓŠM[°`A£F 摕••••UÙ,Ì7Ñ'C$ߎ’§i%ƒ…̲,È­+ÕŽ.SiÒæóçÏ/X°€Ófn/ˆBƒò–Zµj8p`À€:®oߟåªÐ†Ïž=;iÒ€4jÔÈpükûèÅwSc ™“OS§ÿHcƒ+аB9²k×®sæÌ1|aŸì/Öæo«Ä üAPš{ŒäRSS—-[VH›¹m쌌Œ*lö g­Ö®]û÷ß_¶lÙ®]»ÊµBr!Ÿ:ujúôé=zôðõõ5ô†á&…Uœ™EQÿ¹[jÙòùüïà«êØzÆVh„P@@A«W¯~üø±……Å׿ó¥ iúöíÛ·oß.€Í!+++GGG®¡¬€~›á¹>>>›7ož2eʛ7oÜÜÜÊ©ö’$™˜˜øçŸvîܹyóæo§Í®®®ŠŠŠfßݹsçøñãJ¥œã¿\')Š û2Ë3Šx: ÀÜÜ<((H©TríÎL±XYY-]º”›€Ÿ_›AEº O¯_¿~ppð°aÃ>¬ÑhÊÃÏÌMúIIIoÞŒÁ ) †arss 󥿔6ªœ....\ÈÎΎ‹‹Ójµå4¬V«µZ-÷DšŠÅb±«««……TÔ@˲:tèСƒ¡,ž={ƙÑÿñj©×ë¿òïEbyÆ|bïŠ^˜™™egg¿yóŠ<>¶ƒùÎtš$É/šÍEk¯‘‘‘™™Y\\œZ­.×¹Z4MK$ƒ6WXÚ =%===33“[Ն+$W'¿ÝAh,Ϙ"|>ßÙٙ$Éììlœ'˜Ò‘J¥ŽŽŽ_P› Õ^‚ lllžoD–k3M„œœœ¹¹9|Ñ)Å<O&“ñù|,Ïï‚X,.§-갟_asÁÊ®ÐÖÖÖr¹Œ\g8’$)‹áK/÷‘H$•*UÂs9 õœ„B!–gÌw«Ð<Ïð= Št{åë1Ý -‘HŸû޳,KQÔd‘Õ7]-ËÚ±Àņ)K‡3óÖ–ŠŒÏ÷çãê÷=e–g ƒÁ`°"ê5B”Pb]ÅÃQJºÜ¬ôŒ,ÊHš“Ÿ¬µ©äìdoÁ'PΛ—Y€Ì˜Êy• ÒŠ\=Ý­€ OþáÚù5ã—è×x6€$Žn2€ˆŠŠINW $µwsv°–“qv✙­‰Æ 絝-ŝw]kϗ§Í¬úuôó˜€,Jhdãâ^ÉLŒÔY©¹z‘˜—’ÿ&ƒu¬ìfoeLìs«ßÕªU{òäI¡ã£FÒjµžNbyÆ`0˜ ]©R¥©S§nÜž1::ºqãÆÆÆÆ‰„³ð>:\]Ò?‘ouÖS~óLÛ0jì™4÷þü ±'Œ,Žÿsø¯’Þd»›š–.Zy~ã¬a[¯Z‘Ze?zÝ®É=Óž„®_Œü•K Õ³ 'OÞ÷h°fÃÜ&UÂ·O Š1s2՞8s)&âUç)G·Ík'åÓ 'wM]°éü›t)OkR»×œñsÚ×Tܟ⣰Ÿ5nâ•ú#Vmô|{uö”—Ÿ'éÞš<ºÎØò¿1/öS,ïÔŸ9—–5\yfɀʆÔ;âwôØÐšŒNñø-ÓV™%óݚ Ÿ5ft£êÂW—÷¬ 9§uªs'ô洂 z.ÙŽæ×j¶¢è3€a—k×®………€Z­Æžm,Ï SŒ =wîÜcǎ:tÈÂÂÂÎÎÎÄÄÄÌ̌a˜’Ä!”››[ô8“ý–dÖèîûêȺg:ÉØ­«ZÉîÿ±á< Hì,Ÿ<ÒåhŠ‹ 8x÷ÙíÄD,éç¹zòÙq=! UôÃ[žÚ.Y¹uAÀzÿuü¯^MªÖ'‰ä ó:Ì=pb®jO»Ö¿íš2¥U-Ý£1†>lŒ),r˜qfØÂþ=º·§_d¬nÚŽ{߃Q+÷Îkí@I 3ËzÒâí»jWyŽCãnû¯ì6€Ã£¬goo:|ӄöŠ&æ€2-ö•،˜‹£MÔö>ü|_7õƒý£{Nüù ïú•@>©xxõô͗ö[WZ3«CÿcWu©bëF¢g8ܹs'888,,¬^œzõêÕãÆ0Xž1 аB€H$êÓ§O÷îÝïÞœy÷î]‰D¢R©233K²íŠ•gœ*+áÕÓ»œø—ÙY¯e¶2€ôdµ ‡'å0/±Ðšè6&ˆ %Õê¹ٚ›­ˆNQì[€Ó#§c×Oé`ËDÅ:ž\ÈÕ§Ñ:¥FÒ~ڑ-SœŒ‰·uÚ Ñt5h^Ý;ŠGŒ°ˆêœ7ayçw߬n]ÉÖ¡†@dVI.“€Äœòë×vl{”û$‰¡²²t §Z”ÌÂÖÑÎ^Ê5"ÀŒ@tFÜ£Ër÷k¿w“Èœ~0îâÏÛ?UZéŽTÍv+æ.TßX+lfm»-[«ÐeÈm†aþþûï˗/§¥¥8pÀÙÙïë‚åƒÁ`J4é8‘æóù 6lذaYnœ?~1 œHnj[]3cAªòõõ°è'—B®—qwµ1 ¡Tf0¬”ˆà€Tœ×‘ iD! zœV© 8¯rÖ_!+—ý~Iëz[šÓ|Ÿ@ Ö²jÄ04ŒŸ/‰(ŠòññéÔ©“••®Q_އ„ýß—.]:uêÔòåËqV`þ›Ì;wöìم hN}Õœ‹‡_xȒÆ">«ÑK[vïÒžŠ#¿$›»t£<¿¢3,š˜ãÅlnRò"¥=+/öÝî€EÃ4.¢7èõú &ôìÙS¯× OOO##£§ó…ÀÎm óýÚÜb-BT»U¯í£cZɌmí¬x%ÝR@›ÞˬáhÝ"Pþgåp~Îû*‚Ba¿WÐ|Wç?ŒÞõŠÜœ/Ì"Pºº2 “““S’ÇJ ÃRÈÈÈȇþ—^PÕ¥K’$¿’U¡\4hš>vìX¹n˜Ì²lÕªUœŒŒžo$‘Ž#„222BCC¿ì¶_!ccã6mÚඃåó¯P«ÕIIIŸK àöíÛk×®‰‰‘Édÿ)!”––7|øp©TúÅš‹@vvö¶mÛBBBÌÍÍË©8B999666cǎõõõý‚ ýèÑ£ž={úùùiµÚ/•íZ­öêÕ«4M㶃åó¯J¥FFFIII666ÿ^›CCCW­ZÕ¶mېÿ`fŠ¥¥õïßÿÕ«WóçÏ722ú‚ Í=Z¡P̚5ëéÓ§gϞ-ïͰ‚ƒƒ,XЩS§/¥Ð,ËÖ­[÷äɓ_¶p£E̗='˜ššJ¥Ò§OŸÂ§˜â .¬^œº]»vcǎ…ÿÞðË²æææ»v튍2eJnn.§R_J›srrŠL™¿k×®ò3 =dȐ>}úlÜžñĉœI]ñiÿ>z˜™™Yš_‚Ç¡1Xž1Ÿ‚µµµµµuxx8|Òð³A›/^ŒžbŊ¶mێ3>rBxéW9[RÈŽú͖cÉ ’••ÕŠM›RSS•JeÅ«W"¹¹¹ãƍ{ûöíŠM›,--ËՖ5€qðàÁþþþ6lø‚ ýïrîÃÕ€,qƒßYYY …B§Óáý/1 vn'ÇswwòäIdddµjÕ>¶çšà+W®,^ŒžsçÎ…@íÝ»÷üùó¥‡éèè8gΜ’®É;Ϊ£bßêøVö–2wa‘[B@Ó:…"‹Ç“K$Œ‚'ÔYYZR,1’èC])TÖÖÖk×®4iÒ/¿ü²iÓŠ vu"„”Jåȑ#Y–]»v­••Uø™ Þì!C† „Ö­[‡òóóûŠ” !Ä2Œ.;;‹GÉ%FŒb+Bt¹éYŒÈX,€HÄI"MÓϞ=S(<ÏÁÁ›z‰Á`yÆ|4Õ«Wôèё#GlmmårùǶæQQQ+V¬ýœ­øŸ¥›å˗¯^œzÜžq›7oþ`–~^;v¬­­m`` µµ5TÔ× ýÓO?oݺÕÎÎÎÛۛa‚(ÑÙVúيWhuò«Ý?Oœž~C3+Eҋ{÷Ÿ{µð²+ØÁÊy4cÂòN–Ž­Y™BŗfVVVNNŽX,–J¥Sè –çï ®IíÚµ àñxÕp€€€Œxñ¢oߟŶ8 èÒ¥KI÷Ò4=k֬ׯ_—$Ï yvr׿H·ŸýzöâWõqy4¬Ïòª+x:+ÏŽ63îɩؔ•…[@6çÖõç՝’ÅDú°HJU1'n„[6hWS*"siÛNœœÿYr•{šÍȑ#œŒŒ6oތzøðá€I“†ÉŸ?ÜG W®\éááñ‹õàÁƒ<àŽ¹"5À Ðݺu[œzõƒŒœœ ‚˜0aBDDD!O0BÈÍÍ-((è«z#hmVÜ㓱)« óɍ‹79ÎkÄÉóûœd2ϝ}â5@UŠãž ?cÆ ’$‹Vyóæ5hÐ7A,Ϙ`ee5tèÐ;vlݺuȐ!B¡°ì-;BˆÇã{=BH£Ñ”r/7:[šý*Ԑ ô¹€M­~Ýûwñá€õ‚=®’*2 À²P$~<$uٓ$ä~w^jd$¶aië&œ~šÝ* €i§cöG8mþe„“™H¯—÷{³|ÐÒ-zI!ÿ'÷—¢(–e£¢¢œœœâãã###7oÞ¬P( wI¥ÒáÃ‡ÇÆÆ~^yŠ(Š¢šü±*Z4³µšýjžžÐ©²„fH»@ HLLäVìܹsÞŒyÜø{4'ç×_-yfóWƒ—/0rrõÇÒ»íä55®ÒÂuI.‘ˆ)RðÁ÷"999""bçΝ …‚¢(‚ ŽZ­‘‘ÑĉŸÜÇÇgãÆÓ§O?yòä«W¯>(œb±žü6a LêÖu°W÷ÖÖv“ò‰Ø¿7ÿ«Ò@ÎîzM†=n8mɜ.I}; ‹x7ï À›ÐZÍ¿+é·hQý ÷oÝ£|ÆR:Z§çbn$ÒÝ_6rI4ŽâåµÙӂH;GP$\Ù>¥oÀÌ£’¿vª|móÏs×lÍž7ã×þ+âj;ý'Ç9ÃFžz’¢@ˆ-©Ë’•••Pì<_œ^/‰ÊIž =èΝ;—/_Ÿ~ýúŋµZ­¡Lߌyvùòåû÷ïߟ};q_œzõʕ+—/_ŸzõjLLŒá8ŸÏ¿wïÞå˗oÞŒyþüùŒŒŒ¢5„ šŠcbbt:]Q'ŠZ­þìý¹ª"2&Ó,Üqå^< ðú§˓t<‚Ò>‹j78pΜñuE«‡u:Ü敛øä쉜Wix±iñð>5#ÏmótçþWI¯ ²L&Š!>—.]Ú»w¯¡,p³ƒÁÖ3æãlh33³öíÛûøøpsž?>99ÙÅÅ%**ªØ6…ÛIÑÝÝœŒê™±S‡ÆõWyY4ïõS.@¯S h$“pnGý÷ííÖÜ-Õ:;xËškqÛzrsuqñÖ±kÖNëçÍñs&zԖ‡÷Z«U+Kên6ë7.gþ/;n._ÐPòàÄ®»Y]ƒ›k©Ò„æu.=úk3•,ÍMÞzÙҞ¹ IDATönX×:»o†{ éןG ¡óîÕ­oD&Žv·€(TJÞêt:‰Dò÷ßwéÒÅØØ233O:eii¹téÒàà`N®X–•J¥999ŸžcÅ |–rÍÓ§Oííí…B!7ø••e85sæÌ+Vpžj‚ ÒÒÒ §êÖ­+‘HŠ¥RibbRlÚu:—š5jŒ}û–“d¡P™““3{öìpÛ òx<Çw|Z~ûöm•*U uTP¥6=„Ò#ÇnßñkåJÝXÑbRój<à· ˜õƒT %.Üpé|,ô¶)ÐÅ¡‘NÃG<€W»®ÏnÜbéäñ>VšSut¶m0MëÊX999#GŽÜ·oMӏ?Þžq£@ ÀmË3æ£mh@`kkkiiY¯^=F£Óéx<×ÈÛúüóÏ?³gÏ.(q=’¢‘ßà9ŠÁè2yÔöÁ v“ˆ¡µ*Æ]\À§£ÍÒ Mlœj;À·³‘˜JX¶ÄݘUº.i;hIŸ33£ëï›sªÉâ[N)4kjdÚÜÃK& ŒÍŒMi-­Skõ2ùµ­Óü±@šlِàPPBjµºmÛ¶>4 úV®\yþüùC† 騱#g_ŠD¢=zóùŸ8OM.—;99íKå/>[[Û   ŒŒ Îâܵk·R†Ú€IµZ ‰„›Ï±aÃn³L‚ §L™R;˜;¥T*ÿúë/C¬‚P«Õ"‘hƌ\€Ïç_ŒxñÚµk6løŽÞ EQׯ__Œxq¡ç³H\wПéÐÛqïN:Ðp̂º& —׃[š“«qws_ÅBáURB$BÀšÞêÌ]]kžY!»Ø $<`ËŽ³7MÓFFFAAAVVVÑÑÑ»ví’J¥%-dÀ`°óH‚' XB—“•žÚifÐÒ_ûXZxRc¹° £=Ün•+W.Ô|›˜˜˜™™ސ$ikkûÉò\&&&ñññ7oÞäÌkGGÇN:q›føùù=|ø0>>ž ‘HT¿~}n¶Wjjê•+W8Y533óõõå&Ÿ3 ãïïçΊ¢H’ÌÊʲµµ-=íNNNù€§§Áçó 7šššŠÅb™L&“É>-æææÅì¶Í h3 Àòð¶àYïš,ZÖÀLBéc÷ûö™<åϰ5m_þùsà L‰eH3@¿ÎÔŒUÑ`BhsÖ³Þ¹dd2™ŸŸ_rr2÷Bá}Ä0Xž1Ÿ.Šeã~XÒ YÍo" Ó[¯ö}6·Ÿ/)>:ŽWÕ:/ò €ŒŠ­kâ­ÓKß[ÝH;iܘƒ—çô7*Øl0±¬›õûl9tÑâ×?šŠ(!•õôÂÌMÃN7~yb×é˖'×õiý£¥ÓÐ{Ž»7Ý·†êõóž ª²…”úPŸ;Aóë–w–rNlGGG;;»üÇ98EQõêÕ«[·.w%I’†éô&&&?üðƒ!’$ ©pqqá·,Ó¹µù):âþï?=^lLbQÕo°õúykvè»­lQņ•“š¥–I€}ôÖQ"i7]̜–a€g]ÇÂvˉÐ]{Œ°îõcÀãWF<ªLý'ÃÔ÷-Z”^èÌçO ÃT”NÓœ˜`xyŸD†Öë†ÀvYêƒé­Ö4ª$'yb÷ºÍ((±4­§i@Ô¬ßèI+ÿÞ·Ž©Ó/Žiëúõ*Uù&(ÑbŒe‰mÚŽ©[·n‹-26§Ž'û‹ìܹ³wïޛ7oæyþ©Ý—¢€ÁàŸþéСƒŸŸ_£FJ÷P{ ~ŸmèÞ(ù %vNNJ)!2;'G­ŒäÂî2[¡”J'­JÎZÓþ¿Ìý³\v„Õ3z>QJ Å[oœe±X °víZNW ëÖ­›9sfffæ}ÆUŠ”Zû ?ꎗÀk@Û/—›Uà¶Í»[Œà @ ÐÖoúî–/Ú|ÛÝ%ÙŒuëÖžžžO>ù$ à)wÓ¥”†„„ìÝ»7::ºwïnm”®Ô<(™~JJJ\\œ»»û믿®P(¬œáªªÒÇfÚJþ㶄Æ3zö{8ëšÝñññÇ 6ì‹/Ÿ ²>O)Õét:îá÷ïÏð8CåU¿Sw(Õ8 J·ÆmÜröJ²y˖-¥³¹ä`åiޚ"88xߟ}ÑÑєҗ_~¹RºdÊ7n܈W«Õƒ R*•‚ `Ž!ôôaã6º'd2Ùøñ㣢¢âãã/_Ÿ wôþsü¬+©»Þ3ó9öžµMûí·ß.ŸÍ2™ì© FQ’Ð{÷î3fÌŠM›*5)­SNJJ7nÃ0Æ +ÉfkqµZ]•nKU¹žá)v„°zF&ôÔ©Sßÿý)SŠÄÇÇ»¹¹UÞ`ŸUñˆ•aNž<9mÚŽÅ‹—ÉfF£Óé4ÍSk$°~uHHÈîÝ»»uëf6››4iRIMÍ Ãäåå-[¶ŒçùwÞyG©T–œó&„øúúzyy1 ót–=??ÿÖ­[yyyÏ꘯°°;‚!ŒgTåZ*•Ξ={éÒ¥}úôEñyÛOÉåòU«VY‡…*ÍuêÔy„i?©„þ믿š4i’ŸŸo«Êø.Aºuë6iÒ$‹ÅR’Í Ãøøøøùù=µlvrr¢”FEEY‡û6›ÍOÿ‘Ò°aê}Òa<£ç2¡ !£F5jTJJJvvösuÏyJ©^¯/Ý_úYesé_D«Õ^Ÿ|Y¯×'''sWIíÌǙL&ëbŠ¢È²¬¯¯ïSËfJiݺu“““KžIJJÊÉÉyú­Í¢(–Ÿm(BÏšJ$4Üí+äêêZPPýVÖ5ðl³¹Ì1“F£qvvNNN6›Í•Ý‹»$›­×Ä?µöüÒõz}^^^~~þ3<퍭ÜãUÅ2Z©Têt:†açþK՗T* x¶Ù\&¡œŒŒ!·nݪÔY¢”º¹¹ùøø<Íl.a…Bñ {¥Y{c`O1„ñŒªhBÆç°ŒËåjµºŠŽí—$ާ§§Z­®Ôû 3 £ÕjŸm6€L&«U«Ö³œ³²uìRÜ ŒgTZ¡P”¿Âs¢Jw/IèGŸT5ZvJ©D"y:KZœ6„ñŒPq$àâ?ŸóóÌÛó˜—æÔsw3p¢oýØÎÍý* Q @@0ë³Ònž=›êè.Åÿ„ñŒBO¶š%„ЬsŸ}ªFM¢Þèß)À[û\ „‡0žBè)!}þBì)Š€µÂœó©ÄÌ >@)eðAÀë˜Æ3BUcĒ둉T¢ŠpóvfEŽ]»Æ3BU>V!R"SJŠcW$ !îvžbÆ3B=;žADòwRhþ՛` õó(yœô(:”Þ}Ä0 !DB˜òoBã!„ðÐÅ;qÍÒ£@æ†W)zŽ”ð†ŽMsÆLúê8!€à֙/ޛ²ô׋„BDÎ"ægd̜¡Àg0 %wôFè™ÂëžBÕ¡iôöü7oÆœ7š ‚!?bᩑ®&‹éæ‰c—ýÚW˜sýèIÑŸ+n[óùò¯-Â^yóRmü’Å/7 ’ã9iTU7r>~øðáF£±Äìܹ3%%ãa<#„ž;;;•J•ššêííýȕeãÆ—/_^³WԜ9sÒÓÓqƒAÁsÏ¡'ÉÅÅE£Ñ$&&£žX%„ð<_ãW”ÑhdŠÌq n?ã!T)<==ÝÜÜΜ9x—Š… žçsrrôz}Í>׎0žBÏ¥”eÙÐÐЂ‚‚sçÎÕĊðžËÆgé†ÉÉÉILLŒråÊíÛ·Ÿ‡„ñŒz–ÂÃÃu:ÝÖ­[srr!U;¡ÿkÜBȝ³¶üŒëZй‚z÷ßÉÜg‚„‹ÅRTT€×ëY–•Ëåpÿi!Œg„z4Ö0–J¥;waÕªUf³¹j'4!„ܹtìØ¹TA|ØÞæéû~øbåwfðOSLùû÷—2ï3Aë:!„ØÙÙ-ZŽš^œz‘åŽmÛ[ŒŸ[Øs!ôä999ÅÅÅ­ZµjÙ²eÇW©Tp÷bßÇ*t˟ζ1Q›ï«ðœ@HâÃ\•\Ï (Àg1dàôUœšƒ»²¢ùÂüÙ³ÿ„^ ….žT*=zôè+¯ŒËqœR©4›Í¢(Êåòf͚ᶄÕ3B=±<<<âââA˜1cÆßÿ ÷öûÏõtqæ —v-nVÏËËÕÉqè¡! ~^0Ä×§–¯¿®ßÇ; @}ú•?œ°~ßÑÕÓ{jíëôñùu=%„ú+‡õ®çæîà`÷Á÷ŠÉúýó·/ݘünާ×ÌM— ÕoŸ÷¿¹¿ýiZ»ºßH2¿Ÿû–“³³‡GD÷!Ë -þ÷_¶íŒžÍÀßëæ|öÃÞS;–Žnìá³úH2%äÚÖC¯ßŒ>|p× àOö¥ßÿ Ä: jýúõ›5kuãÆ† FEE5mÚKgŒg„zò íêêן}ûe˖=zóæÍÉÉÉ¢(Â};u+ AÊf!„Àƒ»w˜ìØrЪoÖ/žãf/eA¿>¬Aß Ӗ­_³ttágœš4ú‘\îé­ ö~cyFӅӣnoùlɳðÞ¬W#¿Þ°aÅg-Bt û Æm@Š‹‰¶`Á‹õ\(ˆ·~ÿrúë]þ—ÑîÃYƒ™‚ 3çT¬T*F•œœìââ2nÜžùóçㆄñŒB•UCK${{ûf͚5jÔHQY–-_ï’$’ƒN™2ÅÖ¥`œk¹:hå •Êdސ„7­ë.e P¹£o0@¡™J©Ü1ºã fÖ ÐsÎì³ý‡¿0>¢ï×ËçœÖÜW ʀašD"‘0„R ¢[G¹Ë$Àý³~îÄ¡lqrò±ªÆ¡ @ÈÝSԖ\K£6­›xËð, ʁa€‘0uÒÝd2õìÙ³K—.NNNûöí+€‚ž7ØžªÄ„¶†Žõzh¹\®R©4R©ÔT@¡P(•JkxYŒA9ÞPꎵh(€p!5¿8ì)—P|Z›ˆÀ ÅÓ±vød^M>Úûgêí£ÈñA³¿:—Vd}9ÇòïΐPð¯?ùË¢ñëNíK3džÿá­šêMæòóŊ"±~'-éXF)… )õåPr2~üøñŸŸŸ …·Œg„ªô~rlö¶_è‘ÙïŒv_ZVæéC®åsLPÌ©$nʊ YúüŽSK'U«FFû‚E(ÛõL†˙?9•¬ðªÓB«‘Yˆ@ ØÈ.Ÿ÷ퟷs–{#Sà ¹wx^€†ìÓÛvlþq/‘ñF€rœÇïydjœàÌžu—‹ÌBf-Yÿ˜}ÚFBBŽã(«”³Ö'­Å¬ÅhäA¢TJáÞëŒï9ï{÷Í&#§PÊJbŸ`1A¡”’ÒÇwkZ‹™“Êe¢Àq+“±Lù‰Ûú"‹ÑJ¥Žä{K{ïœ÷Μ93eʔÂÂBOOϐ‡œV=°kBšºT„X‡õ–É”÷d¥”H•JéÝ'JçÙ=Ùv·?¹5›ïŸîN Ô‰â’©\@VŠ`KEæýŸ€€T©|š€åyÞd2)•Ê =°q!Tí2ºÌƒŸ{`˜ÙÔRϒŠßþŸ"ó¿œ!Œg„Bã!„¯D®¡$<·ˆî»…à*@U5wîÜ9qâD~~þ»(«ŠQ©T.\š©K‡0žB5»»»ŸŸß;ïŒÃ0 ÏóƒÁb±Ô°e€”2 Ó·o_›#›"„ñŒªr¹|ìØ±’g’’’rssŠž‰3›Í&“ t„ñŒªêÊ4öêõúŒŒŒŒŒŒÏ%G$¶1EÏ!T51 £R©AšÁçhEQT©T5øøa<#„j¹\îããSãOÐJ$©TŠ?7ÂxFUÖû\©Õêçgy±#7ÂxFUuO*«Šcϐ¹gû¯‡Ï&;¶ìÙœ]-{YU‹CÌfTží@Õð¢”Ќ=?~±"á„(—žÜœaúW;nå[!xK „ñŒBÏ& íÜџw^ yaÀÔIS&õoª?öó±K7„â[WØš¶éœËŒŠ+a<#„Ðã§3w5éFŠ¢V빆 VÞª¿}ÁßI©ù<”¿sÉ &Á”zò÷×o!TûêéÓWò̀·aFOž{FÕdž¬ÔôdÖÉËÛI  ñ®eowúfFA‘àdϖ}?!@EcêÑwÇ-LÊ.RÖ <"Fq|úÂdŽr·ÆÃßÞØCJË;BX=#„Ð X,ŒI€â¢—(Y&++ßdælÜ¢peç×WäÑó>ŸëzgÝï.ÙøgÿéŸÏÝ?K?ðëEÀlFÏ!ôØŽ„02VÊHeŏ©@ÝÝŽr…íK)gÔ;·ëY§A¯ÿkUpývŸààíìçnoÈ-À5Š0žBè±)œŒ]}¹;…7³xîvŠ!ËÕÓI#ÿ÷ìÞ¿g“)% K²·îÏ¡Šäێ›=˜§—Ìxÿ‡õ ۏ]V†yâEÏ!ôX(€222<ØüçÞ_÷˜ÎnøîÌ9æA!®røkÍŽ×ÜÌ7Âï[ôV¿[Š!Œ$üÕ íßv}¡û‚vŁ„¹Óß4ù.§úÝv ĵŠžì†ªÉ¥@ˆc݆ÝY²äÃv?~Èú ™69йä§\O9¯â-"ɹ–˜’Ր¹cäØ5¿0™%J•T*¶¿ÜóЉµœFʧ>ž~F•œéâ=y111 r¹Wų/ )XÇã2ääëNŽj%[ü’õB* Šÿ$„ÜÍÞÒÊï*ï^V…#|!¬žBèñª»Y«Ž³ó¶³+Œ„ü›³ÿþYê™R±õ,B•Ï=#„ž“&<@ã!„BÏ!„Æ3B!„0žB!Œg„Ba<#„BÏ!„ÂxF!„Æ3BÕCMmGFèࠞUE„“'OæååU÷l ÷ööÆ!Œg„jˆ={öDDD(Šêºs‘HΜ9£P(0žÂxFšæ`Y¶]»vÕ7žÀd2áïˆÐ£ÁsÏU]ÇUëùaîÙÉàyh„°zFšæ*Ÿ3ñC=û ‰¢˜———ŸŸÏqœ\.W«Õ,Ë⯇Æ3B5:š¹Û¿­[—p*YæÛçµØHBèÝW <Ïgff^œz•ã8ggçÚµkc<#ô°q¡jÎ@šqꇖ!ÑSÿ"m;tlèóùˆÃgZ„R¥Ú9Ž3™LƒA&“Éd² 8BX=#TÃ™bö¥=}ºõ÷Õ¢Am<”DìÔ4ÈqÜŽ„¹Ž->٘š*޵”wpp7nÜÑ£G˜Šggç³gÏâO‹Æ3BÕºrKaúÖOúŸë¿zÿè`žµ÷ç?Löº&Íâ&vOúþôÚc9›;‘{óÙvƒ·ÍgŠmŒü)î~ŠeÙ³gÏΙ3§M›6‹E.—sG)eY600Y„ÊÃÆm„ª BP˝Kû&oîx|n—›ûVµ}iûõK>š1svbÔÛ= µ<º ekgBˆ°{ú€¶üy|ÝH;­œ{­.[/çB,EYßḬ̀¥Ò§u×¹g²Í„ä=ë—.þøç-Ëz¿@HƒO.å$ni “©&¯;Äñ"!„ˆ·?h¯RÛyútÝ}“˜uJ©ŸŸ_íÚµƒ‚‚víÚåëë€ÓéðgEã¡§J.—?Ö?'cãߓ <——Òr»Ù~˜ßô«ßŽ|œQd«¬L8øK%ù§Òl–¯)ÛçõkÚ|%»jÓêAu¶œœÁ`1ë‰ÄãáS‡~ëy{ÙìwO€hHÚ¹pìËS­ý振˗sùäåøÅKߖ.ysÑÉL@ö|—°1–‡Ïþ1ˆêՖ=. @ȃÏ‹¢hýcêÔ©‚ à‚Ð}`ã6B•B¡PDGG?òÇEQtvv:thÙxæ¹ë§~:)vÑg\?ºyuŽ+°… !@@áç+S;‰6'hŒú6s’~ã+ct×z-¿=₝ü^Ÿ<ä^œæ©žõWþy=ŽŠ…Eiºš©3>v‹ÇõIDATû F—ë—øÕvïe¿Ìy³kìÖ§—U`ÓµíÓr &ŒÚŸ¶ÆMë=oôñª{ðÙn•JµaÆ#FäääšÕê‰'Ν;7„0žzzL&Ó¶mÛ¹€ffþüù6 hÂ(íýBe³h.© --¥ðŒ¬~'àӓš¯‡“Í ¹B›Îm}åRš`1pE·Ÿ|lÜŒ­Z­ŸVm^‹2Œ Ôñ÷ðñF,›øùø:ȀU))+fNψ9Dëô‚ëÍlf4ûõëׯ_?­V{ýúuWWWÜNÂxFèicÆfõcMS"q irnó —ÎA~i£Š/ìiHXŒê|§×ê-vÊ^šÝsŒ ‚®Û_R„è™ß>œúÏÃy|kziá;£~*0[/‚µñ™ÈàKo,Q\zªhdUÉÿӈ(3fÌÐh4Uj„ªÜWBÕVæêÙð»WwK#g~÷[œ£)¬ï ÞrþM͙=‡-ü(\”ÒûçB8*rú ˆY7oÝôÓ÷ßí!Œ!H…"S Täa=fkUñ ßJ8•”~çæ™ã‡.äÌZBˆÑhä8N¯×9’Rª×ëqPn„°zFšÚ#”akGMùðåžC=³ľæ Í¡ËÈY/3Åe¬Í€”kìk8+ì=ì•ÖçÅA×÷ˆ ¬Û¬Ák³Ç®›±rê„úïŸàl¯-±ëâࣗ)#urò’2D—)9—”CÂ{5ßHÝœŸ:‘~ß9EÑ××·{÷îåG sqqÁ_!›ÿï8^BO^LLLBBÂãtޞ?~\\œÝ=õ«5}óΕñ=flë3zöËáö·“RUÞœúŽÑVPuÛny¶^F ¥›ÂEþmŽ/ô÷LâßQdŠÂ¯ØºukjjjDD„Ùlö÷÷¯è2ª*5)BU6n#T­š ¡”+ïðÖrý•Ý<ŠÎœÆÛ»…Ô PÜïC¶Â@ñÁ9±F40L©!6KŠ”yPü{÷äþùjmÙ6›ÍœŠ¿,Be`ã6BÕ3¡ au=ÞÑãAEò}§T*«9,1]ÂxFUˆ“Õ ØžP>|–Tïè'~]BX=#„ž1QϞ=«R©¬—ŒˆY]Èd²””BVõa<#Ts4nÜøÆ@ÉÎÎÎÉÉ©^9gíbTí,ÂxFU˜m/œôRÉÃ;wî$''W»¥ „ð<w¿@ã¡¢L¡l2™L&Sõm%E‡X@㡚F¡P8::VßùEQ­VãIh„0žªQœµZmõJ©T*­îÑÂxFݓm2™L&“ÕŒeÁ¡‡W%"TÕÕ€<ÃlFã!„ÂxF!„Æ3B!„ñŒB!Œg„ª3É!„ñŒP•ñ8÷kÂ1¶j ü)Ñ£Á랪IIIƒÁÎÎîÑ.%"„,[¶,33¯DªÖT*Õžqãp= Œg„ª ww÷ÔÔT;;»Gž‚^¯=zŽ–_Ք sçÎÅõ€0žªBBCC/\žò8ãd‘»p}VGåûà ièáá¹g„*E«V­Ž9"Šb¥ìŽ©ÍŠšb]ÕXQ­÷ìÂlFÏ=cM›6MMMœ~ý:<éÎAÔº›'T0ôù…Ef‹@bó»0µp(Sy+šššèæÍ›III7oÞÔëõžÞÑÃÃÆm„*eßOúè#¹\þÄ*'jMaÍù‰§öoü~ËÑÄÛ2uíÖ]ºöéÚ®¶³šë[J†BM…ùœD­UHjhGHé•oó¥äyë[ž¢ÈÔJ9ËTÖ:1)))‹E&“©ÕêŠn;†…5Âê¡§Áº«eYö‹/Ÿ°X,„'Q¢ïÅEcÖÎ3š¿4æž÷+«Ÿþfá»/^Z3àõA#ò_$î˜Ô'~ýٚ[FJ)gÔL|9G!‚Ål0-Œh}˱ãÇ~Ÿ=CÏWê–@aY–çù«W¯&&&^*'??³a<#ôô h˜={ö±cÇ6mÚd4­»àÇ iJ€`<¿cÉëüø¯Ä㻺(ŸM^ûzóþ–Œ%}›„”ûV’—KYzŸIW°œä~ÀÇ+XL“£õÃÏ¥@ˆxâÓ¹ŸM+©ŠËË<¶gõú_ÎåÅ+¥ /ß[ï§ÿeÆp֟a˜€€€Ö­[ÇÆÆvèÐ!66¶cǎ:tèÔ©SXXØÚµkñÿ•‡ÛUVÙD)U(ëÖ­‹7 :uòôô,]'ý×&Më ç‚;—?[žì…ï‡ÔÉ?ž)áRFVAÝøÅ“GŸ8ó×#»{÷V”›(}ñÓm-€öwqM·.»šFä wÆš—úëÜ©>7+;_j§ÍOMJºÃùÖ ðu“1 3’.\ýÇ`²hj…D{ˁ"dÝHÔkj©ó/§ÉšŽŽTXò®ÿ39[êäæV·¶’!åÚØ‹—À˜sûôÅ$³ÅB·ÐÆuÜÕr*Z²’¯šüTúäSW²íœB#µb.ÈÎÎ+’kUÙÿ$ÝL·øÔr•2 Ò®¿–j2óZŸÈ /}ê…o&~žblƒžÊUpc_{rçÆÕ‹ÉwQ8ºû…„ÖR2æÓkÖÌá­Û~‡RªO?¿ ‹®ËÈéC_kg¯µ êŒ~¥4åèÖ·£š…ùé|ܝ'~™ÅÙ^R‹Å2jԚÇ:tèË/¿ ²>ðàÁŋ[ÿ4hТE‹ð?•‡ÛUn jµzÖ¬Y­ZµÚ³gÏÆ7oÞüË/¿ìß¿ÿ?þعsç.[öïߟ‘‘a£)˜·ä§ž ҉¿qbç–í¯ýŽup÷.›D³ prNé<›3bÊŸöO‘@Ì9ŽxcbZØÆÓ—ÿÜþÝkâ© ×nf cŒvþĆ})mG¯þ+aŽø×Þm»¯ä~íÒY‡ön\žK“ž)D¹Nªð”ÙžVâÌ `H>³Ÿñر¡ÙaŠwöÆ_‘˜9 ë1fÌÇ£_ò®6«Uû€‘æCáÕÍ&ùkŸ}±Ÿè5sŸæÓŽ%çÆø9ñfðýÕÏo4àn¹pŠ•ÕûkÃÂ$îLbŠTdó ôú_¿~÷Ӂ\…œž"·¯îÜÚ]+ kVwÓ/ßíÌSe_®fÀOC‚ǬÚ8º)¥…DDÀ€‘³°M§L\ôV[WþR oÿcEb!äåÿÈ©‡¬Ö:̞ô}oÁ Ï_:–”ÿBK?ÿúpÚÁÇÉÑ€:yÔR}ÿÙrSÖß©F##K-prpMãÜÜ|µ"q` CàÆ™õR§Õ?Œâ,|ûÃâ|íxÒº G Zí S–úF(diu¡þ7Ĕ"€š–n‡ŸÿjÆôÌ=^ŽnîÆBé®ã÷?ßqèС'NdffnÛ¶-$$„eYüAÏ=³º$€#"""""惋/.ŸÜ #qòk€L—š©*cÛ¡«’ÜïWoù-è•ÖÉ;Ž¥åd׫]Ñ‹‡°Y•¬8÷™Ì”†QµPgµÆÇM &“Þba$D,e‰B %ÂPë lB ®‡€ÀøŒÌ”‹YFÆ­þë=»iÅôB}~ZZºRÁðf£ÂÈQF–ä&Ÿ“,ѹÖ÷×FHe €Ǟ{ϛMFCŽRƒ…ºÙiœœÕ`2ò‰”È€5°D¡Šx C ff"PîæÙ_njûð޲a#wìƒ%Îb1Š”§BÉ®ÞÝJ@¥Œ»aC€Š €Ò Ú®ÀqFÎır¥1`ÄRVûÍ?~4fi_ŸÛÓß^úÀTBÈ€I“4hpðàÁ>ú8ŽÃÿ„ñŒÐ3éÿ„çm\ðC$Rw]£ü%Ÿ˜F,|ý±K\%ó–6oý¢CΡ¥Q­bºEÚß¿”Sžú‹I §mt~sï ?Ý­Rö ϕtS¢"@åYÒ¶n?Ñ7¶Y˜\ß±¢Èìàª&@€7qŒDmçYØð¶3 ñ¶Î»ÁBB»\Øu`وJÜûÁŠí‹ü3²¥÷Žþ;æÀʁåæ›€Z{W‹Œ p%ëAš÷Hzû‡m'{GGª qûœ sUQF W.Á`ð†K¿¿õœ11ýË:‰»¶Û“,€TI3ÏÝHM.„@y©æ ;¯–ŸØrªÓÄ(-NþºÄnÑH)¥Å‹Y*Îs³ ¡}ß^úÚÛ­:Döýyÿ偱þöölD‘HŠ÷·mÛ¶ŒŒ,þ9 5a<#TœQÂH]ý[ ÔΏ›}díìoBN£>õC=)g¿ªwnÜ,ÔŸ‚áœÞ¬7ñ@©Ò¯Íg†Mß²tæw…¢PjïJõ<€Ès}¡‰`€ô‚ÁÄñP{Òä©Ã—~=jðþöâñc§{Ç͏Ñ9ͅ 7‹DæÛ ÇûoxJ«K{£Ä|§ FCÇM©k«žd]BºE0k§?æ,jsänðû€!ß®ýª=§‹8káKŽ/Ð @äÍEEz³@­³T€ŒfN AÓ§Mûß²ÏßycŸÖrì號#Eûkøz_J?jÀèoM˜í,ü8ŒWÿ@HÏ`˜ÄÍ¿êÓ¯eŽòý©³†ŸlY¶`hç‚©@/1‹ŽÍώºvĀóœHéoÍXÖÜ8œ`Ôç,Öø€œI(@ ôÔÆ_n>.vŸrIŒ~¥U€³êaŽÏ.^Œ8fÌ£ÑȲ,Ã0‹E¡PlÚŽiêÔ©žm#ÿ,³f͵€PtäȑƍËåÿÖyÖk•€*ç zþ»Ö,[sèŽwD Æ˜xî’QáÓ²I ‚©ðb-•‹Ghã–ažZB1];µ òšÒ®÷›µÒ×ý–5~H+¥\íP7¢^ž§VÂÈÔnµÃš¶ˆšå®u«ßŽy Jä(«pjØ9~ÒøÎ @4®naMZ†ž©(ViÞ±uš?1q*{'÷°ú ꇫY[‡*ïaµ%D¡q è3y\ޟ+£ömõbš«›gx£–A® `$ZßzM›6÷”Ë5ººõꆹkX"Óxèê6oYÏÓUãÞšy‹9ρDéÜžÛèÉãc]¥€ujæì"Õ*ì#Zµ ó×û»ˆTÚæ¥~Ãú8Ú»ÖoÚŽvp- S;¬~¿§œ£G`dóº~®r‰Ä·m›ŠnB‘Y¢rðŽzuâ„-TÀJŒëÔkЀ¶“Œ°rO]ƒæÂu®,gâx‹ Óvì=zPçPw±Õ`!Šâ®]»ÂÃíý t:ƒƒƒƒƒƒV«uppP«Õ-[¶ìܹ³««+nðšì!¶« T5͟??..®Ì-)KÒ÷ÎÅœk7íÉç5JVÞä….± +(âîÏR,ØÜåÍ/õèæxqë‚Õ;OD¿wéӁµËE¹6ÞB)%Œ§\“Ÿ­çlO ôØ€1KÐQÁômÍÌ=o)”Ôö‚ñ<ÿî»ïöîݛçy¹\^¯^=FóàG°q¡jv@MˆuWîÖnÒÔæ)I)9z^ŠÖžº¹+î÷¡ÒeN}„ä3»þ¡£ß “ö® ¥NWßóîâ»l” ǒ‡Ö¿ˆÍ%6g€ÔïdÉSeŸÚöT0KeãŽÔIéážKOëÞEŸ÷˜ãÞûxÞ3 )ŸÜÌVQõz}EñŒÙŒ0žª! „Ví['Ô÷¡kÓâH"ŠÖS? ËÊ՛x©ÒÞÃÓYFî_œ• ÇG~S™×îþõßÃÉÖ·U§äáf²ì1ÇC~=&+ÂxFÝ7*(! •kÝœµîpoõ‰ªJpÀ„ª®Òýžvأǯ~$Xÿ ¬žª‰/^̲,!Äl6㍪J©Éd£ôˆÇÍØs¡ªI¯× ‚`­nSRRnݺ…ë€úía Q*•”R©TªÓé<<^¢ߺyS‰^è3¿oôôž‹-Ì< uu õ«£(ª©®n^wošZº¢\Ÿð×/¿ºÿá{ªîš …²tYÕtajëΧC¡ôôÅúè§¡®®¡nuœ'V€’6ŸTyÏæ†/æòù؎KÿÀ¡ÏþWšËç³c—>óųãã£cñýòŸ]Û¶lžýƒæŠ_ÿ7ݺeS€B+¥\Ÿ00<:EŠ”Ñ/æë¿6>Þc}ò[ÍÀðð•\|ßóK䟊u5ÕÕ õ«kª«gË3¿§ŠÁÕüd!7:ÅK–V­Œgmèå$æÿˆµõb;+å&Ç.„:: _†Sï\›)„NA‚üzö ,N+ïi\²tyèe鎏>ú(tkimkk?Œúî;ÿàášÐY˜ïŸÿwÏù7‹÷‡ÿêóžýû?ðÔþ8O¬H³ßœc;nۖÍß|ác;.ßûÁßt÷öÅvœ)±¢ŠºyݺÙ'×Íëîm𝫰N4”žŸsßýþC§H‘¿ýO:­òk#úÇά¹éÞæu÷67­Ó–ׅ³ƒç;C§˜o÷ÿÆ‘[óÄǞúnlg¥ÙÔû#§þk°ïÿK—Uíùÿ÷P§Ç£ëø'²ý¡S‡U ·ï~6æCý‹“§Ç fn,í²ã—fŸœ^ºüavªŠae.t"æè?ÛþÐ*êa+”¯+¹|wo_Ô;ç/nÛ²yö™õÖ-›kª«E*Ö»CÃQ]ÿŒÂlIïÛNeëíjÿ9&$J6Óðô™éÂÈàéµë ˜€RӍ¥]Ëk¯_ÿ㎓ïýÑï®þèÃé€y˜çòdÆoÈ Éº{û®?³^S_·uËŠæuëvíØî5P ³%ýõo;÷5­ÛºeÓÖ-›ÊhU&Ÿi"Ûïm )—<6ÀD¶ß× @eӍ¥ZOß¹·Ît]ÿÓékÑ;#nǜ‰žþ³í Û썀䛜JíøË¯Œ¯iݮ۷nÙdï"P:ï ¿;4<» äó;¶77­Ûµc»œ‹ÀÛ@Ò,›é™™|SÑhŠ{óÌSŸ*˜n,ÕZ^k›÷W:ߞlÞWWt5Hnhfº0tŸsÃO„܆ÙÖQ­©¯Ûµcû®ەd@IœuŠë­3]_{ýó;¶oݲÙkYó64›KÄ5E™ÁSM÷ï €Rэ¥×¡Ž7fŸ×Ìs¬;÷…mwş‡›<ßÙØŒÓmÌPŽFÇÆÛÚ·µŸ¯iÝÞGv{Z ”ÚlIÖÒúú®Û·nÞŽkÇöЉXˆÁó ÛVÞ³6tˆÕµ™«a/».›é֍T°;C Œ\Ÿpšãð ÿօLŸðÁʘóð™z»ZCGåÝ¡á—_=ø_zå'-ÃCÇ*ܕ\þÍ£Çÿã~üÿüȱ¡ã°ýgÛCG€že3ÝÁ*κ<™¹šŸ €Rэ¥Ô¡ŽÃWrùOý»?ýEœažÙþɱ ¡S‹5ûŽú[ßù‹ïýàozú΅ŽTŸÑ±ñ—_=øü¿þw-­m¹|"ž8s‹&²ý#ƒ§C§€XMd±PqVfàT蔊n,²ã—fïjþ4S…F~it,qŒŽ@%éîíûî÷øœüMvüRè,@廒˷µþƋ/iÈÊKÿÙök3n'-®æ'G“±PqV¢ÂP\º±4zåՖÏü1ož¹ãÎe1„áÖrCï (ŠîÞŸŸõÒ+?iѐ1žÞêx#tnÉÌtaè|gè“€uQ…Ü„>•J7–:=}çº{û>ó‡M_‹ÞŸà³i‰3tŸÓg òŒyôø ßz©¥µ-t ®äò_{ýÅïþ¥»ËÂàùNOçI‰lº±(yuÅ¢K[›õÿËÍD+J†Û53]p3Tª¶öÃU±ywhø[ßù +˂·€ÁÕüäåÉLèó%°® (tcéÒÒÚ6:6~ë?þÓÙ҅aa2§ŠÞ (‰ëªCÒbvÅâÉ3]¡ƒp3—'3ìSñ2§BGž™éÂÈàéÐ)(>ÝXŠäò…#ǎßÖO¹ôÁ/et,q|f*›2 NWrùÿø£kå΂}*^b·NdûCG øtc)ÒÒúú•\þvVÇ[ï•" ‹1‘íÏfzB§JèÝ¡áïýà‡=}çBÒ¢­ýð_ýèÇö+&–ûT¶©÷G ¹‰Ð)nl4Ó­™š<º±ŽŸøæÑÛ›5Uøhh|yÑó°HÞ@Å»’Ë÷û?Œ³ªˆaXŒBnâÂَÐ)€’{ùՃ±™ZÕÊ'–OIR©²I]š8+áñXÝX*œ<ÓÕÝÛ·àŸ>}-:s.WÄ<EfðÔÕüdè@ɵµ~å'-¡Siq%—ùՃê±dº<™zçhèPdÙLÏÌt¢º^žÌxPatc•/—/,þ³Æ?¿›Ž~£(y(–™éÂàùÎÐ)€8Œyôžz ˆÓ˯Ž\1™†ÎwzFO…™ëá³e¬Uš(º±ÊwšãðèØøâ_çÍÓ¿Xü‹P\ÖÍ@zšÇ€˜¹{,™fŠ ý=6+R9®Í\-‹ÚiÔZE€Ê¢«pÙñKGŽ/ÊK\ú ;US”—¢ˆŒŽ@zŒyôž-g@l®äòê±dÍtû”$£\®ò*ä&ŠÞ €¢ÑUžC‡¯äòÅzµ¿ûÙèw}®X¯FQLdûGO‡NÄÄ%@@œfë±ìø¥ÐA˜¯·«5t(Ž2šÇÊ –Á|·H7VÉzúΜyŽ8Cc³Š Ï|PÄ€(ú϶_›¹:“–Ö×=§bs%—ÿ«ý8t æ+ä&.œíëj~r"[—Í*—7n…n¬’µŒÖVô×ì|{òƒhyÑ_–Ř™. Ù¬©á95³w‡†[Z‹ÿî’EÊ žºšŸ ¥Œ†Æ¢(š™.d3=¡SPº±Šu䨉w‡†KñÊ'{‹¶€‘b<ßéM€‡çÔ@ÌÚÚŸ<Ó:sÌLú{ÚC§€E)»I¬² À§ÑUŠ\ŸÐÒúz‰^Œw(Wø`e‰^œóŠR¥­ýpOß¹Ð)€yå'-º&ÍhŠ{rìBè°@Sï\žÌ„Nq{F3Ýnµš º±Êtšãð•\ §»:NŸWºgaŒ)€ŽyåՖЀ¹’Ëû¶“@œ]­žÔSŠÊt«Lc0n¬eÇ/µµ.é—.˜ª)é,@ÿY£c"£cã‡:ޝH‘îÞ>›“А›pÿ4eªŒ.».3x*tŠ`Iè_Ëk¥ÚŠøq'ßû£ß]ýчÓ1œÅ-º<™zçhÓý{B€8Ü׎®Šºú¶~Jwo_‰Â„ršãðÞGv×TW…€EKkÛ®ÛC§`ŽÁóÍ;—W׆·arìB!7:ÅB\žÌ\ÍOúŠ(wº±JÓÓwî­X>Ç7}-ú‡á·üV Gq†Îw6®ß¹déòÐAà6¬©¯ÛûÈîæŠ{?ù·¶nÞTІ/æòù(ŠzzÏEQ40tq`xž€+©KäJ.šãð§ö‡b¶toš_ýñ꜡®®¡~õ'póºuóšé\Ÿ00<üñ¿’»”Ÿýち‹ÙññѱñÏìÄê“O|1tæèíjÝŸûÙÐ)à6”éÐØ¬ÌÀ© >:‹¢«4qî?Ñ3ùÀoÕßÙlž 3Ӆ¡ó~‹@yiš«‹ù1kóº_÷p󺷞Ÿs=œçÊ«*;rìøÞGv7ÔÝàÁ=p»|yÿb*ùšêªù?}ó ~XvüRv|Œ§÷\vl|`øbÙµe&Vh"۟Íô44n nUYßÚ5šéöà ÜéÆ*Ê¡Ž7b~[u¬;÷…mwÅy"ŸÉ> X°­›7]®=0|ñ䙮“gºþØúJ.äØq£c·åé/é†sŠ†ºÕ u«¯·Éå =œ}³Ý|¿áÌ2±šLýgÛW5lŽD„²ÍôÌLB§XžBnbêý‘•÷¬ dáÖ4n»ûžÆÐ)hfАˆõÖ·ÆæK—–ë'BªjV…ŽPrw×6n|p_èÁ¬,Û¯åàtc•#—/ê8ó¡2ù]¿œ¶ê®©˜ÏåæìӀÅk^woóº{<µ¶$;rìxb'Étc·«¹éޭ넚©®Úµcûì%^åÒÊ9vüÉ'7:–(…Ü„%"”‹²›•<µùwþ tŠ…[»þ¡ÐnrìBÌÝØšÆmµõâ<‘Û²di•ÿ@,À¡P4‡:y^sè§¿ˆÿPnn"Û?9v!t š³ Ù÷¿ýÒWŸyzM}]è87p%—?rìDè@üã7œ?û“çŸ}lÏîÐq>Օ\þd,]s[Ïw^ÍO†NŸáÚÌÕ²ŸllVÔ{)§«ÙñKmíqÍš*|44niCâôvµ†Ž¥Šºjï#ÿÛöÕgž^QS:Î|=œ}¡#ÅŽkÇöçŸràßy)± ّcÇCGàŒ$ù*£Uš™.d3=¡S°pº± ñÊ«-O?úöØw. €O*ä&.œí*ÐÞGþþ·_Ú¿ïñÐAæxëLWvüRè@‘5Ô­žmÈ>¿c{è,óœ;4<0|1t æ›Èö žn&3ë6ŒÒ©Œ’ µtc•à䙮žŸ:w5`n(3xêڌÿ.P|5ÕUžÚÿ§ßøZ¢Èì7ƒJÕP·úëÏ?û'Ï?›šï9‘ѱ€ê?Ûî ‰u5?yy2:EqŒfº}­”/ÝX%him !úù…ÜLŽ"t 昙.ôŸm*ÖÖ͛Ÿÿí sôôž (¡];¶'ê{NE'Ïtåò…Ð)˜ofº0tŸ3t ž± žiì㌎”/ÝXÙkim"Š¢èÓÙИ/3pjêý‘Ð) bÕTW}ýùgrPwoŸ‡ÔPÙf¿ç<ýå/…òkWry«É4xŸÓ;A’)3P! gUÌ~H€ҍ•·\Ÿœ-#—>øå¯ŒŽ%ŽÑ1(µçŸr !õXOÐ=Û@<ž|â‹_}æé„ìWóNšz€›¢˜.Of®æ'C§`!tcå­¥õõ+¹|èÿ€ã­÷îŒës¡S0ÇD¶?›é *Üs_9„EgÃCGâ°÷‘‡¿þü³¡SD‘m® 6‘í<:ÌQ‘+l =tce¬§ïܛG“246kªðÑùÌ¡S0Ÿ«˜ Ï=óô}MëÂfðÒcëæM_}æéÐ)¢Ñ±q­|by'HÒTØec³*ò tceìPû¡#ÜÀß÷L~xgUèÌQÈMžŠJ­Šºê¹g„Ýröîåf"{y8 wiåkfºà ɑÍôijPqÛÎ?Œá”ë ¹ ×û”#ÝX¹:rìDw"Ÿ9— ‚ù2ƒ§¬À€Rk^wïÞG_<ÖÓç!5€È“O|qۖÍa3 hålð|§§ö$ÄÄX §Ü]Ûxwmc }\fÐZE€ò£+K¹|áPÇáÐ)>ÕÏ/䊣ߝ‚9fŠ ƒ>0¥wà©ýkêëÈ%é2Z _þÙ°«*ù„ë{»5tˆ¢ž.¿qyumUͪκ®"ïQšxº±²tšãðèØxè7óæé_„ŽÀ|™S“cB§€Êwà©ýOwñ€MMuՁ§BnVŒ’˫ǒìòdf蝣¡Sv#ƒ§gŠ 1ŽòžÆ(ŠV5lŒá¬ëfŠ ÙLOœ'°xº±ò“¿täØñÐ)>ÃÈ¥²S5¡S0_ÿÙöРòíÚ±=àèX.on Rgï#›Xå&†Îw^›¹:©6‘c¡bE³ cž‹ŒŽ”!ÝXùiyíõ+åðÆ£ãä{wܹ,t æž<™<:TŸ'Ÿx<ÔÑÙ±K¡Ž2±ÊMÌL|P’€®Í\¥:ªªYµŒº6Š¢Uõ±ÎEQ4šéÖ@”ÝX™éé;÷֙®Ð)nÉôµè‘C§`Ÿþ³í~»¥¶kÇöPGw÷ö…:h׎íÛ¶luº‰Õä³cŸ€2ƒ§â9èú*ŕ÷¬]º¬*žC¯3:P^tceŠåµ¶ÐnCçۓDËC§`Ž™éÂÐùÎÐ) ÂÕTW}>\=€SÀVÞÄjY0:F(±•F_¥8{ñXœb«( ÝX99rìÄ»CáSܞ“œ>?˜8ƒç;¯æ'C§€ ·5ܐN»±á2{£šN—'3Cï ‚Ô¹šŸŒ<™‰ç¬¯RŒ;önìòdÆÃ€2¢+¹|¡¥õõÐ)n[ïP®ðÁÊÐ)˜¯¿Ç Ž¶nÙ:.5ÕUíÙäè+¹|._rt¹ˆœÛ ïŽcŸ˜ebšŠZº¬jå=k¯ÿéõýŠqŠçZ5ŠB7V6uŸ’+Ë¬Ž“ï…ŽÀ|£™n»æ €êV¯©¯ rŽ'ԐZ[7k华Ý\ãú¡#DQÍLúºZC§ ]b«‹>>4EQmý†xÎýžØŠ@O7V²ã—ÚÚ‡N±@—.8òK£c‰Óë”Xóº{ƒœë 5€–m®‰d„å†|P’8Mœ?RÈMÄsÖ'¿ÊÖ4n‹çèë ¹‰©÷Gb>€…э•‡W^m aQÞ<=rǝËB§`ŽBn®y(©†@sc@jÕTWÝ׎.t n¬±9£c‘J£lŒ;?ٍ­¬ûʱ(ÞdC7VzúÎu÷ö…N±(Ó×¢þ0t æ³kJªŠº:t uB]v80t1ȹedý†Žðk…Üą³¡S ™Á˜v VÕ¬Z^];ï/ÎÛ²Øþ‘X$ÝX(÷¡±Y'z&?ˆ–‡NÁ3Ӆ¡ó¡S@Åjn ³SH³†ºP7–åõØqZ^]›œÑ±Ìà©«ùÉÐ)špÙLÏÌtLw Þp}âÊ{Ö.]VO€ëfŠ ÙLȮ°º±€;ÔñÆèØxèÅq¬;:ó žïôŽ*Ló:Õ œêW‡ŽÀ§JÎèØÌt¡¿§=t *ÜÄXlg­ŒçÆëb¿r,Š÷€Ӎ%Z._8Ôq8tŠ¢¹ÉÿòW+B§`>»æ DBMoÔTÇýi 9ŽãÉTÈMD ÍtOŽ]‚Šumæjf Ÿí‚ŸŒllÖݟҙ•Tfà” ,’O7–h‡:_ÉUÔbŠŽ·Þ ù&²ýæý êLoqӎ'Ól7}Êæ·P|P’ÒÉfºc;kUÃÆ%Ko|‹Ç§uf¥ç?> £K®á‹mí•346kªðÑО[ǧÿ¬eP!VÔT‡Žv_“ѱ䪭ßêaý'rÎv„NAešÈÆ·Wð&_SË«kï® 0:6ªH<ÝXrµŒÖ:BI}{ìŽ;—…NÁÞ@ŰN š©Бçòµò€€’sëXä jJãj~2Îrèæã˜«êŽÑÙ~_Y §Kš“gºº{ûB§(‰ékÑ©sÖ.'NfÐ:l(²ìø¥øµN "H!WŠ5:Ù¬H ÄYŒUÕ¬Z^]{“Ðh‘©Ñ1€„Ӎ%TKkeÍúù…ÜLŽ"t 昙.جŕÿІúºøà¶$jtÌÔ]œ·m}æ~+ïY[U³*ž0—8ÿ¡Ü:ÝXµŽ¶,"Öþ IDATŽx’§7NgCG`ŸÌÀ©É± ¡S‹ÒŒîÞИofŠðñ?MÚèXÿÙv{D(–«ùÉ˓™ØŽ»•±° _n…ÜÄÔû#ñŸ À-ҍ%NvüґcÇC§(¹‘Kd§jB§`ŸÁó¡#@åÈåÜŸÓÜäŸ1H;»Uš›˜÷W5:VÈM y3H‘Ä9/µtYÕÊ{Ö~æ råXïü·K7–8‡:_ ñ%~÷³Ñ;ïú\èÌ1‘í<:Tˆá‹1Ÿž¢Šº¡nu̇I“Ë>û›ûÆnWÒFÇÏw^ÍO†NA%ˆóž­[ŒK¬¡qëÒe>4ŽV ¹tcÉÒÓwîÍ£•?46kªðÑùÌ¡S0ßàùNË4 (²±oÉn^gh £¹ÉB×ۖšÑ±(Šz»ZCG ìMœ?òÉ)ÉÒ¹õ° £c3Ó—ù$–n,Yµ¿:B¬þŸgòÃ;­ûHË4 XâÝØºeSÌ'°`I›Èö{ŽÏ"Å<)ÕОõd𝵉±þ çð™tc r䨉îÞŸÐ)b5}-:s.:óeOYŠ‹”Ëâÿ­n ˆ¢(;÷Ðjdnu¡’6:Ö÷v«=",Fœ7l­¹µ…гnqûbÑeNùšH&ÝXRäò…C‡C§àçrÓÑo„NÁ3ӅþžöÐ) ŒõÄ^Œ­©¯k^g§ÆŸÐ5Š¢šjA"i£c3Ó{DX°lŠgf:Ÿ¡ùÛúÚY²tùmuiEg_À­Ó%Å¡ŽÃAÞÀ$Á91:ófº'Ç.„Ne¬§ï\Ì'îÚ±=恟ÿ¡Û¶lŽÿÐòrmæS ƒ€Ž žïœzߛt"Îh鲪µëº­Ÿª‡Ս$’n,²ã—ÚÚÓ846ëÒå³S5¡S0_ÿY£c°p=œqwc*Qe %ÒåȨ́ý­€ŽEÞ ² ×f®ÆY-`GâÚõ-]à›ÕD¶ßœ €K„–×^!°Ž“ïÝqç²Ð)˜ãòdfdðtèP–zúÎÅŒ`M}ÝÖͺ1 ÌÜXC}]ü‡V’€ŽMdûœävÅŒ9pUýBåP·ŽH ÝXx=}çÞ:Ó:E`Ó×¢wF> ‚ùú϶»3àdì¿»ÛûÈî˜O’i`(D7V§[”dŽŽy3Èm‰³þYº¬ª¡që~âµÅË œ r.7¡ ¯åµ¶Ð¡óíÉ¢å¡S0‡{˜`²ã—ލn,˜ Ÿ)NŸ©ÂG#¿4:–8FÇàVôô{ëLẆ>¹ï‹1Ÿ$ÓÉØ¿ÿÌ27VDM<ä2€›:ßymæjè$ZÌÛ¿qM µŠcñ]ÉÀgҍóÊ«-¡#$ԛ§GîžsYèÌQÈMøŽ Ü\._ø«ý8æC?¿cûÖ͞JQâ²ÃÈec·ãV.r^²tyš…oŸffºÐ¶=t -ÎËÆªjV­Œgí"_$ÔÝ~™Sšf€äЍ…ÑÓw®;Ä%ÉeaúZôÆNÁ|>-7÷W?úqüë²|ùK1Ÿ$ÓÉ3]ï Çî®Ûã?ŽLr·òÃ8:–8eÍ>ŸfrìÂ-þÚ.Š¢Œ|-¯®œ»¶qñ¯³1ÏØpº±0 Ý܉žÉ™hEèÌ13]:ß:$TKk[üŸ|Ú¿ïqãÀ¬–Ö¶ çî}dws+ؒ¥Ë7>ž/tŠùŒŽñi⋊7òj@3æ]܄n,€CoŒŽ‡N‘toœÎ†ŽÀ|ƒç;§Þ çȱñß#»ŠŸîÉ'ùP ™Ž;ä=æ¶-›5ô¥°výCU5«B§˜ãòdƚ}n(ÎAš»k—W×å¥iÙÂLdûoeœ*1ЍÅ-—/êˆûÑI9¹ôÁ/et,q|Zæ9rìÄ˯ŒÿÜçž9PS¬¥[@¹|¡¥õõ G[šX: ³fŸO<=3]ˆíž"{-YºŒ(ëÀè@BèÆâÖÒúzüQ”©Ž·Þ ù&²ýÙLOè¡Š±ýûߺySüç ôÊ«CœÇԍ•NCãÖU C§˜cfºÐ×Õ:É2‘íóžâ{…úså@BèÆb50|ñÍ£ÇC§(S…†Æ—‡NÁ|FÇ`VKk[b쟊u¶)³uŒñ֙® G?¶g·éՒZÿÀ£¡#Ì7šéž»:Iqmæjœ#Pk·-YZÌgDk×?ŽtY€ob—'3®«HÝX¬Z^ s=rù:úöØw. ‚9 ¹‰ g;B§€rùÂ÷~ð7ñß1EъšjہYÃnìWҗZmý†P;ßn¢×èÿ(æù§RÜêÖ1£cI ‹ÏÉ3]Ýœ}¡S”™ékÑ©sš'Nfð”ËcH­žŸs/~÷/BýŸîÀS_j^wo£DÉå ßûÁCmS|lÏÕAŽN•[wë˜ÏJr]fðTlg-]VÕОµè/ëÊ1€4ӍÅ$—/ŽŽ[ˆŸ_ÈMG¿:sÌLÏw†NqËå õ£÷û?`ÿŸÇ÷>òp£D [ŒE†Æâ²Œº6›}V’(Š®æ'/Ofb;®D^µõªjV•â•o®›p•;@pº±˜ê8êJxóô/BG`ŸÌÀ)‹æH•Co|ãŗBÝëEÑc{vxjšÓä˜-ÆÞàó;¶‹Mӏyv3Ӆþ·P§]̓Oëw–è•CŽMŒõ9€ëtcqȎ_:rìxèeläÒÙ©šÐ)˜Ïè)q䨉oŒøç_{=àˆÆ}Më<õ¥P§ÉŒ‹¢hïžÝO/_م< _²tùÆ·Yq4Óí³’)—ˆo¡bUͪ•÷¬-ы76—ªu»¹lŠûڌ;DBҍÅáPÇá€OR*Ãßýlôλ>:sLdûGO‡N¥’¿ÔÒÚöÿüåW†]p_ÓºoŸðµšêª€€$Ÿø_ [Œ=¶g÷Ö͛H¡†Æ­«6†N1_oWkè3õþH!7Ûq%íZ^]{wmcé^ÿÓÌL²njI蕯§ïܛG -ÖTá£ó™6þfèÌ5xŸ³¡qے¥ËC€b:yŠë䙮€ë?N1Ì:rìDKkÈÖ(ŠVÔT›a bãƒûNe:Å…Üą³|"tˆ¹Ô)õhWCã¶8ïN»n"Û¿výCñŸ À,ÝXÉj#t„ ñ÷=“Í¿YWdä_A¡èÆJëȱÝœ}¡STˆékÑÉÞüÃ[,Mo‡ø€“gº†.†NQö²ã!žAJäò…áážÞsCø{¶Çöì>ðԗ<††”;yŠ«¥µ-ìf×YÛ¶lÞµc{èéÕôÀ£™ÁS3ӅÐAæèíjÝŸûÙÐ)ˆU6ÓçBÅÆõ%¿lÉÒåk·ÅYø]7šénºOüçéÆJ*—/ŽŽŸ:EEéÊm`mÕ]S¡ƒ0GOû֝O‡NA‚ŒŽ'áñ À' _Ìåó=œçrùüÀÐŰwöÜÜc{v?÷•¡ST¬“gºzzυNŸ†ººœ<:·m`øbËkm iîWÔT?÷ŒoJ!-YºŒéGƒL·ÜÄD¶?›éihÜ:ñ™ëóž†R^6vݪ†Aº±¬n ŠavÍo豲ī(tc%tšãpròTŒŽ“ïýÁÃ5¡S0ÇhŠ»qlgmý†ÐA(WÙññ#ÇN4Ô¯þäßj^·îV§²ã—æM[ ]ÌåóQåòùìØ¥ìx9Õö_}æiMFI¥í>àm[6ûU^²ã—uNÔ/ÔO}©¡îߥ‰SÓý{²™î #ÝDÿÙöU ÝB×f®ÆyÙØšž.8_»þ¡þ³íñÏe^žÌLœ?²òžµ1Ÿ А›HÚÚáRӍ…n¬T²ã—ÚÚ‡NQ.]þ0;UÓ°2:sôŸmè :åjtlüåW†N‘+jª¿ùÂך×Ý:FOß¹#G'áj±{lÏnõjBl|pßÏ~úJèsž…:U²™î8 €x†Æ®Ÿ•8Ûq×e3ݺ1€ tc¥ÒòšmŠ¥Òqòœ?úÝÕ}8:ÿäòdfdðôÚõ…elۖÍ_þYŒA eÇ/<ÓuòLWwœÞ׮Ί×äš­ßÐØŒ3Èü›p uzLdã[šžtYUœë:×êÆF3ݪe€ tc%ÑÓw.iô«$Ó×¢þpËo…ÎÁ\ýgÛâZwfEMõ“O<þä_ ˆUvüRO﹓gºr©Ø'­š©þúóφNÁÜóìέèíjÝŸ;Ì/••÷497…®Í\óR®8‡Æ¢(ª­ßPU³ª›ˆóÐ(Š ¹ —ö¡+‰–×ÚBGšp'z&ø­ú»¢«¡ƒðOfŠ 6iÀlÛ²ù¹gžÈRb¶îé=—ü{¿þü³Ÿ;%͒¥Ë›xŽ¿§=t9&²ý¡žï/]fÞ:&™ÁXǪ×ïŒóž(ŠÖ4n reÑÄX¿n ~º±â;ÔñF÷`Tžcݹ/l»+t æ°In˚úºOíßµc{è À¯ ]Œ¢hëæME{Áዹ|~`è×ÿ;0<|%—/֋—ÚWŸyºˆÿ*(¢Šû÷d3ݗ'3¡ƒÌÑ÷v몆V‰T°lŒCcU5«â¿…«±ygn,›éÞøà>_;1ӍY._8Ôq8tŠTžÉïúíµUwM…Â7i@YQSœ÷‘ÝžÚ:0ÇÁOÜ}_ÓºšêêþàæŠ{¯ÿqvl<—ÿ§w¹|ŸÜ?1ùÕgžÞûÈáSð©6>žïg?}%tŠ9¬©lWó“qÖ±kâ]š8kyuíݵñ·Î3ӅlŠÛ î1ӍÙ¡ŽÃeô1Àrwè§¿ø®‚9&²ý“cjë7„ 5ۊ=ùÄã5Õv@AžIŕØKÂO1V 33ÅŒ!¬¶~CcóÎÌ@¬;î>ÓàùΆÆmñûƒ˜±56ÇœPqVCã¶ ™Ù~Ý@Ìî  ¢dÇ/µµ‹ÏTᣑ_® ‚ùz»ZCG€$ZQSœßãßÿöKžÚ¯K1V"…ÜDq_pãƒûxÕVÿÙd]„F±ŒÆžPñîÚÆP—5ÄÉÙ¬ÑL÷Õüd£RK7VL¯ŒÚ:BêŒyzäŽ;—…NÁ…ÜÄÐ;GC§€Ù¶eóWŸyúGÿáßkŀ„SŒ•‘%K—7=ðhèóMdûGO‡NA‘Mœ?Rôr÷&BTQ-Yº<È:Ç(Þö€ÈNÅ":yŠ«‚Wj$ÖôµèÔ¹«ݯåM–¡óëwºH€”›]Ÿž÷‘Ý u«Cgø +jª¿þü³[7o „ÛÐtÿžlŠ;È ž›è?ÛÞОÍûÁJ’·¶iÔNÍZÕ°1HM•Ít7Ý¿'þsRK£P4-­m¡#€ÔÏ/äf"·Ž%ËÌtÁ& ˆ¢(—ÏŸ<Ó50|1t€›YS_÷ÍŸŠ+GÜ:Â|3Ӆ¡ó¡SPL™Áø.[ºX]»þ¡ ÛJ/OfŠÞ‰ÿ\€Ô27V-­m£cã¡S€×§³¿÷Puè̑8Õž~§K˜H³+¹ü›GÏþñŠšê­›757­Ûµc»12 QîkZ÷ÍŸfãk™ª­ßÐØŒ33_uq+Ïw64nó~°2d3=3Ӆ؎ ;4v=C¯©lŠÛW @l̍A._8rìxè©6réƒ_þÊèXâ€ë®äòoé:øÚë/|륿û—‡:ÞȎ_  Ú¿ïñoÿé¿QŒ•µî 2ærs}o·†Ž@qLŒõÇvÖÒeU [c;îÓžr tcEÐÒúú•\>tŠŽëxëœÐ˜o"۟Íô„N‰óîÐðõ’ìȱ¡ã)µŠŸîO¿ñµOí„ÅZ²tyӏ†N1ßåÉÌÐ;GC§`±®Í\s‚* CcQÕÖošªYÿ¹…Ü„§(±Ñ-ÖÀðÅë«rhªðÑО›~§ÿlûµ™«¡S@Bœ;4üò«Ÿÿ×ÿ®¥µÍ§ÏïØþí?ý·.«M÷ï¹»¶1tŠù†Îwz?Xî²ñN25®ßçq7jt,Î)=€”Ӎ-VËkm¡#ðkGßûðÎÄí‘H¹BnÂ%ÌpsWrù¶öÃ/|ë¥W~Ò¢!JmEMõŸ<ÿìןÖÅ ³ñÁ}¡#Ì73]°i¿ÜMdã«jªjV%ç¶­Ææ0-]6Ó­Qˆ‡nlQŽ;ÑÝÛ:¿6}-:s.wגυ™ÁSWó“¡S@xóèñŸõRKk[.ߍ÷@ªìß÷ø÷¿ýÒ®ÛC¡øjë7„zš™S“cB§`®æ'ãŒ+ÔšÖ -¯® 2‹93]ˆyV µ–„PÞúúý/Y 5üζǖU¯„9þkÇùœ§Ÿ:”‡¶öÃGŽßûÈn—EŽmËæçž9ÐP·:tJhãƒû²™î™éd}À¢ÿlûC_øãÐ)Xˆ8‹±(ÜšÖ§ihÜvy2ÿ¹ÙþµëŠÿ\€ŽÑ-Êæ~úV|W’ò™>ÿÏÿÙ=ëÿ›Ð)˜£íµÿ·¥ã­Í;ö4¯»7t(³[{zÏ=÷Ìÿ ,ҚúºOí7+–K–.ozàÑþžd­1Œ<™zçhÓý{JôúµõJôÊÄ9ÀtwmãòêÚØŽ»ëwùjÍtoÌïKÚ¿ €Êc§â¢ì}äám[6‡NÁ¯5Ô­þâî]¡S0G._8ôw'"7óÀí{whø[ßù‹–Vÿ ,ж-›ÿô_ûþ·ÿL1–M÷ï ²îæ†ÎwºB©ì\ÍOÆ95Õž>YCcQ-Yº<Ԛǘ'öÒI7¶XOîûbèüÚ>ùÄÒꕡS0G[Ëÿ•ûÕLEÝœ}'Ït…Žå§­ýð‹ßýK7·e¶ûæ ŒuóŠÐYˆÛÆ÷…Ž0ßÌt¡¯«5t nOf Ö=I IºlìºU ƒœëÊ1€èÆkëæMíÙ:ÑÖ͛v~þ¿ ‚9²ã—ì¹þ§>ö óîÐð‹ßý‹á‹¡ƒI·¢Šú±=»¿ó­«K³Úú I»·)Š¢ÑL÷ä˜+ÛËIœ£Kk·-Yº<¶ãnÝÚõ-]Vÿ¹—'3Wó“ñŸ *º±"xò‰ÇWÔT‡N‘vÿóïï ù^þ?ÿÿéèØžz ftlü{?øá‘c'BjۖÍ_}æéý‡ÿÜWÜSHŽñÁ}Aèß\¯Ñ±ò1õþH!7ÛqÉ›*[Ìs{)€+‚†ºÕ{1:Òïý÷4ÞÿÛ¡S0G÷Û?빘÷;ž¿$”»+¹ü˯Tw_Óº§¿ü¥|ç¥oŸðÇ{y8t’bÉÒåM<:Å|…Üą³¡SpK2ƒñ3K—U54nížÛåÊ1€Jµ$t€ qà©ý'ÏtŽ‡’F5ÕUÿbÿÿ:óœrðÿùä_Œ’Ëê8üÜWğ*Ã˯Œ¢ÈpH¹ÏïØŸuËæ­[65Ô­…„jºO6Ó}y2:È™ÁSÍ;—W׆ÂgˆóŸ«$EQT[¿¡ªfUœSt³ ¹‰É± µõb> =̍́§ö‡ŽRÿò÷Ÿø\õŠÐ)˜ãàßþ$ûþ•þ­7ïé;sš$/¿zКbH¡m[6ïß÷øŸ<ÿìßþ§¿þúóÏî}äaÅ7·ñÁ}¡#Ì73]èïi‚ϐÍôÌLb;®q}â®Ç›Çè@E27V4»vlß¶eswo_è éÒP·ú‹=:säò…#o¹É8Ôþ†‹Á`1ÚÚG>›•uÍM÷6ÔÕmݲÉb`êýžGžjë746ïLÚ­E£™îƱŠa’,Ρ±ªšU+ïYÛq ÓØŒsð|güçf3ݛçâ? %tcÅtàËû»¿£‹Õ¿ú—~—8ÿó+¹_ÍÜät÷ö9vÂ2(XŒ¶öà uuþÿ*Úúº†ººæŠ{£(ÚºeSMuµ2¬òÄ9ˆsÝÆ÷e3ÝAŽŸ‰Þ®Ö‡÷ ‚»6s5Îq¥P#Y·eyuíݵño(™.Œ ž^»þ¡˜ÏH ÝX15¯»÷±=»ß—ÏgÇ.åòùw‡†‹xP(-­¯77Ýë:T†¯?ÿ¬ßStK–.ozàÑ€­1,ä&.œíØðࡃpqEQÔØœô…г·¹œo"Û¯(ÝX‘xêK'Ït]ÉåCI…ÿåúýИïàÿýŸoå‡]ùÿÙ»ßàªïûNôDZ$ëœ.úw”"£?FRÒšÄÆ5ØŠÔÆÝÔò ÛÞkZ÷ÁvœfîŽ3u;³¹3nwгsÓÍv:œÙnsí¢Ýfí"¶3ø˜MŒöÚîØîØ2®ùã•g2ž6G"À&÷œqDˆqôûüÎ9¯×#ۑÎ÷aŒŽÞ¿Ïç[œÛ÷ì› *ÕÖMÖ¯ŒNQö^zå5[P=ò¹ÜR¬ÛýÑÒèÇ_föí™ÙÙ÷;³§Þ,ÇÍØŠsÿòOþô‰ÇםC7ëáÛßЩù\.:×qæììWŸúõßûí„ ÔqÏŠ™éÃ!?ÖÿÓ'_îèÙ\S[„«%94vgC[}®!±ãnE[ç}!ó™éܗÇýNvgC[ ¯Ø$ýtc%–ÏeG‡‡ö<œ7:HåûåÏ~Šå®Îè,ðâ Ï9}æ?xjÿ-7øY^EZ¢ŸqW›#G¯?‚ ܊BsS¡¹éGÿ{uâô›GŽŸ™=rôø™³³Ùn܅âÜî''ý<ýfuu¬òGisøè±ÉgŠ<=ÆRè^;òêٝbË—æ_ÿoûKu—R6ß8_ okmiŽNQáò¹ìƒÛ~>: çæ'ÿfßM}Ê€€4éj_5:Œm×ç'ŸüÄ¿ø“?üÒÃ;¶ßÝÑêú=¶ïÙoE§J`jÿCÏœ‚ Ôв:…›ëŠOŒ|þì?”䥲ùƒŒ w?…ržlì‡ Ý!ç&Œå zèÆ–Ä®Ñ*ÜCߑ[‚Šþæé™,ÞÔ§ŒøÊkGŽ™Œ  ÍM£Ã۞xüwþí—ÿø×w>œò’lÏÓ{Oœ~3:P“Ïøí̒è^;R[—º íN~÷ÛÑX Éеm ŒV®ìŒ7ä7Ñ»ç§/ΝOþ\€Š§[ýœkúz£ST¬BsÓ¶­[£S°ÀÌìۇ^zuŸ8ùôTÉÃ@ åsÙ-xâñßù“?üÒØÈв|JïmÚýädtšñ·þí—ÿ8pȅâÜWŸúõâÜ|T*UMm} ïb97óú['ÿ.:x’Œ—®Œ†ÆÞ•yúÄË!çT6ÝØR1:¶tŸðkŸ¶©3õÍ_ŒxiŸøÆ©ÓÖ@P ÍMãc_~"¥ ™?R¡Tò¹l컹3gg¿òÕ¯ R­ìŒ7j)ÜG8ùÝo_¹|1:™L²CcµuÙB[bǕJkP7rÏ@ÅӍ-•BsÓØÈPtŠ Ô߻ЫÇL^º9vüÐkGýéûž=àÁXÊE>—MmCæT(•þÞ5±ïæ=6ùŒý ”^ GÇæ‹çNÙ¬˜I0å84–ÉdZV‡\n7_ù²ë”?ûóÅs‰×Öy_bg•Rˆ–_ IDAT–Ñ1€Š¡ù\vb|{tŠŠòÏþé/-k*D§`ƒž˜¹Õ·1SûÌÌŸ]’<˜÷²Ç¿ø[W]Å©PB»vNÄ>ì8ùÌÞ§ß @EêèÙ\[—N±ÀåKó'ŽEK²zÉæ—¯X™Øq¥ÕÖÓê%¹ñ JèÆ–Ö–ÜÝѝ¢BäsÙ­ÊõÁ¢JUœ›ŸÜû·%y©ÝON–äu aýœkžxüw·nÚäFÇ T ÍM»>yñ؅âÜWŸúu»R)­šÚúnVœ>ñ²•q±’¬^¢F¯J¢>×pgC[òç^Ÿ4ÿÖÉ¿Kþ\€ Š;Æ¢#TˆßxhŒ.·<: L}s²øœË%y©ÃG9vŒ$/ Ëç²»>?ñðŽT, xé•×ü$JeýºÁØæûÌÙÙÝOî @EZÙyoc¡;:ÅÕ^ÿoû£#T¯·NþÝåKÉ}ó5zU*Q—¥›y=ä\€J¥ýœkî_7¢ìuµ¯ºïþŸ‹NÁ3³oï{þÕŸ Ñ1ÊÚèð¶/<úHøu³nƒÒšß»7õÅW^›|f*0)…£c^ôXLmmº¶D–$K—;Úês ‰·¯»rùbÈÑI7–„‰ÛÃJRî~ósFGàj{Ÿñ¥}Á3ggœí ¬­_7ø{¿ý[áßøzîùØPIò¹ìc>›ajÿ—^y-6fùŠ•=›£S\íäw¿œžýgó%S=®\Ÿ˜äecmå=4–Édês QõØôɗCΚHº±$š›¶lLËåhýºÁöžOD§`ÃÿêKÇO•üe=÷Œ5P”µ®öU±e2™ Å9?F‡êj_562›a÷S“'N¿› Óѳ¹¶.]ãVóÅs§ŸûíèU'ɛÆ2q K+j+i¿X•M7–Ñá¡ØEå+ŸË>²ã³Ñ)žÚî¿úKñ²Šs“Ïì]ŠW€Ä¬_7øë;ŽÍàO(­‰ñ±ŸÞÀŠs»Ÿœô%TS[ŸÂ͊Ó'_¶5.aIŽ"µ¶ ÔÔÖ'vÜÒ)Ž „TËŸ8w>ùs*’n,!ù\vt8øIÃ2µã?³Œ¹5: L=ý͙,.ыüÎó‰ ÜmÙø@ì”ÉÁïņ{,úBÁ7NÞýäžÀTž•÷F¿ü$—/ÍKÒŹóNìžÊËd25µõQÿ_ŠOX«Pº±älÙø@쓆åšÐÜŽmÃúè,Pœ›ß÷íÿº€GL>íÖ1Ê^øÚk¡Žò¹løÆÔ_yÍœ”V GÇN~÷Û&c“äMcµuÙB[bÇ-µÆ–˜^9É_2€ÊŠKÔèȶèeæ×Æ>S›[‚Š&¿QŒxiI8|ô˜çPîò¹ìc>àÄéӁ§CEZ¿n0üⱩý,M¥„–¯XÙÙ³9:ÅÕNKJ’CH34öŸB[6ߘü¹óÅsçÏþCòçTÝX¢ú{×lÝŽ!:EÙèï]3žþè,03ûöŸ—Ž$pÐä3S6APîºÚW~ïçAX £ÃCwwŽÇføÊW¿>3ûvl*IGÏæ›“>Âô‰—Ž%àœwޚ/žKìž¶Îû;+­AmŸÑ1€’Ѝ%mb|{ì’ú2òŸ{0:WûڟÿY29;»ïÙɜK'ðÆÙ Å9WxBÉåsÙ];ƒ7+^(Î}å«_÷$¥RS[ŸÂ͊G_{&:Bå›I°bÉæ—¯X™ØqɈš„Kò ‚郖Ïe·l4:v}¿ðó[îêŒNÁ/Ÿðü‘7g;îÐsÏ{€rWhn2:Š«}ÕÃ;¶ÇfxãÔéÉgöÆf ’¬ìŒ·±syÒOrnæu‹ã–Z’ãGQ#VKjùŠ•w6Ž%îåKóoü»äÏš0º±ãc±³§_>—ý•±_ŒNÁÕ&÷þ§$»Pœ3:@›9;u4T¶Ñám÷¯ŒÍpð;Ïzî…Ø T’ŽŽÝø­ci+öÊÂÌô‘D*vUÚBÅ÷EŽ›y=ä\€J¢‹11>!ÕzpøŽÜ²è,°ç¯žšyçB‡üÎón Üš›¢~†n§",];ߖÿµ'÷ømN©,_±²³gstŠÎÍŒ>3Äu×ÕéÜÙäʕ;Úês ‰—€À+Ç®\Ÿr4@Åš‰P¥Ö¯èë=|ôXt4*47mÛº5: çæœôjÈѓOO=ñøï„ ¥Òß×ûbÄzÃ3gg‹sóù\6ù£¡âåsÙÇ}䏟ü§±1ŸòÕ¯?ñøïúmNItôlž>ùòåK)ºÊîõÿ¶¿Ð֝¢]¹|1É;«Þ=?}ð™Ç;®JLŸ|¹ãžMÑ)ʘ¹±0á8§Öo>ôKÑžÚž¿Ü]Œx)äè7N¶+€r·>n÷ډӧ£Ž†Š×ß»fl$liêû̝ÝýäžØ TŒšÚúŽmVœ/žs¯ÒR˜™>œª”EH²ÝšHº±0…æŠð÷Q)Ôß»Šï“ŸŠNÁGŽ?ô÷‘‹ 'ŸÙ[œó];e,ŸËôõ†}â”}k°„&ÆÇîîhÍðâ+¯M>3›Š±²óÞŽÝÝuò»ß¶;®äÜVUÞ=?}qî|t €2Š‹4:<Ÿ¡>m~ëWŠŽÀÕŠþz26À…âÜŸgÄf€[ÔÕ±*äÜâÜ\ȹP=víœ[7µÿ€kz)•ŽŽúî·£ST”+—/ž1rTŠOŒ ŒéÆ"åsÙÑa£cúåÏ~æÎŠ–è,pðàÁ#ÿ}6:Efjÿ™Ù·£SÀâuµëÆ 2uµ¯JÃÛº¯|õëv-PËW¬ììٝbé“/+¡é“ • ¡ãžº±`£ÃÛZ[š£S€B>—ÝöO¢S°@qn>=[“O‹Wú–o欇K`ɍo»?îZÁ÷](Î}å«_Í@ÅèèÙ\[—Nñ¡Ë—捎•{ª*Æ|ñÜ{ \éÆâíÚ9!zpž.·<: LýÍÓ3ÿXŒNñ_yÍ¢ÊWÔܐŒ];êñðÑc.£$jjëÓ¶Yñ£GÇZV'Ь]œ;ÿîùé蔌)@€EӍÅëï]þŒažBsÓ¶­[£S°ÀÌìۇ^z5:Å»Ÿ Ÿù nÅ@_oò‡ž8}:ùC¡ åsÙ4<õèâ1Jee眍…îè2:V*nšª0ŠM7– ;¶GGö…_‹ÉUö|ã/Š/E§XàÌÙÙ}Ï~+:”“ E÷ABú{׌žxŒÊQ^£cÜ 7TU˜Ë—ægŠD§(Kº±T(47¥áMT”õë»z£æ#9vü¥ã§¢S\ßgx«@:MŒÝÝÑ›ÁÅc”Êò+;{6G§øÑ±[÷Þ;oÍÏE§ ÄŒŽ,Žn,-F‡‡–åsÑ)bìúå£#pµ=O=áÚ.çö={ :\Ûc>þÎÎÅc”JGÏæÚºltŠüî·/͏NQƔ(éÌôa#•‹ K‹|.;1^›ÿÙ?ÝŸ¬©‚"óƩӟmæÖÕç:{6G§øÑ±Ežrùâô £E•̯/ÀÍҍ¥ÎèðPøÕÍÉøÍÏ=«}íÏÿ,::svÖû|ž®j[Ù éÑÕŸjld(:…‹Ç(ŽžÍÙ|ctйuìf¹ªâñK p“tc©ShnÚ²±òGǶl| œçÑ)Xàðß¿zä͙è7áÐsÏçlK lÌÌÎ&h>W]A:MŒ ôõF§pñ%PS[ßœv$:ҌŽÝ¬s3*Vžùâ¹÷Þy+:@9э¥ÑèðPønú%•Ïeٝ‚«íÞó×Ñn΅âÜä3{£SÀ:s6 bíÚ9ŸÄÅc”D¡­?Uwzœ~dt„²qq¢j0}ÒZE€› K£|.;:¿|cé<ôàðòæÖè,0õô7gÞ¹âŠüÎóGŽN×wâô›!çvu¬ 9x_¡¹i×ç'¢SdÞ8uz÷S“Ñ)({}ƒãÑ>tfúðù³ÿ¢<(ƪ„Í™7E7–R[6>†åK¡ÐÜŽùçî‹NÁŹù}ßþ¯Ñ)ißþoEG€ë+ÎÍEGb¬_7žuSüÚüƒßyþÐs/D§ ŒÕç:{6G§øÐÞ:–ªëÐÒFeR%._šŸ™> lèÆÒkbÇXt„%ñ›ýRmnyt ˜šüFñâ¥è‹tøè1oòH¿#Gc ͕Œ©ÊÅÄøö»;Ú£Sd&ŸÙ5ÃJÅèèٜžêÜÌë?«­ÍƆI­‹sçß=?‚„èAnœn,œºÚW¥áéÂÒêï]Ó÷ÉOE§`§ßÜ÷Ry?XŽïÙŹùèðQNœŠùyt¡¥)ä\àGåsÙ];ã7+^(Îí~rÒwÎ܊šÚúîµ#Ñ)>ô££c\Óô wPU‘3Ӈ¯\Ÿ <èÆRmb|{øœÍ¥õŸ{0:WÛóáV9;»ïÙÑ)ࣜ8}:äÜþÞ5!çWéj_õðŽíÑ)2oœ:=ùÌÞè”·B[c¡;:Å~ttŒkrÙXµ1:pƒtc©–Ïe·l¬œÑ±_øù-wuF§`_xþț3Ñ)JàÐsÏÏÌŸ®íÄé7/îkm±PRdtx[n•vñ·®op<:‡ŒŽ}„÷ÞykŸx.:‰š>iRà†èÆÒnb|¬2~š‘Ïeeì£SpµÉœÿ):Bi\(ÎM>íXRê¥W^ 9·«}UȹÀOòØ£€a5ˆ‹ÇžEõ¹†ÎžÍÑ)>`tì#šIªÐ»ç§/͏NPtce ‹éoÝCߑ[‚öüÕS3ï\ˆNQ2/ŸòڑcÇ£SÀ5Duc…ŠxÄ *I>—Ýõùø÷w.ãÖuôlÎæ£S|àäw¿ž5©bœ^urÉÀÐ•þÞ5iØŒq+ ÍMÛ¶nNÁ3³ozéÕè%6ùôTtžÚ‰Óož9;rtŸËÆ uÖ¯ŠNáâ1nUMm}÷ڑè87óú¹™×£S€ÎÌô‘Ë—TàÕÈ%s7B7VÊ}tì ÿÛÃÑžÚÔ_ï)^Œ¢ÄÞ8uÚÝ €Í¡çž:º¿W7i4:—ݵs" }íÉ=.ãVô ŽGGø€©«\¹|ÑðP5Ó\—n¬lŒ¥áœÓ"<ö«¿«MýÇÿa©\(Îí{ö@t ø@àŸJ*Bšuµ¯NÅã_ùê×=[Æ¢Õç:{6G§à U9ÿ\WMtnT>—Úót™m„ÿåÏ~fYS!: RhëOþh€ran¬œŒo+¯Ý8ù\vtÛ?‰NÁŹùj«ÚýädtÈL>öTÓ²|®«}UÔéÀ Úµóá4lyñ•×ö=û­è”«šÚúîµ#Ñ)XàâÜùs3¯'ybkÛ@’Ç•‘À;ùŒŽ|4ÝX™™Ø1á&<ôàp]nyt ˜úæäÌ?£S,¹ÃG9V™ªP.Ž;nh øhù\6%[{žÞëâ1­ÐÖXðã’T*èÆ~‚À¯Ì™éÃW._Œ: ýtceŠ¿wÍýeò“Ž®öUÛ¶nNÁ3³oï{þÕè 1:@ âÜ|ìŸDýœ.ƒòÐß»flÄÅc”œŸÁñè|(ၡֶšÚú$O,#5µõCuFÇ>‚n¬üLìØá†üúçÊiÄ­JìùÆ_DGHΙ³³6Ãeò™œgÎÎFŸ,Ÿ37edb|, Ëóß¿x,:åª>×ÐÙ³9:™L&óÞ;oœ{~:ÉM ~ŽÀѱé“/G ~º±òShnJÉs…aýºÁ®žÞè,päØñ—ŽŸŠN‘š}Ïðè+É;ôÜ Û3™Ì–Oá±Gqñ宣gs6ߝ‚€G…jë²*~ŽB[m]6äèwÏO_œ;r4@úéÆÊÒèðPÞ8}„Gv|6:WÛóÔSÑ’v¡8·ïÙÑ)š.GŽÿZôà…n ÊN¡¹ib< Bö<œ×Åœ,NMm}÷ڑè$}ÙXÁBÅ{ëXÔÑ)§+Kù\6%oœ®éŸýÓí˛[£S°ÀÁƒOÌTã³BSûžT€Äœ8ýæWŸúõØ }œ…æŠØ À"lÙø@Jî–vñ‹Vhë·^/Öù³ÿ0_<—䉍-~ů/ð«4}ÂZE€kӍ•«-èKãÒÂBsÓ¶ ë£S°@qn~rïßF§3ùôTtªÂ‰ÓoþË?ùÓ Å¹Ønƒòµkçí-ÍÑ)2Šsá5?å«op<:BUKxHš¶.[hëOòÄ2žVqŸxîœwÞ 9 åtceltd[t„kø_G‡ksË£S°ÀÔä7Šß»"Ìá£Ç^zåµèTž”c­-Í[6>›XŽ|.»kçDtŠL&“9|ôØä3ž0c1ês =›£ST¯„/sÓØ üZ%üo@¹Ð•±þÞ5[7¥ë2‰þÞ5÷ÝÿsÑ)X`föí}/‰NÌ{–Ô¡ç^HC1–ÉdF‡‡¢#·€¿wÍØH*~#Oí?àâ1§£gs6ߝ¢œuòï._Jt!j«n솵uÞuôôIk®A7VÞF‡‡–åsÑ)>Žó³[¢#pµ¯ýùŸEGˆwæì¬z €¥Pœ›ßýÔäמܓ†b¬µ¥ÙBEšãcwwŽG§Èd\<ÆbÕÔÖw¯‰NQÎÍŒžäqÙ|cCËê$O,kËW¬ŒêŒ/_šŸ™®ögŠ~œn¬Œš›¶lLËèØ/üüÆöžOD§`Ãÿê‘7g¢S€Â¡çžŸ™};:åý=Š¿ó|tŒås1WY¥õØ£€á!H±h…¶þÆBwtŠêråòń/34v³¿bçÎ&ڛ”ÝXÙJÃuÍù\ö—¶Y)ž:»÷üut„ŽžPœÛ÷ìèTˆâÜüä3S¿ÿ‡üÆ©ÓÑY>àŠ1š$…æŠ]Ÿwñå­op<:BuIþN)—Ý¬À¯Øô‰—¯\Ÿu:@:éÆÊ^>—‹N‘yèÁáåÍ­Ñ)X`êéoÎŒs!:EŠüÎó®LàÖzî…/þÁ—Šö§ë‘‹4|C”Ðúuƒ)¹^zjÿ—^y-:å§>×ÐÙã Úä$|§T6ßž|ÅÊ$O¬k3í)@ÊéÆ*Áúuƒ}œ ÍMÛ¶n À+ÎÍïûÏ/D§H}û¿€2v蹟øÿgJnûQ}œnƒÊ31Ÿ= ;B2™Ìî§&í'gV¯lªÊŹóNòD §­ëŸš£^¹ ~º± 1±#òIáß|è—Oçšöü»¯¿w9:Eê>zìÐs*CnÎûßoÅ̝Žs ±ß K$ŸË>öè#Ñ)2q lVLFòµG`ÇSÖ"¯›yýâÜùšÓRH7V!ºÚWE-Üèï]Ó÷ÉO…ÍOrâô›‡þ¿ïF§H©}Ï(ÎÍG§  çæ=÷ÂWŸúõßøâïNí?ÎV,“ÉŒ uµ¯ŠN,‰®öUc#CÑ)2™LæS§]<Æ"4ެ6`”€é‰.TŒ³¡­>א䉣>×pgC[ÔéFÇ~TMtJfb|ûK¯Œ–ü†ŸßøÜƒ ŸÈuíùþ2:Bz9;»ïÙ.eà'™™}ûÈÑã'NŸùÎêfÝÝÑîµE8qêÍè‘ú{×DGà&LŒ8õæá£Ç¢ƒdŠöèj_eƒ+7«»äÜÙ×/_ò„âRyæ‹ç’<± ïŒ…¶„`þÐô‰—;îÙr4,©+—çϟý‡èa–¯h«©­NQ–tc•#ŸËŽíyzo’‡þÂÏol¹«3ɹ®_xþÈé3Ñ)Rmjÿ-7š›¢ƒð™Ùٗ^y-ŸÏEýÈþȱã3gß>qúô‘£ÇS;vM»vNDG(K Ϝ6õÿ›èܜÇ}ä‹ð¥4Žõ»Ÿšìêh÷47¥>×ÐÖyßÉï~;:HŚI|È,à­hmxýÈþ£ç‹çÞ{ç­å+V†œKçÝóÓ¯þ—ÝÑ)Âüìÿ²«¡eut∫(£ÃÛ=÷|b?ÐÉ粿2ö‹ÉœÅ *ÎÍOþÍŸèe`òéœ)¹Œ€L&sæìì¿þŸ7Ù,ËçºÚÛ3™LWÇ{ûû>(Ìò¹Ü-.œ™}{fv6“Éœ8õfqnîÄ©7gfgË« ûQïØn›"Tƒ|.»ëóÿ:7~œñ؏ÿNtÊÌêµÃgŠ'<ÛT=^”g¡â-ªÏ5޶ D­7œ™>¬xŸn¬ÒìÚ9ñG_þÓdÎzèÁá;r˒9‹4õ7OÏüc1:Exñ•×¶;n¡@ ](Μ¿:ì‡ ÄŠöøI<Ð×{Ý,ÎÍœqêt©â¥ÇýëG‡·E§²~ÝàØÈÐGü÷01ï_HÔèðБ£ÇÓPöOí?PhnÞ²ñè ”“†–Ձ³2ìÜÙ×>Ñec·®Ð6pôµgBŽŸ|i~fúH¡­?ät€TùXtJ/™k'Ÿðk.·H©oþûâÅKÑ)ÊÆ§Nzî…èpӖås=úH>—$*ŸËŠçŠÁÉgöž8ýft ÊLwÿHm?ŒJéÊå‹ _6ÖÚ6PS[Ÿä‰©Š¶>ðζäûT€tҍU BsÓØÈВÑ߻Ыçú+ŒHґcÇœv4:E™™|foqn>:ܜ]ŸŸpÍT§®öUïØ"“Éd.çv?9é{inJ}®Á:ŸÒš™>|ùR¢¿  ÝIWÁ¿’Ó'^ŸrùbÔéé¡«L£ÃCËò¹¥{ýÇ~õW–îÅYœ©ÿø¢#”Ÿ Ź}ÏÆßÙ7î×w>Œ~Ý`t Ìèð¶¹j1oœ:=ùÌÞè”™Õk‡³ùÆè•ã܌…ŠåªÐ68F™ðž!@:éÆ*S>—_ªÇ ù³ŸYÖTX¢gq—}ìÑG¢S|ÀÅcܬ†–Ձ7-U’é“/'|¢¡±Òjl [«xnæõ‹sç£NH ÝX%›Ø1Vò×üß?÷Ku¹å%YnÅÔ7'‹ß»¢Œ>zìȱãÑ)à£lÝŽa×ç'¢SiÑß»f©/™ŸA.cºûG·ÉUŒ„×âÕÖe mýIžXñ mý¿ŒŽèÆ*YïšûKzEWûª°Æ']ffßÞ÷ü«Ñ)ʞÑ1ÒìáÛcÀU&ÆÇ–bSÈ"žxŒ›UŸkhëŒ/:Ey»8wþÝóÓIžhhl)~U§O$=w6º± 7±£”·Žýæç,á«Q{ŸñÑ*Á™³³ûžýVt ž†_ßù°UŠÀ5íÚ9áâ1ÊÔêµÃÙ|ctŠ2–|±ž°‚î/ž{¢NHÝX…+47•jÕÆúuƒí=Ÿ(ÉKQ*GŽéø©èbß³¬‚ U–ås_xô‘-Mí×ÖÕŸjt8›3™ÌמÜãâ1nJßàxt„2–ðB< —HCËêÀ’8ᵜi£«|£ÃC­-Í·ø"ù\ö‘Ÿ-IJhÏSOEGšŠsVÁËò¹ßûíßZ_ÒýØ@åuX³°òIDATÞVÚEú·â+_ýº§Ížq -«‡fÊÚ{ïŒ5_<—ä‰v`.ÀßÓ'­Uªšn¬òåsÙ[–pÇ/~fyskIòP*SOóÄÌùèåàwž÷¬+i0Ð×ûå'ŸÔÕŸ*:Pví|8%›ϜÝýäžè”“îþ‘ÚºltŠò“üžËƖNà×öò¥ù™é#Q§„ӍU…-èë]ô§š›¶mX_Â<ܺâÜüŸÿl¡éM>=€j762ô{¿ýÏó9?+nH>—}ìÑG¢S|àÅW^s/7®>×` i÷Éæ—¯X™ä‰UeùŠ•kϝ}=êh€pº±j1:²ø+Ümì3µ¹å% 훚üFñ{—£ST ÃGœôÊkÑ)šR­-͏ñ·&ÆÇ¢ƒeŠ¿wM©î™Ÿu{žÞk7nõÚáÀb ÍL¹|)Ñå¥V_.µÈµŠ'^ŸrùbÔé±tcÕ¢¿wÍÖM÷‰ƒëݟ.3³oï{ÉØûR™|fÊ5 $oldè‰Ç·¿wMt ,MŒÝÝѝâ.ãŠô ŽGG('ÉúXšžÔÚº"§'“_Ñ º±*21Ÿ}kèíÁ-K†[ñµ?ÿ³è•ìÌÙÙ}ψN@ùម=ŠÀ­xìÑG\×pgC[Ôégtc@µÒU‘|.»eã͍ŽýÂÏol»çK”‡Åyñ…珌9¢Âzîù™Ù·£SPù–åsc#C_~â_n]¡¹ib|{tŠžxŒ›ÒÝ?R[ç‘ëK~Ä'v€©z睛yýâÜùšÓéÆªËÄøXkKó ~p>—ý•±_\Ò<,ÂäÞÿ¡ò](Î`©mÝŽá‰Ç×íb@ mÙøÀýë£S|`ÏÓ{;‚òPŸkhëÔÁ\ß¹™€*éKFì×ÙèPtcUçÆþòЃÃwä–-in֞¿zjæ Ñ)ªÂÁï<ï<Käþuƒò‡_Úõù‰BsSt ÒìÚùð?¹Ô\<ƍ[œv8›oŒN‘jçÎ'ÜaÜÙÐVŸkHòĪ»Vѕc@uҍUõëúz¯ûa…æŠm[·&‡Wœ›?ôâ+Ñ)ªÈŸý–ÀPb}œñ·{ô­°Dò¹ìc>âŠs_ùê×£SP6úÇ£#€ZòÃ=‹þªPàèä»ç§ß{ç­šÓ¢èƪÑĎ돎ýæC¿”@nʞ¿Ü]üÞåèUäðÑc‡ž{!:bëŠ ò‡_úœßþç®–ZWûª±‘¡è8|ôØä3SÑ)( -«mðûÉ÷øåHRlit šBº±jtÝwJýœkú>ù©Äòp#Nœ~óÐß[ñ—ŽÉgöZÀ­hmi²AHØÄøØì IÆÔþ֕sƒºûGjë²Ñ)ÒèâÜùwÏO'ybkۀ…ŠIª©­,#]9T!ÝX•Z–Ïý€ÿõ7>÷`’až{þÒ*’Šsûž=€²tÿºÁ/<úȗŸøãcZ1 y»vN|ěŸ„¹xŒTŸkÜ,—fÓ'^NøÄÆBwÂ'ø5Ÿ/ž›™>u:@ÝX•Êç²£Ã×ûåÏ~Šå®Îdãp~ëÈŸNQ¥Šö˜™};:eãîŽö‡wlÿ“?üÒc>²~Ý`t zš›v}~":Å\<ƍ[œv8›oŒN‘:.«±_ósg_< yº±ê5:Œ­µ¥ùª˜ÏeÜöó!yøIŠsóûžýVtŠª6ùôÞè€Ý@_ïû•؏ÿÎèð6ƒb@¬_7žuӆèpñ7®op<:BºŒ÷Î[óÅsIžØÚ6PS[Ÿä‰d¢×*ÎLŸrùbÔéÉ«‰@€];'þèËú£ÿ䡇ïÈ-‹ÊÃ5MýÍÓ3ÿXŒNQÕ^|åµ-ǎ÷÷®‰@ºŽ¶4¯_7ØÕŸª¿¯7Ÿs9 Fãۏ=~æl*¶PLí?ÐÕŸÊL-×Õвº­ëŸä·ŠÖôI «E¡m êê¯Ë—ægНìŒ7ät€äéÆªZŸÞÃGœÿ·…æŠm[·ÆF"“ÉdŸÿ?2»ýý¿œ™}ûÐK¯ÆÆ!“ÉL>=õÄ㿝€xwwŽ÷÷­)47÷÷­1€_>—}ìÑG~ÿÿ8:Èv?5ÙÕÑ\W÷ڑ™é×/¹Š.“Édf’-Kjë² ’(…¶þÚºlÔ¿ùçf^÷KTÝXµÛµsâ·ÿKïÿõ~--Ëè«ÝÇnÿÁ¥ùÛ겙Lfê›ÿŸxñRt 2oœ:œïÙoo‹@Òúz -M…ææ®ŽU]ííæÃ€²ÓÕŸêáÛ÷€cOøûyìŒëª©­ïèÙüú‘ýÑAâÍLIž)qÓX¬BÛ@ÔÐä™éÃÝs#õ¹†ÓŠ«v…抱‘¡©ýú{×tõôFÇáºüœL]öȱã‡^;…ì{öÀ–üH ‚ÝÝўÏåº:Ve2™þŸ5ù\®«}Ut(€Þväèñ® ‰õƩӓÏLMŒE!í:îÙ43}øÝóÓÑA‚%<4–Éd[,TŒÔØÒžPôÌôáŽ{6E€Û~ðƒDg Xqnþ‹ð¥ÿë÷ÿeM…è,|èóïþÁý«3磃𡱑!ïá~hföí™ÙºÀæÈÑã7òa'Nœ¹š³×ŒGg ïÚýäsÙBKóûÝÕŸ*ŸÏe2—J@õ07F&ŸË~ñó^<ûÝK³ßÎ‡^Ÿ>{ûõÑ)Xàõ'£#€H¡¹é/ŒÑ<é¡#“ÉdúÖm|áÿýWóÅsÑAøÐí5µ?žíöè,ÐÝÕ€[ò±è€EßàxtøW.÷Ž£Sð¡Ö–æÑá¡èÜÝhhYÝXpÛjº¬lº}°÷ãÑ)øÀÄøX>—NÀ-эñ!£c)tOë…\Ö­cñúzׯŒNÀ­Òñ¡ú\CgÏæè,°<{[_ûÑ)ÈL싎@ èÆX £gsm­qéò©®ï7®X¢ªmÝŽ¡«}Ut J@7Æ5µõÝkG¢SpµOwß¡z-Ëç&Æ·G§ 4tc\meçœw6ŽE§`UÍß_Ýޝ¢JmÙž!Ÿ3L P!tc\ƒÑ±žk.:B5jmižwÓ@åЍq -«[Û¢S°@ӝû™žæèUg×Ήè”’nŒkëî©­³G.]>Ùþœ\öŽèUd ¯·¿wMt JI7ƵÕçÚ:ï‹NÁu5™Ouç¢STCc•G7ÆOÔѳ9›oŒNÁ}mW*¢*Œ š›¢SPbº1~¢šÚúΞÍÑ)žÚ†µuÑ*ß²|ntx(:¥§㣬쌷±Ð‚ w^¹û.ó|Kktx(Ÿsß@ҍqFÇRèÓ«/EGšdwwŽo‹NÀ’Ѝq -«Ûºî‹NÁ˳·­ïoNQ±&vŒEG`©èÆžŸîµ#µuöË¥KÏÇçrÙ;¢ST û× ö÷®‰NÀRэq}5µõmFÇÒ¥®&³ŸoYtŠ 4±c{t–nŒ²zíp6ߝ‚î.\j+¬ˆNQQÆF† ÍMÑ)XBº1nT÷ڑè\íg»o‹ŽP9Z[šG‡‡¢S°ŽtcÜšB[c¡;: îŒÒ×՝¢BŒåsîÕšpº1n‚ѱh¿˜ËÖG§({}œ[6>€%§ã&,_±²³gst XžœmmW>:EÙÙ€$èÆž9=›këìK—Þ•—š–G§(c[7mèï]€$èÆž95µõFÇRŠ®&Óß~[tŠrµ,ŸŠN@BtcÜŽŽ{6eóÑ)X û§°ºœ%:EYÚ²qC¡¹): э±}ƒãÑžZOk1:Bùimiž‹N@rtc,FCËêÖ¶è,°²éöŸéiŽNQfcÕF7Æ"u÷DGàjŸlÿ^.[¢l ôõ®_7€DéÆX€ú\CgÏæè,PW“ék¿#:E٘Øah  êèÆXŒŽžÍµuÙè,ð©®ï7®X¢ lÝŽ¡«}Ut ’Šcñjjë»×Ú¬˜:ŸîŸ=:BÚ-Ëç&Æ·G§ €nŒ[²²óÞ;Ú¢S°Àªæï¯no‰N‘j£ÃCùœ‘G€j€ãVK¡»æ¢#€WkKóèð¶èÄЍq«ZV·uݝ‚šîüØúþÖè)µkçDtÂèÆ(ÎžÍµu6Ô¥KÏÇçrÙ;¢S€Î@_oïšè„эQõ¹†¶N£céRW“ùTw.:Eêšrº1J££gs6ߝ‚úÚ®4þT>:EŠŒ š›¢SI7FiÔÔÖwölŽNÁÕ6¬­‹ŽËò¹Ñá¡èӍQ2+;ïm,tG§`ÂW>±º5:E*LŒoÏç܊Pítc”R÷ڑè\­ÿ®bt„xwwŽoÙø@t âéÆ(¥å+V¶uݝ‚–go[ß_í£c;Æ¢# º1J¬{íHmÍuéÒóñ¹\öŽèaî_7Øß»&:© £ÄjjëÛ:Ž¥K]Mf}ß²è1–ås;¶G§ -tc”ÞêµÃÙ|ct ž»p©­°":E€-7š›¢Sº1–Dßàxt®öɎKÑ’ÖÚÒ<:<€э±$ZV7º£S°ÀÊŠÛ{?"Q£ÃCùœÛïønŒ¥bt,…îiœËÖG§HÈ@_D§ ]tc,•ú\CgÏæè,°<{ÛÚ®|tŠ„ŒŽl‹Ž@êèÆXB=›këlŽK—Þ•—š–G§Xr[7mèï]€Ôэ±„jjë;ŒŽ¥L]MŠ¿ý¶èKkY>71Ÿ=:i€ciuܳéΆ¶è,ÐýÓ?XÝޝb mÙž!Ÿ3°À5èÆXrÝkG¢#pµ»æ¢#,•Ö–æ‰ñ±è€”nŒ%×вºµm : 4Ýù±ŸéiŽN±$c|ÝIèî7:–:Ÿlÿ^.[¢ÄúzׯŒN@zéÆHB}®¡³gst š«Éôµß¢Ä&và£èÆHHGÏæÚºlt øT×÷W,‹NQ2c#C]í«¢Sjº1RS[ßœÖfÅÔùt÷íÑJcY>7:<€ŽÓ‘œ•÷6º£S°Àªæïß}WctŠÊç &pº1åÖ±úôêKÑnUkKóèð¶è”݉jhYÝÖu_t Xžœm}ktŠ[²kçDtʃnŒ€uöl®­³û.]z>>—Ëޝb‘úzû{×D§ <èÆHZ}®¡­ÓèXºÔÕd>՝‹N±H†Æžqº1tôlÎæ£S°@_ە¶ÂŠè7mldšÐܝ€²¡#@Mm}÷ڑè\íg»o‹Žps–ås£ÃCÑ)('º1bÚú ÝÑ)X pç•O¬nNq&Æ·çsî®à&èÆct,…úï*FGžQwwŽoÙø@t ʌnŒ0ËW¬lëº/: ,ÏÞ¶Ÿ¿çŽ:I7F*K¡{Z/ä²õÑ)èëݲñè”1Ý©PŸkèìٝ‚–go[ەN±Àϱè”7ÝiÑѳ¹¶Î®Œté]y©qŲèغiCWûªè”7ÝiQS[ßœv$: ÔÕd>Ý}{tŠL&“Y–ÏMŒoN@ÙӍ‘"+;¡-: ¬jþþêö–è™-7äsÆ žUº1ÒÅèX Ü5 µ¥ybÜMc”€nŒtihYÝÚ6‚šîüØÏô4PŒP*º1R§»ßèXê|²ý{¹l}ÈÑ}œë× † @åэ‘:õ¹†ÎžÍÑ)X ®&ó©î˜ëŸvíœ9€Š€#:z6góÑ)X ¯íJãOå>tldšÐܔð¡T0ÝiTS[ot,…6¬­KòžeùÜèðP’'Pñtc€ÔÊÎ{ ÝÑ)X p畻ïJnžotx(Ÿ‹Yä@¥Ò‘^FÇRèÓ«/%sPkKóèð¶dΠzèÆH¯†–Õm]÷E§`åÙÛÖ÷·&pЮ œ@µÑ‘j=›këlÕK—žÏå²w,é÷¯ìï]³€GPtc€Z}®¡­ÓèXºÔÕdÖ÷-[Ò#&vl_Ò× jéÆH»Õk‡³ùÆè,pwáR[aÅœøØÈP¡¹i‰^€*§£ t¯‰ŽÀÕ~¶û¶¥xÙeùÜèðÐRŒ2dtc”…B[c¡;: îŒò‰Õ­%ىñíùœæX*º1ʃѱê¿«XÚèëݲñÒŸ&ü(ÝåaùŠ•=›£S°Àòìm÷~¢”ƒŽl+á«ÀÓQ6:z6×ÖÙ¶—.œ+/55,/ÉKmÝŽ¡¿wMI^ ~Ýe£Š¶ŸÃèXÊÔÕdúÛo»õ×Y–ύÝúëÀGӍQN:îٔÍ7F§`îŸþÁêö–[|‘-7šK¹ž®I7F™éŽÀÕzZ‹·òé­-͆ÆH†nŒ2Óвº±Ð‚V6Ý>ØûñEúÄøX>ç&9’ £üK¡{Z/ä²õ‹øÄŸÞõëKž®I7Fù©Ï5tölŽNÁ˳·õµß±ˆOœØ1Vò0ð“èÆ(K=›këláK—Ou}¿qŲ›ú”­›6tµ¯Z¢<ðãtc”¥šÚúîµ#Ñ)žÚ§»o¿ñ^–ÏMŒo_º0ðãtc”«•÷ÞÙН‚V5u{Ë ~ð–ò9Ã$J7F3:–BwÍÝȇµ¶4OŒ»i €€éÆ(c -«[Û¢S°@ӝ[ßßzÝÛµs"0pÝå­»€¶Î^Ÿtéùø\.{ÇG|À@_oïšÄòÀéÆ(oõ¹†¶Îû¢S°@]MæSݹøCcDэQö:z6góÑ)X ¯íJãOå¯ù? š›ÎïӍQöjjë;{6G§àjÖÖýø?\–ύ%Þ§£¬ìŒ·±Ð‚ w^¹û®«çùF‡‡ò9÷ÃF7F…è^;«}zõ¥ýÛ»;ÚG‡·E…€ŒnŒŠ±|Åʶ®û¢S°Àòìmëû[ø·;ÆÃ@F7F%é^;R[g__ºô||.—œ#“ÉÜ¿n°¿wMtªnŒÊQS[ßÖyßí5uÑAøP]Mf}ß²L&3±c{tÈÔD€RZœvøÊåùšZÓc)Òٓ¹çµ…æŠè ¹í?øAtH‚ŠT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT ÝÕB7@µÐP-tcT Ýÿ{v ÈßzK£ 7À…àpáÆžpc\ž1.Ün € 7À…àpáÆžpc\ž1.Ün € 7À…àpœ —æò&7IEND®B`‚././@LongLink0000000000000000000000000000017000000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/images/validation-configuration-1.0.pnglibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/images/validation-co0000644000175000017500000013225711251452073033234 0ustar twernertwerner‰PNG  IHDRŠ] ÅÛÑsRGB®ÎébKGDÿÿÿ œ§“ pHYs  šœtIMEÙ  6òbE² IDATxÚìu@ÍǟÙÝkâè$ìî;°»ëµ»Q_ »;°ýékwŒŸŸ*v·‚Š ÒpÇÅîíÎïCD8”W}}çó‡r{{Ó;ßyž™A!†a ?á8.88žW¯^PPìØ±£G"‘þ=pÇó}JÓ4ò§BOœ8ѬY3Rá`†aY6_ã:tšJ¥*È\©TªAƒ­]»ö_Tb±ž€cLLLŒµ±±!A~Ю];FCʁ@ |a«q‡Ê|cœ¯1"„8ŽûwÕD–2Éï"2–яüÃ`0diöðsÉ3BÈ`0€^¯7 㟻Ûú€Œ ‘™aYV¯×³,ËóüO_DøË#‰¯ßño-áoËÇqãŒfOº{˜¯vRFøM¥(êýû÷aaaZ­ÖÖÖÖÑÑñçÖ„Öé4I$ŠÀb¥(*,, !DQ”“““••ÕÏ]DÀóËD" ÃPÙ B°`àXV`dRaô%)Ìh?Ãè-= œ:6.É̕–æ"꧍Šé˜˜˜ÐÐP–eÍžt7!¯¬gŒÒŸ|#,þ{zL„J¥ŠýðáƒÁ`ÈiõÓÏd^pçވ-àXccccccããã¿°\ëç)¥€G·7-Ýr>Z /Þ{­ç„Ïډ  »þÇÊM;4]›3»(!€K‰}öàþÛdögº!„pZÔâ9ýŸ`î„i·bR"Þy• ÿGiC%''›œ 9ý–XÕáŸ[Ï‚Ûc[_wY/Ûïìï(ŠR(›6mÒjµ™»*£EâççמqãŸGžlX²Ý£ßÌÚÎiÐQEQ”V« ̲RL±XþjÑ|*#kQ¡¢ gŠßV‡¶«¡”Ñ™~ØY˜;Ëe^Ž©šÐÍŸý~»ŸfŒ`é^¶ó ÁµŠÈá³ 2ݞ{ÓÓd±©PM‡‹âÃÁmÔªœ†ÎšUÓÛÃðèŠ>æ¿ËmòŒH¥Ò   sssKKK¥Réàà`aaaooåʕ>ˆ@ üSë#@vòŒsû•ŬŸ4y˜ûéÀÀ@‰ä3+ÄÃÃcÿþý Ρ„° AƒfÝÄšhÉr“‚•|xrfö¢àgQï8¶ÁšÃãKX6ƒ þmÁõ ~ÇOîá*EðâäôÙÿ~è1eÝÒÆÅ”XH»²ye\ù֖÷6LÝöªIÀ°qý}6ÍÝ{îYûýkÉÄTÄ¥ÝCæl5ŽK‹iËû•°”|µ(ÝÝÝG•åbþ¿'† ¯nž<}œh‹Õ\%{uûŽWÎýÛÕOŒœoȬ`–GVͧ­ê_J)ÐsZœ Œ(ÉGçwYz;:Ö©\6UL+)Ý»' —,?û9BåÏÑŸªÇ»KëFžœ5nÜVC­é›Ø4:¹!//o›±btŒÚ·Ãą¿5V ̪ãBöíæÊ5R_Þ°xîÙÐJ”mRûãD¶>ñɚE«Ž^{̱eǍmY˝áöEÓ7ç0S¹ÏÌY+"ɯ\œþÄÆÛýâÞ G¯ñý'umP"ùÆö‹ï‚*bxë?*NÙØÍGÐêÒd Faæ­=ú®ÊˆÉU^Üåz p£/7{„ÐŽiӌ¯^œZœzu‰D¯^œ"}@ø‡Ö3Fpo÷ê»I)ãÇ€Ç 'w}Û¥i϶UôÛõ¿ÀÖßÛ?¹g‡vcîJꗒœ˜Ó²˜o·K¡VU‹<]2bÞå°DþIÈœâ Úvï҄ Þ'Ð׬p‰0 …"¿šáµ7÷íܲù $Oœt52‰ñOCîùúµîÑ­¹ôUà—á“("xuvýгw’t€;T·a¯`ºE׀Ê.vNÜ&1³ Þ……!¹sÇ>j¹ÛeÇëd^ªŽqð.îY²nm[s:õÍ£»×_ˆæàñÜ1ëmmÔ³{£7º×­ùG M Ù<ª]û+Êj•LÚ=}á¡SQ} ƒBøèâžM6œ‹iб›_KKŠžØœu›ŽçË4îв̕i­ýþ}BèÁy]ëw›v[ð,o2œ×Ú¯ub›BÅ=ŐäQÔ¯ž³ŒÒÄGߟôØ+ž®›Ý³þ6­c“^Ý< 6+p÷[}®šœñåƒÁ0tèPãEœ^OÞŒ"ÿØzÆš¶ì|ÑeM …0‚ŒêHär¹›››q*Î`0Ô«W¯W¯^‘‘‘óçÏ¿víÚ÷oaFQTdddóæÍM|Ç%>zù À³M×VôÁg÷~šÕnCЬ*EÌX­Ž’ˆ œtÅ{í]?ܓ{I=zñéUØ­9TZ¢[Ÿ6=<)¯íKëýõ"±BF›†ùzÃ-ìm{=ùñËÇÖ‹ÖpO.y²òšèd•lý†NoiaÀ9ùÚß±àgÿµ¢d&44Žlٲƙ怀€+W®X[[7Žçy£x#„ …J¥ú¶.žaŽã>ßX  K·b^U=–]ÙûÂPß3|Ï¥+E&­ £DuOkfaŠÿ>òÏ¿â¡!2~ŒA+xD1ðîø ‹·ÝÜՐ\×V’ºàR‚À­r“ɵ[S¡Â²¥;Î>OÕ€t‹ö•àHƒN=yó@xË!V'¢DÀ‡Í;vÀaðÄ©ú»+©Æ… N~ƒEú··Âɲ©3xǪÞ֑‡Ÿ]÷8â …T q—1­k dööæú»×öíA֋VnèYՁcu ’BbȰcǛ¬ž2¹9Ҕ±H­oÏ̝[›­ñôºôÀŽ– )X{»»8Z ‰Lž~g4èÑ¡€µÂ ‹ Ñð Ë+›&•Ùù;…XÁ¢'…€Šé ›Vˆ91#õqö*SÑ]À;1 1ziC®Óyìëî ‰>79ÏóÞÞÞϟ?7®rÁÍÍ-%%eÔšQÆSãÇ}ûö©Õêo(%+++www£I—Qç‰ì›Õ­ôÇ_œŸ÷Þkó1Ïuj–.DD]Ù\£Ë4œÁ·ˆ($:œÝì@@Ÿ śVrE"sk{GáK°±÷ý6|çiUqïp5”E# )0 @Ó€BˆÐ'@‘ò‹Û+ip,Y P¥À+DÖMÚù»I)H,11€lhî·àÎ3 M#Šu Ÿ¿¡ƒ“ް·öôv‘X €t dZE" ¢P‰Š{Õzô‚“«w¹Æul)H‰†(F€©ˆŠŠ 4ØDÖÅ·j W[ìKŠ©Üº•0ƃnÔšQݺuCBB€Réµk×HD þ¡O¢033˲P6=b$*0õQ³A×ÿXÝ}äÈ~%Kîi%ŒŽ7d]óƒüÆ€8mj‡VÓ7®ÝÖá0ЩãdÀ æÀ€1  CMJ  ûj_•ã_zÓÃW²²G×Íìǯ¿2[ nnn™/ ‚ T*mmӗЋD"†ad2Ù7a¡¬k£0‚¢UóŒ|hJÿØpu—ÙµÜmDðæ*íÇÌ;Ù«€òÖÚmVp9¥³,ÀÓšT öxM¢•Ä͜6&ΜIxêï6·~÷lr 0À†D•uXȲ˜KSq<Èh.Œå‹0ˆ0ŒŒA–c/\Î ðqTÇHäÀ¥`ƒšdn:-†çïS ÆHCBz-a 10ÁeôagmÀ ¿yŸ” ãÀ\o®_„0Ý`iiéíí=~üx©T ä•*ðeOpN=7€nïꀑ•K*ey|°þœ‚Ë+BH÷rß®³q‚ÜÛ»xi–ÕpTÑ.>•_­YŽúDt܇ÛÿõRÅ}£|ü%/x‘W¿¢eBf®ÛqðŸÆ`xÿòÁã8-ú$kÿǙ#€ŽIÑz=uÚĈ««§e€:¹\d÷åRʏÒC0Xû6/çõöÜñW•ýª•–hctzëŽ)¯¯­˜‘êRLø9ŒŠ”kD£ž³×<‹|ùNJñ͇o°¶Ž7èR5ªž íõæ±{to“Õ€ÈÜîŒÞÁrÂÇÁ‚d¥º»xn_þ¿“¢5ê7+ÆöЀžÌ à,Þ€ ’ÉffŠˆ"‹²¥š”}tiì€%OßÇ¿ž}ãÉÛpª3\©7mýwÉÉïî.Ÿ0ÖF9Œ¶pŒ%X.§åقD^Þen͘0cÕŒî%Û/âÿGÍ^¡PL™2§ˆ<„&Ï åÚVMÅ Å KiÈ¡¿úavrr²··e‚a˜=z8;;ˆBëÎtkênkéÚxhbŸéëÛ€:A«¶-«ñçü…+Õû=*™‘ÜL&¢Ñ"™…ƒ™\Á4X¿gïr‡MãªØYÙx–®òV €Är3™qÛ,$‘(­¥VÆ¿)¹ÂŽÂŒe¹îóÚÛ¯ïë]«Sõ \ŸîéÖtݗ×Ñ4Å0L–RzùòeœÁ…0UlÕšbu‡Ks7yÙnAG7*Q€rÛʛ{†ï hž.ÍÊR!“‰hdŽYe1Dew]Û"Þ=²”W™q+•+ÖLá9œXêÙ«CËÄãs<ì G¶k×Õ[ݹü°'ižéè`žS¹ˆ÷áIÄ™LL ¢n¬­ÿrxuWss÷‘φ\ý°Æ@@”DА2h‘\ná(—I)SéÇ@ªÛq˅%–Æ”p²ó­ÔëÌÕ×,XL}~s†dmMw[[·ê›Åó¯„N³h‘Dj¬j`€ s¹Äè'w0+”^ڈ¢%2…˜ÆÐdéºÃû'ê.m»ï8ëäŽIb ¹hö¶¶¶2™,K…Nœ8ÑÁÁôAÁto,‰LžXsxDÝãng.é(ÿΗª† ‚êÚµ«F£ñññÉâÙÎ܋åÕBÖµk×Þ¹sgÓŠM_‹cüÉ ä1—;aœî+ýì™¶žx èÃÎŒGezÉ €ï•Æ @SŠ’"‘HNŸ>m<ß³lÙ²fff_.¥€€€Þœ{>|ø›KÉÕÕõÚµk… úbEd*¢OÙ6æ"ìĈʺ%'/tÆöpšñ @ÔDzù,¬ÏKçÁž¢?Kñ𬓸TðAãœ~Λ‰fnŸû ޱ‰)Ï;ƀMeºeÊ2ƐŸ,ý•åÏÂú¬˜Mh³ÉJ1™ôšúL›Óë‚úŒöM›Sø/–Ïìœ7€H‹Æ–w·xa3{O'kü•!€V«s’a¢Í!÷òŒ1†*}gWù¥G÷ÿ¬Çÿr'ž«x>Ýý/,Ï’ · Ì×2]r +÷’ÛšBŸ_ûŠ01*8swۏC£4U7Lš×Äׁ"°¡`ä9:Gá×ÑaŒEe± uŠUÈê†!¥C ò–‚8ï9˞ƞà#ÍCkŸÀJÉÜܜ<ßYG9UœX,&k³ ·[ÏÇ :”ã8øxÀNÞF ‹8кu낔„ÐÞœ{)ŠÒëõÆLýäöX,Öëõ)Ïóƒ ²ŽŽÌ§ªÿ/#‘HΜ9ãëëKŠ‚@ |£<7†4 >|HMMÍÛnšãžÖ­[W­ZÕ8(7n,‚q ZjjªñœéŸY¡9Ž;vl§pÆ oÞŒ1þ›@:¯`Y¶{÷î%J”0±=@ äFž{õê•ñ!,,,666Ïûh„ÇqÖOaŒ=<<† büšR©BCCMŸ<öSÒëõæÅûûûg|ŒŽŽ~ýú5™CÍÛ eYÖäé&ðuyÎøK¯×kµZ­V›&”Ñ¢-€n1óGcŠ~~yΜþéÌ¥„16–‘ç|jödš@ |»<Ó4mcc#‹óUžG0$2™ÌÉÉé'wngÎü?82+–––®®®DžóŒ±R©$å@ Ÿ]žœœœœœ غÍoÌÌÌ ^íþ]E666666äy „ŸKž?n¢T@ªP`¯ŠpŸþEd »™@ ~*šb®€ðüK+†è%@ y&@ä™@ ‘g@ ˆ<@ òLøÈŠ€Šœdüš,“§‰l^ÁZ'W‰'&&þþûïä%«_¬G“ÉdsçÎ5nE÷ck6#ÁÁÁ>„|{=ÁÊÊjÚŽi?*Ë¡ÐÐÐõë× ‚@¥ïG‰D2uêÔÿàñzDžIŽB‘‘‘cǎutt,R€9ÅáWx…††öìÙsŊ–––?P¡Q ‚°dɒ»wïúúúæÓ‘¯ã/^ 2dá…r¹ü‡dùÞœ{ÿûßÿ&L˜ ÕjI#üN ŰaÆJä™ð_Ôæ×¯_wéÒ¥]»vcƌ!ãý_ •J5kÖ¬N:íÛ·ÏÂÂâ‡ÈU†6Ϟ=ûáǁ¥K—οèâââf̘ѧOŸ­[·J¥Ò’å5j >œ4¿†¿úŒ}ºþ/|"†$•ÉÒÒrôèÑ5kÖlÓŠM+t†6/]ºôòåËsæÌ)Uªä瞵Ƭ988Lš4ÉÁÁ¡OŸ>Æ£Ø~ª„3§&W)ùžëŸ‡ú3æÔ”JQÔ»šÕêÿŽ%Mäù?ŠQ›ëÔ©3mÚŽnݺ1 “±?ù¡C‡hš–Ë劐ÉdmÛ¶¥(êûº„±áuØÃWï4YN·ÌœHAýðák-BçV †ŽÉX˜85êò©#‡Oþ™ Ï1m_éxñwfÇX¶J¥räȑU«Vmߟ}JJJAîªË²ìºuë:ŽlÙ²âŋC>ï'Ÿ¡ÄS§N533³cü(‹£¢¢xžG5oÞ™¢Zµjyš ÇaŒÍÌ̌éÉHŒÉ€fÏÆW'>L•‹D"±¶¶~óæñ5§R¥J™ÌrçΝ bT—9©ñšÏ£sžíş;Ì­Öq·ÿ>ûðF}ë¬Å“¯»ðE=± Š òïƒ;Ï>Òq|Ÿý\7h•búOœuþÔõg‰zøŒ#²çØòtnž³/¶tŒ±“““Ɉôš4A€‰(ÀŒAÏr”H"B|šFkàyFА‹:óÃéT«SðåŽÆÑ5BØ OKUëcnoyaV§IÓ²QŒX*—I(OÇLëáÕç^I7/{¥T$öˆ–<§ÕjYާDb¹L&¢)˜ÓjxZÂ`V­e%R˜É a“–9BœV«Õsˆa€ 3 Ìs¬F«3ð-–)ä!„0«ÕŒ„âuiZ#’È2ÏÒPT†T-g%eè~w¹~ÆŽxN§IÓh±X„(Ä0f{h ¯‹ÜZ—ÐlúøÞÆtè5izƒLÂP ôZ€R± ×( #èÒtD‰äfr…€çŽZ­Žã)©\!3!Œ!£Ë2v^E©Tª°°0__ßÄÄě7oVªT)sÖ#""š6mšç~Ï,C@„J¥ÊáeŒô…Òëõ³ÅæææÆ%ƏF·<ÆX$)ŠŒŸšÕjãۀc¥R™a gü›˜˜êë뛔”kgg—9yþùç‚ Âý‹ÂŒN£Rk£c茊‡ zFÇò-7SHD4Ïj€_ŠÇz/–P‚N«Ñ±Z*—IÅ BÀi5Z*ÓcžÓé±H!a>|ۜΎ꥝¬•21mÒÅÃëuP44:cZfА0”1<fV‡)‰\.8]šV/ð%‘)dRúóg\à9–5P"IÕy‡¯|Ÿ"ô•JÉiŠ¡> åyN«Ñê <%U(€"!Ìé4JBóZ-‡Ì-ÌŸl2ŠÅbœ^Ÿå¢¿¿ÿ/ù±žÿÝJøSŠ+ucϲ]—ß6~x{ÿèšßzœôàxÓZ圬¬JŽ\ Ÿ ’cܷë¶)ñ¡ëFT.æeogå?uõ à5ñ›'v¶¶¶µ³r¯ÙlÚíh^÷ä9©ÑÂε 9ŒÙvfk@ÙŸŒ`Sîï_ÙŒRIkë"5Z.=ü0UèÄ¿Ÿ wnžÝÍÊÚΜPœíWâMûÛB€“ý9%ÀÏÊÆÞÑŸX³Á*H{wzÅäÊ%Œím­œ›õýãj +€jWïj—ì\4ÆßÚÚª\Ÿ¿4"Θ¶áōÃkí·ø‡ž=ÝÊuÝñ0—öpPóRÖÖ֕۵îߊåÀ­g³cÖŠ%aÁÀàøð³ã:7œuð¹ñ«û»&޲"R¥==ºI·Ù떌kfcëàê\gíŸÏ4ñçÖ®QÚÚÚÚ£ç”Ñ©¬q câ™§š”””ÈÈHFòl–oKó²‹¡Lw2îîîʏdnÌkÖ¬±²²R*•VVV!!!_ñ<ŸqÝßß?óOj×®m ÇÊʊãžìé§i:111**ŠeÙìýž^¯Ï)‘yø`bŒà”ûÇÖ·²wñ)UfäÁË2‰%€äš3š•öµµ¶ö³æŒš‡g{Ç֛tZ{e@Ý¢6ßNáÞ?àgmgkm]ŽÓ˜]1©tô·:ƒ¶?¬W]3žùŒó™’Èt÷¶ÍÐ%†ŭí'þïINIœ³fäÀI³Mïîåájeå;yÇe@›ŸjPœþ³æuó+ÕkÒFµ>áHÐÈ2ÞE쬋·zân<Iëz”ë¹êž17·öÒÿÈóÔgGõ˜¶&,‘CúЋc[(Ý<==ûm9ùH&±BöáäòÞUKZ[[{ö›¹ïœÚ Y«Ëœ ³Tò-Óím® ùɓ'«W¯N—|žÿ%׋ëù_Œ^¯Û 0 IDATýúuZZÚ7ü6³‘‘·&€²Š_Ùaƒç†=ìÅ'?sâä ù˜²Ö)7-æn<\¹RÉÛ˜kŽÚ9ª_ /ù§Ÿt)ÑïÂ-õ"vsçÎÓ_TÚ~ér]ûW3ëŽ( `Ÿ*]Âӎ*#Wwk1wËÚëæø÷wš¥-°jRG''gýè… pèŸ;Ló\3¿êõœ[Ž`~bÏàfžŒþéîÀ¡7û,~>éÀP¿iœ÷u "xŽ>¥Ñ C#öÙÀҍÿôér)âT9¥>&6M†ss&þ6ïþàéfÿÇp¿Î5_|»§¶ R'<ÚXâ²gwúÿÞuìòÙgëmm6w|›{â'oéWÙK Œ*úá³T €cž0ÝjÀiÕúª!3Çv›q¶ZÏß2{?v²Hiç]Ȇ߲n{ÿŽAî†gK–žsí<×ÙBþXóôà’iO&nŠ/vz~Ÿ‰ü|âlö-øtàÙø›Ž×*”û-žFÙq­ËIsš_£\i4†a=z”±rJ,+ ƒÁ Ñh"##¿¿yÐ4!“ɲennn\æ#‰‚ƒƒË”)c0€RiLLLÆ=€iZ,ä×ß¿ìØ1gggžç---3ϳ„„„Ô«WÏdJbcc9Žcæöíۙ­m‘H”’’’’’1¹Ãóü·ÍeŠÅâèèh©TšM³„—ÃË·ù³ãÎÛ$üµ­󩢎${‡õs¿ðÖ§k$ît/×µJ×í[NÜ9þÖÀíÛîtW"iJ‚(`HÐÜcõû×l³ýZ@“ö5ÓÞÝ»›ªŒ êø—ïÂ>ٔ«—–k;Ønæz¿þ›Çµ°²sXŽÏ쟠(†Šø·ç6­?ÒeÙù[‹ãþçß§nъêþ.üûû7w^˜piëBGõœ%uÆñ›}šÈ¶õ¯Ùªâ;){jÔ-5r䌗£ö{òñ§NžŒðÊljIå‡Ãáañ6Zø0ΧþÎF«ÂÞõaÂN ©3÷\\>ã·åïÆIêgñWéÒÃvÖ®0¶±ûáþám3^ÍÙv;šŒUî ù͛7ǎÛ·o_‹-ÜÝÝÕµÜDžÿÅŠsrròüùó¿m“/±Xl0hšÎóta€’G™\s婸"ïŸ~XßomQ r•ä;wN»ð>‚£àItšYž!Å˜Ó èŸìJIë<œ[ý’62°YpiéBûU ’Û–­SþʟÇS_¿ÔâD-DsP©h™ íâáQÔ^Š €=S­ñžùõdõ†Í®±³Öµˆ'œÀ“ÕóÊŸ;Â6Ž^_±z=ñ(€{rìØU•TLœÆ¶RÛÎõJ —ö¬<°«–;€·%€&òLtŽ×ÈýºtY°nÄÖjœˆ«åbc ÀsÜÿÎϬIa%Êyÿ͇i<]^¢¢E=ÜÍD-…žšð;‹ÖŒ¶®±@“éßHVk²wa,]«µhµd܁¿®Íhšpà‘ªôŽº•åú$ÖrüñçSë@×)³÷w?òšLRd²#Â7NQÆ+ 5&6‰3€Tô¥öƒR(¯_¿6vpÖÖÖ[¶lIKK;zôèÙ³g¿° '÷­4>>ÞÁÁ!ûW:ÎøÇq ,0µE%$$dÜsèСcǎÕ7³XŸ|ùrÜžqÆŒ#€O…Æ0_¶ã¥RéèÑ£5 ‚P¢D‰¡C‡ŸxñbÁ‚Ɔ¹{÷®Ï·íkFQTDD„q\øçmË«ºÚIÁ®YÏ ëÞÎ:š„ðÛ³šD{«ˆãš ސ$+î^Â՞*æê¡Ž0÷r×ëBŽý™t?‰œ×kQ";£,!DÑrŠe²Ôyó¢•$V¶nE=<ÍD po,ÞõVÄP˜ç$Žžõù—t”°IŠË¢§KG8Ë&,òŸžÿÀ•Wƒ;Qs«æ“v¬ïP4/NŸ‹­5wxçæEDý–o¶£Þùg«GvYxFÝ5ç’þè|ž_³µno²¢(1MÃۋ+³]kú»[Š¡b»ù‡_ù Hœ™øZ!ǎ[ÆY ”šIÀ¬ٌßotí!_WÛààà7ÆÅÅMŸ>=(((ú1"τïšÈÂNNNÆ%©ßÆ¡C‡òeó ŽUùe]}:,ØØrý J9mlE€Ô#›çíº,–•+åà"€LB™6œ0æJæã÷êT’".Œ:á®Êœ‚3“*."FˆÐr‚Žž 3…”H"‹ôÎQˆ(„€ *Ö)ŒÕ¥¥RÈW ýæþ_œQȃNSܹ./CK@Ìdš˜ŠŠå $K 1ˆ6NèjQ¹ÒnÀr:œŽeÌÌhVÐ<«ÏTÂ×2IÅÈRj U¢Qiъˉ*VªÑÖyןe‹Ÿ&+Ôž}…’NÀT±53Þı< AÊ -J‰{{áüáëëT»kÃrE%¹è²’““<˜ùÊãǏ•Je@@@@@@ž4‡§OŸvîÜ9ûõ®]»>|øÐ8‘ŒxñbkkkAÄbñ¥K—6nÜhôB3ŠjÕªÎí1cÆ$$$‚P²dÉ1cÆH¥RAärù²eË®^œ*Ïó_­ªÕêK—.eŸrìØ±êÕ«/_Ÿzôè–-[²_笕FÅœ& !BḦ>Œ~væ,Ç|™cêzXa-Ÿ £W@wïü¶Is7% ’œm“þl ŒD" EbKqfMC eð‚ P`ÐD^ž"3‚³*n(Wqi+o(^26“ˆ|l-@ÑæfÔÇç‘…ÈŠÂŽ>œnhЕ{‘`3}XYc›ÍX°'k¥Èø#A§VBˆ%œýן‡%ëÖ°wÃRî" P±]z“ϝ!<}úô-Z¯Zµ*‹g…È3á§àçÜ! XZ¥×NJGh+ºù¬o ðxÍÆ-ÞWnpwR«5B‹ÅŽÙ 1w¥b^¹ÓœuMþùìù»$ @ĵÝ;¯Ä‡ŠÜöz|ŒUýQC!±‚s>,ir4ˬ"+¹„}qóè}ÝвRõýcoÄ*J;c¿Âit™âôÞM»¯kÚ=KB—Ò‡Öœh¿€…5mHIV™[˜»‹õû¯ßŒ=€¡ Œ»ž-Qåân«0:£9M†k ðq^݄s”VZ[™…ýµvõåu íZ|éÆÛJ€ŸÉ2ÎpC i¡ ~Ík˜4õŽcÍ áuÜb9~òқîåÝÌqÄÝËo)ÛrŸ.f%Þ¢bƒ÷µ-O€ÎÀ3ŠœeáeßÇØÂÂâ»7œùŒŽŽŽì3»ÆÍ·ãããAÀkµZ'''ãWíÚµkݺu\\MÓ©©©ÎÎÎ?ÿã?Þ¿OQÇq‰ÄÖÖÖx}æÌ™ÉÉÉÆyt•Jõå,g]ssó,sð‚ šÕêo–g­Vkr2[bfm‘kχWkWøå­Sëvþ-+ÜK‹ÂÁMé7kͲ Κ /ޱ%hbOÚ¥(sûøŠ”SNì:Å"`“ÙWñIp/N/[}òŸ¬QVW‡ØÌðê|hòxÊB”Ì{ò™Óٓ$Rˆ¢ÏÜ~Pšž2áá… è[ܞç?`ô€Ô“IÙ}ñ֓Ÿ«ØÂ«s›t†ÂEì€@ɪvc]}Èš”Ê>þcj[|×{šY»Þ¬;÷ ~ïr)¡çƒÖ—Këa;Rb/I™á³÷7/‰@—>þNÇBî޺ʐï2eÊL˜0!ÃøKn%Fäù?mç튘O#w„­|üº—ÀsGMÛÑ@áR·Œë®]³[]ÛîÂé\àæøë÷ `Ղš@0°iêTÇ2 oÝ›ºœþÓFåHÙkä<;·R%˜-}ü;úÐ *Š{°6øHóê՚µK™³¡gûcWlëXJŠWšå$eêvT÷ᚁ ¯ùŠxöžß°€Ú¥iœJ«Ò§ixŸœÊcÓ%”Cõӆô_Ò©eDsW†²q÷›³¬ǞÃoOž7µg³Ί{wµž ‰—5€Z¯ÂjN˜ÕñjcÌ )Œžû(Ñzšt<]€R›Ù}o­_7ùõ%+ ‰^$e ›¡‡<Ëf±QŸ1 dV§N“ŠŽëS+WšU±ž±¶Ä梈£;ÇŽ‘Ù£°çjOÝÖªš-×zP×ó£gõš²«LqCük¿±+û×/-£?«îÌǑÿ7nœ››[æ®-666oå2œæ”»qO› }Íü-ƘŠiGGG0.±ÎX¹2^Ïþãú2°··Ï|ݘ͌¥ããþýûgÖ]Š¢ž={&—Ëóýq@®ug÷n4x@Õ®ú8*JOYª9ÌŒ˜9bÒàvõ==]Òbߎ_ž¿{;^Ï«°ÞXß%}Œ…Žjà‰S-áÕ²‘몟ô©ßM†ò—Õöfí¯oë-Ï!ž]SÏ8|å)þZNsʧ»»û¢E‹ìíí X±bÆ?òµÑë™ðƒéÚµ+MÓ­[·>v옏OFãîСƒ]DDÄÖCš››§€€ä$ϟ?$Ù41Û™eÊlúiŒöIï2€:óóŽ>^G© ²lÐ9k¯›NE®ƒÍ)±C…^ ?ĄÝÒ€•X9®]»Jî2Àd ‹cÝŒü~ŸîT¿œùÇ{ ä̅AÞ.YœÖ`:ϟ;uêÔĉûöí[®\9ãRŽãX–5Ÿ¶ôÅü.lmm'Mš4}úôÑ£G/]º4˲ù§Í°}ûöÕ«W÷ë×ÏÛÛÛè3`YÖ`0˜\Ý]=»qÏé,M*Çöú)U&ž,Ÿý¯?G9ä®PŸaÓù"Ö`0jAýü«‰fŸPxŸÇžûœ~Œÿ?€‰< ãs ‘H4hpþüyoooãØÒÒÒßß?¯Cfzvrvc欟Ÿu9Ýøå Ÿ#ÅŸ3X €Dæ¶~ƒÆÕбÄ™L*B9ü1cQ©Q»ŠˆÑê eú-…DÙSa2qƐϟ??xðà1cƔ-[Öžë3«'Ÿ›™»»ûï¿ÿ>a„I“&͝;7_mè »yïÞœAAA£GöõõÍÈòw¢Ü4QSb÷…a_nž£œÊÚ£y‡A˜‰è/Šø75û܌‡Éñò_„ìö%ÃçÙŠM›5kÖÔ©S',,,ó`\œ ÈÌÈ?-ucÙ2"©™¹…ÒÒBþemÆ%KÄ"aŒ±ñ^,K%¢\þi ùÒ¥K]ºt™8qb†6gl™?k³63pss[ŽhQhhè¬Y³ôz}þðh ùðáÃãǏ?~|†6¯K$¢™ZŠEb‰˜¡ÈAïDž ?§B·hÑbãÆuëÖ Íæ¶Êµ}IøÖËÙ¿þ¹­„>»–›ÂG]Ÿ|ÙßßöìÙ%J”È*žçmmmÝÜÜŸã‘Ü+Ž‹‹Ë† BBB–,YbTè|Šñĉ ˜={¶——Wæ,;::ºººÌÿ†G¡œ§`~þ§æ¿qnµ£Bg I™übH¥Ò}ûö)•ÊŒ}‰A°¶¶öòò’Éd³š&Ã+ãèèxá…ŠM›Nž<9ÿ¢³±±Ùœ{·L&3 Y¶··/ZŽhÁ¬M377?xð EQÆ¡ 1L¿Ÿ_u_0"τ¯`ì°Ê—/1ŽŠŠŠ‰‰!fñ¯„V«5j³Q'¬¬¬ŒŒŒäry¯tÍð֜:uJ£Ñ„……e?z(¯Ú³N§Ëœe;;;///‰DRYÆ7kÖ,C’u:݋/ò)§ÿ+B£Ñüz ³‰<þqƒrrrÒh4ïÞœ#Åòë Â@©TzyyeœÆø£Zš\.wqqÉ?…Μe›¢E‹Œ6C6O¬Z­Öh4y~ع y&üEcÌ0Œ‡‡‡ñ$Ò¡übÈårOOÏ¥ÍYZšq˰—/_æù&e™{s OOO©Tú£²LQ”ÉW×߯ÊËM䙐µß‰DEбµµÍ¿~“ðC*W.—Ø|s.Z,g?s:c133+0»Ù$fffEŠ!R^¡P(ˆ<þë mmmMJã×ãç™À3¶Žo>vâ_‘eŒ±X,&Ò¯Ú†‰<~@¿I Tî/“˜ëÆÿIÄ,5âÆÎ“7‘Ä¢L­æÕ}msV8Œ± Žö*^mV£Q3҆äœg@øeMM„þMȜyó΅§ŠŒ¹8åép5BÈô*+ ú”‡£ÇNü}ΒýÇB4€üˆ<!?Ô_ܰòo}ÅÓÇ ùmHÛð»ëŒç²›‚–X5lвž§Î !ò@ä™@ ù£ÎsôæûêíZyXIÍ<üj—yyç…Lï̀‘¹wlÛ€Rq'ϑ$òL „Œoï†rPЈÅX8zÈRSÃÞjMË9F€7¥æDž oœžøt¹¥hàtlB²Êޜ§sFŠÈ3@ òF€ÀyúK:Øf ‰£ƒå—EšÈ3@ ò ®eÊÑôÅ»o ºÄ÷RÍÍ ÛK0Ïó‚ñlÁø'ÎÐe2抍w²$òL „<a àÜ¿§Oäú9ç"â><»²kåMßâÊ(àÕ_[û÷pòþ{Y6žéàM ^õâqèÓ×1zMÚ³§¯¢?$ò`z!¿!ے¯ªÏcðíŸ|dÌ eCz ”·òÀÀ±U#‘9K±5bh@ O|2kÂÌ4ss ƒƒFªÙ¶ûm-HIþ Ñq[ü+IJJêÝ»÷áÇIQyKçΝ/^ìììüKä&}‹0A«Ó1b¹ˆ2ü”±÷0¢>þmÒNÆ“œ‰õL „<¶ %“ÊÁĎÕÚ 9ù°‰4ÿ ÈÜ3@ ü×Ě@ä™@ ‘g@ ˆ<@ òL ‘g@ Dž @ y&È3@ „¯Bv #„ŒÄ`0èt:Rÿ B …‚È3@ üú=zŽ]»v‚ Òø™ÁÿÌc)"ρ—°,°gÏR??R©ô§M™{&„Œ!€×ëI9üüèõú,{ÿTG8ë™@ ?Ÿa™í­ŒŽ @£Ñ „Äb1MÓDž @Ò$!гiœÉä2šÎÇšyžùòejjªD")T𐹹ùÏSĹM „ì‰Tï¯^ºò:‘5¥Í8³8?|¯¶[qði2—¯QcŒ5MNKž”Ç›Xρ@0AÜ­ÓËWŸk޳·µØ€kЧœ}”žîò<=9üâµ0·.ºö&£f5ÉQobdvÎ6ß»¶‹¢(±Xüøñã3f0 “E˜•Jå¶mۈ<¯Ê×=ğ9”süMö»Lm⟮æ”2çj­Ýj[ÍQz ïßíê76nÝÉe åE¹Óè .”(‘çPdºÇ×®¶_¿gŒMÆ/r‘O0]4M‡‡‡GGGϙ3G­VK¥RŽãAÉd-[¶üQòLœÛP „ô烆¯ÿûá_«{»*ÓeHp"ûaÕÔîŽNî#íˆOãBt‡ŠUòñö.S¡çX@aN}qã,?77gWç «÷$r!€}k\Õò>Þ>%K—ù+#„ô)1ëû*äZž°ß„gYchšãók—,æU¬ÄÈÿß:yÚî$„‚Øû[û6tvpª2+8D#BÈ€ûVqëúµ·É,<Úµ`ýñëOO/._ŠDɲÝÏFª€K»°oÖԐ¿·ûÕØ{ô·<…àÎΟuÊ»»¹7Þ?CÊ©¥£VŸºŽiDÃöýç?reûŠÍ§­ïÖŽ‚›»ßÊÓá€$ìùœ{áÂEJUk0÷äÓt¥ #Um)Wº„··OùªBÞ«AôТÅgN.¯RqÈÈyOc1BpgÿœjåKõ,ÚaþQ5 „ -áåþU3¶;0¹cݱ ÷iЗ†Gãâŋ7kÖ¬cǎ–––õêÕëСC‹- vҝÈ3@ |ў“Ë¿Ý[+•JsڐäõµµÃ[ûõxà9{l‹wûúžÚ68ýŒØ”ßÜNÎ_|äÊkaO•J]ïÕ]º}ó ?u»zÝÞŒºrhñ‚ÃUf¯ß±zIœr¥)Õ¢Š]nUìœiÛÚé#F(EiÉ ŽØuîæÝ FZŸ¿òԟ±°¿AÝN™óÖ,Xt}Ë~Û÷ÞÔ|ž°§¯ÿ²Tÿå;—·;4Җ3X“€ŽzxêϏ’H<·€wSô?ÎÏ|gO¿œ:‘ŒPá’U)‹Ú}{µïÑ¡ˆ+Üׯý²”6³ƒ—Œ(2°qÇ«ñ`îÅÉeC»w]M†õkÎÇ><2«_³9ÇڌZ— š°û^4 Äun¥Ñs7ö,s°gëãîdâ@œ÷ŠËøy›6.i`·Œw“Ó Sqñ)§°kðÛ Öí›žØ !}ÛŽìp®é y×NÆÛ;•)¶C knÏì5lÖµ¢:4©øUµãyÞøÇÒ¥K###x;$Îm@ø ‹víÚ}Û;6¡žžžúõë›üVŸjà;.~²Ÿ‡4áyìµ+šÄ®[÷÷·M®~ìHPŒ: ÿ÷ôYïÕ«-V< ÍªC¯G •4IO"ßÉ›9­š"  I|sÑ;ÕÆ³z­jõ1lUšD¿)¥‚w’£fì®ð€DH Ÿx÷Þàœ÷Ž(.†ZE,+ö{FƒáòÝÓ÷¬í66lÒÀ%ºü’MŸ…kùÄF¿ãxãÂKWg+ ÆŒX0H0ΐúƳ÷¹]óêzÚ=מZ9øpôs/W£N-3T·]ÃzÖ }:ònˆgõþMËTv«ÀxLš{94±ZeÐhÀ¶÷Š ÛÈ^9å]g攕u Àê¡Îå֟ óád0™ IDATœ³àúª.UÌ ºæý›ßÿZðö2éúŒš†Ã§5Ñiï÷è×\»ðÚ{W¬TœÆßž :6¬nÉ·§^ iŽtÛ°M•RTvs’uµ!G_wmE ÉŽ²ÆšgGÔfr±ƒ›D" íÚµëíÛ·92hРµk×y&„Ÿ•Jìââò Kv†Ù³gÏþýûsº¡Aê–8„hg©µo1[™-ŠEÂ|MÏjkÀ̪®’¡Š4è™Ya0èR=jµœ¯Jdù€vYú>ހÓÑ%œ7jsVµàø³Á>Ê6+àd­ÀêÒ>t˜œ+!= ×Ê[ ̲šÂœÖÄêm«zy/j0såêÑ­ä­ŠQHh ’Zš{\Ÿ<¶Ïšû¯^?5,ZÇç0˜ÀÆW~qz 3¿m, ’ÉMü¥¹»^ª4`^vXÙê!S.Y{&4òåÍ¿OÜz§A ?“XJ¢OÚ±pçó·Ñ®¹WåÒß¿œY©æ#-ÌNXtÿõ›»öìX{²B±>ÅxÁ£–j&žˆÐ§×Íq@L'¿‰‰•¹yaÅÁWiz°ª4Ô«äÆÅ[ŽÞ|ú:üú¬QC­í'4*Bs<ƙbÿ2!­V˲llllóæÍÍÌÌâââ4ÍÜæ“8· ¡`@JWOK1 JjåRÔÙ\ €$.…<­ÌåÐ}=Nš8º“Çc+G×M—(£#võï;@*ŽՊ/ø­Ÿ‡@÷vãü‘Þh1²j?ó␊B­æ}íÖªJÕ6ý:îÛ`ãž%µ«—èwãV¡‹¶ï?æÒ5ä¯V›üg§ñ΍zlœ™6jÄžÚåŠñzՈͧJq1™\‘Béèäl.Š@nçæ*± )¹­———H µõi6ròÚÞc}µtÕÒ:+vî/0dNÀš@Jà Ë®Œ©hG[òr2OÌa³26¡W6Ž(=!†ågï¿ÔÚW H¹äõUŠUÚ¥çPfÎuûíÙ2³)ˆ­]lÅ` Œ;.°~҈¶+Ѭƒ[ôƒ‡µ[rq`‹!}zŒì;jzüâYã»;Æ÷ŸÒ¶fŠ˪]}5Þ •‘Úºaä__C€1¶±±ùû￝3›Øcww÷Ö\~ªÀ ¹'))©wïއ&EA ä-;w^Œx±³³ó·ý|ïÞœ{÷î=xð`6 Hïù3¿é‹ Ô6ÏüäFÎNf£Ü€Ûöý•Ûoí<¬4oî®Sç€ë©‡›š˜Òôן®Š(ô¥l|1_œØõû„?žö^÷¿VŽ_ÌOÖ-EákNi·|VÈ9ŒØ­×ë ō7RSS---˗/Ÿ“xÿ×«ˆõL a }šOÍÔ×ÿŸœû Œ¢hãþ̖«¹ô^H!¡„ÞCoRE)Š"ˆ (R€óª(‚ " V@A,tCéE€÷–)€—»Üím›÷Ã%Dy~^/w»³»³÷ò¿™%Å'ò „”Ê?(3„ÜYŠèat;~Ï|4þ É»GƒÐô}ËâLÏÏ¿PÅË,*¢ÜœŠØN–8Œ’%ß(šŽÿjI€–͵‹o»xºÞ>Æb[,vžE – pGKó®µHÙSι‘$);;ÛÝÝý¯ÎÆ3BaŒŸ*+fJœ(F·#«ýok·œILËaº¿ØŽe#MQ®——c÷¿¯eìmé6¯Ï3œf·êâký¿ÛR2åK-VžéÿÚ7ã!„þƒ)O)ÕêŒj5ñª%Šh(¥ 7y›ùž`<#„ЉRªÕj+Q+Œ"ÚÉ»;•$›µZme}…ñŒB‰a˜•+Wæä䈢È0ÌýÍ>†UUÕ{˜M ã!„þ :vìž}ûvGNçææ&%%‰¢ˆ}¹•S¯^œ¬V+Æ3BýÇ9î íÒ¥‹ãÏŒŒŒØØXA0ž+-Y–1žBè?î®–Š`9&Þ%¢A°³täØÙ|«@؀&íêùÕkçΚU‡»ó åߺ–šçææíÌg^=püJ– žE=ÕÆÏ‰š²-%>ÆnòoœÏՄ6n’|òøå·¬ªR§e§p†@öKNÆáMîá[TsáPkM9x5!ÍbhЪeU/Pä¢óOŸ8q#ÇX£A£È0o–R™M!?=53çiâåDïÈÆÕÝÓ.ï>~Õ¬€{óNmŒõ„R5/9îô± ٔ„GÖ­]ÓÀdß8wä\¢(SÏM[Ôðc€UˆÊR5'ñJ†ê¬eÀ|ãLŒèß8ÜÀ{dÇùÎÃ'¬IóZF†XÒoÙ9“šyæBF6­ýœu€üß)¢(8p N:`6›M&€ŠŠ¶mÛ¶~g0žBèîǵZí}¯^ºïÔ!ãDô&­+ç_Uº|ÖÌCûç—ǟp®k¿–6äý9ÄcÓ¿XC‰’|æjý!¿ü:»Vôô»Â¿ß:»ýsó‚O·ŠLšù¥ö䯉_}|ÕìTŸÞgü¢O_1ZS™Ô}­®“snB¶¯ê¬Ÿž4;F%ÖüŒ!_Ö örѲâÁeó&þvÉO'e€òƒgü4e`§ÕJ×wÎÿ6Ǟt=ñPlè Ã~øâðb]ÚöÔØŸ>}ïû³—äL­1ŽíŒÏþתºSVôe^Ú9ç£O/9GäÇfúü íÙm“ÎL<-ñ9µüoÁGýØÌžïÆœµê\®ÆYjÐ}Ȕê5«°±ãçÿ}žôž"¹r99𰡝Îórˆ£xŽço_5yÎÙÁÓç>å`›5Š÷…–?l˜`:>oÆÛW©rbszqÊôñ}]ß³púÊcf“öÆYe^tg[þ©a&//Ïñú…^ضmäää<ª¡pÏ!ôètºå˗;;;ßǺ,Ë=zÔÃãôGA_ôþ®±ï/|-RÑ8 笉±1Wšö_òÃü.5Œ’Ïq¿DówÑîûo?mMʜ-»µ?á³ ³;Ô¶]ÞpÌîÔ³Iej÷чLÙýë(×øeAµÞÜ>òåÝinRêq#û͜ŸF4uùéõAÛ, 6ÿØÓ—äÊžšÞáÕãS[žŠ—§÷Œ\þõŸ‰Ã4àhHÇwüøÑ²+cö{»f\¯&Ï­ÜÞŸ^Ä3Œ(;¿~–ÿ²˜Íƒüý譙ŸÎzŠïޞ{úÔ)·¡_ýôq—jî øËšåyþÔ©SÛ·oߟ}ûŽiÓºvíZæÉÂxF¡Êˆa˜û›’“eÙ2W€­O5Ð;y &°ˆ²>ŽñÛ#Ç>é ºÙŸM‰M2²i2ÀÍ< jv}¹õ§]¿Þ˜1ÛïèÍé™Ož7(7éuÒ¹•cûÒ°Y6P²rpÆàÜkôŒM ªO¯Ú‡çدOt¯W§ëé¢ç4î®¶IC‡ØíšÔÐ{€H‚K£>ïœñr=?üúµq›t"&  h…tKF¢Ž}ÚÐS†‚£Sž²©“µbøè-9 !ÀéÝÆýFsoÅ.9Õh?eäÈNՌwù˜³“zlÉ}724]ÈÊÝj?ût£Å#^ì÷Üs/œ<ø™zȹ±Sñ>óŚŸZ>}GOè÷eߋÉP•!@ÜZôíæþɑ?nÚû\›þed×·;EžJãNè}÷¥ÍôzÌ…«W Ö*zŽ}eÎýëûrE}Óf†eYÇɪœífŒg„*ƒ ŒïF•““ÓòåËïz“íXÙÂðŠÎZޅc„Øñc†_wêÔ2Ê=£óÒíπ³Wœ[™=-š‰`ö«ß£»'äÅJv[Õm;7g)}ºÏ€vá:Y¢Žøé5Ž2ûŸü[ðŸ}Û>ÿòœçÍÜÞ©Ïé2~ï;ð°>;ú™bȹ-7T@¥Ô×€×9¶UÇ5‹ š²hÓùµyöY°Ží4šaۖFÐ×ïҍ+°9îLb5ºÈ#š®:Þäèø–ì¢ÝÙŠS—ޔ’^ýÞkWEÃjOYŒžáêõ¿nØ<âü-nÑìnn €•ÊàØ$eÇÎý–Qȋ}žûbû†u‹g¯ÿ¹`ØîŽ®,HÓ€GïFz«œK¯* "yž€P_£–WTG äïn™–$©Y³fõë×ß¿ÿÔ©SàÒ¥KÏ!ô „Øíöû^]År"‚ãMpnþ^ñ•PMa ©ª¢€_ܲçÈK_Ïù|ÝoêšG8Î¥ÉÓýœçŒöivÛá“çW—ê=XÍ·ëòkOØ2LCmY©ŽX¢ È °&^Ka«µ}¥Y槟»fW@Œ?pàL»Ûßì,ôÖYµÝ³@ç¬IÚ±uOËó­ÕË8º8:G?¹MœýÜÂ}j„^ۓUPÿÑ5„ô|ET Í lVցQU-ŒŸØ³N•þŒŠà££¯Öõ!ª5+M…üŽ«9®œG¿SSÉl3óÄÙTs·ݘ‚Ù ¶ön9&\oŽž?”B@Ÿr'£õ{?ïñë’q““›¿÷lm@Õ Ô?vg® 0›sǬʊêàýw§FUU— ì«W¯vŒpss«œóˆáŽ$!ôp°m‡ŽË>;Žv£š­i ÉjÉ·+ °ùðŽ ßxÊÓÝçj‡î5`[Ljé¹ÀF¶êÞÒÀ²ðb¯úà1iíÚ×£6>×< 0(Ð'0|g²ÂU0çY¥ÂÙ6®,ûŒ‡¿[@ïW|ÿ÷ZWg xDöè=#ýkvèkìÛ5õ÷¹£ßß]À°ÙöÔcúÕ ‰šØùão‡4öJíùªETØúÏŸþù¬î{fEzøUq3:²fŸµœG2ª’œÀb.<ð™þû–á :Ôõ ¯}(‹I§Þ‰ ò òo:cCý=_ÛÀwFôªî)³[‡„œŽ¹Ñ²= kH’d5çÙdGQÞý^k•#W:ú;ë€woôýÖÅ~ç{y{ùzyô6î: ÌV«¢þ}ŸBŽZmëÖ­ƒƒƒƒƒƒëÔ©sû…£¯»ÒýLĹaS999C† ‰ŽŽÆª@šbõïßîܹþþþ÷·úªU«V­Zµ~ýú»Z˜D n$\˗øÐš5ŒŠ57ÏÌ;{™Ž µåߺq#]á}¬×¯¥S¯:µüˆªXrÓ-2çåíÅ]UµåßJNN³Œ“«É70ØÈÊù™iŠ“Ÿ» BnέԎ\A4ºûøyéy–€’—qýFJŸÞÍÓÛUŸ™˜ÊxUñw–3r­äÜì\Ik ®â¢ã)U-éIv'O#ŠhNKIÊȱózƒw@ »“¡Ì‘Û²`É3[u.žF C)B­¹©ÉÉ"crwö 𢧶ŽÄäÌ+£3ùž9i €jÎLº™œmWYw¿*þ>.<EòsrgªhIËÈvòðuÒj¡š”“v3%-OaŽ>ÞÞޞԜ•'±ÎÎ.Z®ìÆóŠ+–,Y2g΋ÅÂ0Œ¯¯oé¡õƒÁÇǧ²}±s!„R[ˆÑCª×)Œ{˜5ž{ pæ ¢wö«^Ë×qÚ%²Ž/Öäîg‚Â¥P Dïìîì[ìdÞÅ;ðv9:W÷W÷bŸR ¬‹wX¯Â·œë¹;^8¹€à±Î„0&Ÿ*Š¢¢XÉ?€Šðí²JOùA)Nçä¡srüá˜ÛÄàêáêWlˆ–Á/"ÂïÎvÅ3&Ï*‘A·‹€”²ŒÎÍÛ¯h `4N~NÅVBx7ß07ߢ²(“‡WÑ}ÙYUUOOϐFSúÓ{˜àåaÃÎm„z(ùL-|QbŠgBqôcÅTÑ"w­]8ì©h"­Â&y‰%HÉO ‹¢w¶ ·?,jÒÝè-³šbe‘RV❒{xçUQ9Åvévñ%ö™”ÜRêànï%¹š%¶~Êë0®„Cž±õŒB+¡ËMƒbòׁQ"ÆþúÓÂ×¥ŠŸ‡ºû­_w–uŒ*;Dï^ꟕ\9[Ï!TÉÊX x.°õŒB•KzzzBBB~~>æô£¥ÕjÓ³€ñŒB)(((++«G„I’l6›ªª˜Ó„cÀWïÞœ§ÂxF¡'7ZŽhq{"*UU¯\¹"Æó#$Š¢ÍfÃxF¡'×]1œ››‹ñ\I~9=^ó|`<#„ЃÂ󌳳³N§Ãªš ñl4ïïI'Ï!ôŸb4àç£F<ð8®rÎ߉ñŒBµ¹ÆqÇá?³•îŒ<×ðŸg„z *8®ÅZãöO5|ÐàWfÿzÒñn9KÍMŽ9°ý×éï|wSÅó‚­g„B  !ôæþ)~š]sÀЎ9ï|ñA 7w~ßêÅŠì.k4öµQ²ó¬9ë[Ï!„D:ÀÁ_~=ÇvþzïvώønDäùe_&Í^:¡}?žûÃҙ/ˆŠG¢c<#„z@霹ïjN­¶õœœõ„a«7i#Y¯žL„²&óvtn;G„z¹;éŸDŒñŒBèA }õfA^ §Ç0Àû„†*ÊÙžÔòWÀÛ·1žB=ðˆ&„IQ MIEJ!/ςƒñŒBèÑњxÂQ–¶ŠEIe¡ZžïíϋO³u{ҭ‘Ïe<'a<#„úw("Zxžùã|–U I§v'°^ CL ÛnÝHHɶB„ŒŒ„ë)fA"„BU T–ˆªJI¹ÃÈÆ3B¡ŒP  é9š«ÿå5ËÖn:°sÕìö5é8й ä§^új܈9«/@®Fžu$.rvGoZµã€]ÈÙñkôÖß[ ìadèßÃûžBèÉÌgB)8Õ~qü8é§m¬;žGÒ€rÏF­;©žàT§KÛÀ@®^<Šø÷|6(óò)Ñ+¢i×V&¬Éöû ;&K999C† ‰ŽŽÆª@šbõïßîܹþþþOÀ±MpI©€žuŒsg^-ªRۋ–1áVÙï"l=#„ú7-hRÑ<[ÖŲöv6Cysab4?0xí!„žøˆÆ¬ÅxF!„Æ3B!„ñŒB!Œg„Bã!„BÏ!„Æ3B!„0žBè¿çaDõ=ÁYÃBšÂB233O?NŇE 2éô†¶mÛb<#„ÐCµwïž^x1¢ÑSŠ,bm Ò?ᮝݏ­g„zèÿú­ÛŠ÷ôÅë ÌØÑîÆòrö^–ÄxF¡Šg"K¢%_µYò°6ÐÝ_r÷¯¢§†a<#„zà(¥„a9BeE-;~(¥„° KTYŠòi”RB†ãª,«T}ÔOÁ€¢(Z,†a ƒF£ÁÖ3B=Éy „á8†J‚¬š8Ÿ!j~v"a<œu@ØÒÛ%„¡ö¬Ì<âìíÊ=°t”RÂð¬bNœœ#p&=óHí©*œråŠÕjÕh4¡¡¡åÅ3ÞX…BkâÃiX†ÜÃP#B"dÇ[÷ÍÅùǔ•dðO ü;ŒxzDŸyǓõVÈŒrlý·—nšKl—á!{Ïçã;Þ™R?(¥”0˲ðïnW#„åä[¿/›øáìÿ-™Ü÷ÀŸÇEõ^2–gÙ‘6›Íf³É²ìââRnýá!„O„ªbòé-W®eq÷$„HY çûæü-™g˜²>§ª"$Þ“ÍU@2QÑ)Î PJˆ˜î·Ò ·[,nå[7Ë _°lþõ£Î]ìò¿iè–·Ý:{8;ªÅ»~ØùT«Æš¿?2ÂplvÌîsUõŒï#„pwæÌ777wwwbÜÝÝ}}}%IÂxF¡‡ÓÖ¥„᎝A£Óó<Ž°Ã™×ê5:Ïó€°é §e†áŽZ×ð€0ÒV£Óè !(•/L|myªj2@X–ã–çµz†!„á4ZœFgÐèŽ !TQÂÚ¿ŽàÞ ]Q& È$ ÿ IDATDzœcaNÇ2„€$œôÆ/éà(°T³•R ¯ãXBiáÞ³œ†!„á ÷MWØè€Àè@KU©)¢ÓÀoô¬ï"H2¥Àò:–×jŽZŽ'`td/ÃiŠj†'¬“Sö’¹?l?œÇêyŽ „嵝A£Õs,ôv ›cXF§cÕDKî.ax†çŒ|œC#C«›Œ–-ª­–!Ž ìíýgÂ99¥ÎxûÛS×­e¥À°ŒN£3hŽ:ÖQ5”Vò,Ãi5:Ëë8–)¬`Ø¢NZ~BçååÕ¯_?###&&&>>>...666---;;›RŠñŒB#›)a@žºcvÏÁQºÁQ~3Æ, NZNž~`îÔÞ~ƒ£tc'NŽÏ(B,G>}zíïû.è1(J?õ­I‰9’F£³N¯Úàµ(Ýà(ÝÎsI”ë[&­ò3þ×ýž \³™/­Þ°dÚ®_ÇNî¶çTLÒߌÙÁmp”nH«gÿˆ¹Åó¬-í̞…ãÆå霮I¿Ï^ÿÓwg¶4¡‡çàšZێÄ [§¬·e§Nìôîs-ŽÆY5ü]·1,oÞ÷aÔ[¯h8–0Œ5åèŠ/‡î=›&ÞÜ?whÁQºÁQ ×n?&+…©DÖԓ»N:ŸÇs k>÷S×ñƒ›uŒÞz˜‚š’åÈ÷CGéGùLûI’…ØÏ¯^Ÿ|:wÓ7_>vøÇíSk͞>?[`nüâö®ƒ£t¯¶éy8öϱ #çÅoúfxœÁQºÁQÍߟ˜uø‹ùiâ÷S>h©_¹ë*ǂ˜uäçñ Gé^ëÓ"úЙÓñz>níš_Ö®9ü]çW[4Xý~ԂµG9ž# +€ŸÚüՈ-ûãy-ÿ× ­V˲¬§§ç®]»RSS=<mÕJ€R*p†ZãºüÉÂ÷]Җí\vZS³UgÿÀŠ]úÎÛþTÛzŒ65ºKÓèÍÞ[3õÃqé ýÎÅÉ „›—¿·ü€KŸ‹Ãý܁޵¿ ëÞüéÞUýÛÔᅫw¿Þ.z{NóÊÜœó6œ~±Ó®e£6‹F6ûôÆï_˜fìú¿•ç?XôYíZ.Æê[r:ÿî/Z°»U=_{Þ¹_žëz*}ÀG›bFjzøWÖ/?Fuz5ÿò±¯†-Ij3úËjDºûjf¢]ÃCÁÍ3[NM ®Šrã+V¬8yòdñwpä6B•`2™†ê”ôOB²33B«·PՒgßº ïüßZÕ2ØeÕ#c³ãN\¿àÚ³_—ç;ži¡÷äE;Ž÷<?>°›Ì‚©×Ò9ôožŠÜ#^(Z靜S¯\ŸŸÚŽn='£(è}ë‡Ôgâý…Fø‹R­6[Õvý†Ïé^×OŽ‹5ŸyÍjɶÛ%”9‘ecp„èš"Ùl5úŽž8·aՀlÛÀ[ŽfÛ Ä¯^p6É¿QXž¯ ÙrScoÝLQ€Úy¯:¡AŸ!]Æòßõ:xòӞU3 žìÇc'g›Ù.3<å98i“ý\J4ÿxBt Çd]:~µÆà Í×vÒp¯/ûöpïE„ÕxÔ~žÕb6gsZ6­@Š4íj»ž„Ukìí¢¯nÚì°¥3Â}@õèßí +¶-ž‘þgµYëöõö‡ «ž©JnâécVÅQó”pœK`ƒ7¿ên¡ ÞÕ녆úKv¹Æ3¯[-Ùv»šc˜“™ùBFâîÄà#'Ϫá%I~A@)k ®¯¹ìR£!GÔ̓{þ0úŽýrr«X¥ËÛQ/\Jژen©š­övS?<ÆÓ ¡“ž=öžÜL¹zð°.thõ­b±’¿’Îó|RRҀ<žqãÆ={ö,]ºÔÑ€ñŒB%äçç¯]»ÖÕÕõþVߌiÃď²wœ¢„3€VÃ(Š ”RU%a8o'Ï©ªªRÎDu bfl$¢~-Æf“»,Ê,¯WDSÓq³r?·{z·UΟ?·M- ¢€‘R•RFUUow£I‘†)8³îãÅËÖ0ŽŠ‰% W<&šr`h5WœŽ*²dÏpá P*J ¥T¢”2¬|ëЪ5ߟ¡7°ŠÝ>xÅp/Þ5jHç%+7E Òŝ.hñýSzÁê—å æÝHr ͑ÀœŒ.](_wœ+ÇPJUÑ.*\Û±`bôŽËÞ^~ªè]•%,€¬ª •)U(¥¬–w30ŠªÊ90„€ªªŸŸ&VUT–É9>{äa« (U5nU:Œ]âï!P›ªÚUU)a™‚Ókg,^¶Ž…šþA&–axÂÎÈ1”cAU /DE•ª QU¥ eµ:–„:ë@QU–á)kdTBTU ÖPª*2ukúZ—ïgýÒzvðåSY ¿ê®ìÂßÝÐ-Šb``à† Ö·oß.]º@ÑÐ9Œg„º»lµZï;ží‚aÙÒ]š„ãLɗâ„ÐHž*¢(Âé =356+_vñàÍ)G%Áš/ºZ© B€ ªUP|:ÏÞõŒpùǧëþŽvo«È— Rnre9"«@•eU‘ «Unìøö˅/.Œ}ºqЅϟž'ŠX DEõÎÐdªJ¥Ü”<• –­ºý?ùhÈ<†&º"XQª­Ñë=͈Q#ój÷kî!¥ÜòÓSӑ߮™X°nÄäK瀰ŽûŸJÕ-§‡äëÉ×òlŠ'Ÿ{æB)Í:»4zû™÷wåTË?ð㔷³TN5§åÚ%BT`s1.£FojÏ1§\bO ODU’šªUD©Jÿ ƒŠZ«”*’Í,ˆJÑ ¬V¹±ýÛ/¿ëÿ}|÷†~çç=ýé5™0¬†eÙìÜŽë©nžªlS€cAËrjîÍŽšTc={=74ÒIÊŒQ‘Ê{¶bYBš¢œpø—ÊUëý ¿å­ï?dêöŒªé-ÙóþvÌùíNš×^{-88øö7ã!„ªÊ\•®5ýyî`’÷ºŸFQžÀýú4nÒû«·ü4§~U—Ë;Ÿò®>ªnˆ'€M‘šTxՒª²*Ʉå b¶/œžO=‚ôfêV…£u Ž[2cwµ×ë5íFTY–E•U9S°‰ÙµÎÚ¯íˆÑ .§viBIPT „PE”e¹0ZšJAUVïèeьœáÃkÕmëÊØl¢íîc¡Ôѹ•뀝Ç/ôù|…³d—§óåØ=¿/µåí<ÄÀ­S;Ž„ŒÔTÁ1FŒREE‘Á)žqƒö_oýmƒÎê/å>º œ°:WWmÞá•s¯d‹¿” ÂÉĘ ךu,K7íô×·}nhՀŽœ6^÷ýDÓ­§H橇’uþŸŸ3ÄK¢,K”:BM͹w=‡„°*Ȫ¢JUÖTÅbv.¡§…k;bŽÖŒSûãš×¡¹vǶ¹oæöìJ²ÌA-{ÔjP׳NýÌ9 ·W³4~ê%ÿ°®OU[¹máD¶S3óÕm I­»ôp5@‚$H\áy"„‚Ûu÷qZ—žÙêW=¡ÀFÉßεrõêÕ͛7›Íf­V{ãÆ EQŒF£ ÀN›6 ÿŸó8aÆ ýúõê@šb­[·®K—.&“éþV¿|éâÞ#g[wï/‹ö;!”R]H·îܹ˜s1i©Y:—Èêõ#=ªÖ õSRÏîœz9V òÒä×ýŒ,•,NÕ:…úTU–%Æ9š^ÕÈ ‚ G.Ÿ9K›œ2šo7£–#„w ª•u,?+? A'0ËZï€ðz.zÂ9Uñu–®_ºr+¯ÅÛÓ|¬7R2œkµª "xTkåëʋ–p‹0hX*[ ”к­êXs@dvös®- ^7M·ý @\ÜÝY·êº?Ë)ѹyº›ÌÉWâbnÔ8ªš \U";6f 2ŒÕ:…ùÉ®PÞ«Z O“³OÚ1õVì‰ÌüÇ¢²{–Ý=B\ õʹ+Œoxóçú IZßðÍÚ«lzòå£.5;xø…wê䒲ãìé ™yšðӞ}¡9/Ù%k8‡U «nԖ7ҙ€" Œ“՚^n:Î)ÈÏ$&^º’–ßâíiÞÖë)é.zuh©d¿zéjV\§©·««}›p5åÊY¯†ÏxúVmÅÅo>{æR®Öìåw[·®ÆÊ²hÉbýU àX@tаáÔÕ:Ã&ŒaPíjY3¡B6ý8kذ×$Ib&==ýܹs—.]:þü… .]ºtúôé&MšôêՋàÃÃS999C† ‰ŽŽÆª@šbõïßîܹþþþ÷™îkV¿ÿùòwŸÚx÷#1(†ãuN Y)§aˆ,ZJN£cUªáÑ.(ªJ)á .Œd¶K !,§Ó±T²Û$Ö`äU$•ç‰h•a5:žeUUìÀèxžUìVY¥ ¯7Y"œ*ÚKUªªpZ=-’BYcTIŽ«*%œ^¯gK „q(©ª*ªj¹×NYQÃ1‚5ÿö^°ËQEP(Q»Ìꋎ‚åyÎ±]ÂpZ ¯ª*áE¢+X (áx­‰p*ہ¡Š$«”Ñi8E%ªbWT§Ñë©h²¬jì*Fcà*‹Â_ÍìÍð-¯JvIVʬÅ®NËqŠg[Ï!„þû¿–dY&„0 óž\wÀxF¡'%€Š?t¹²ŠTï'Ã0¹¹¹IIIùùùÎÎΟŸŸ÷xÆ3B=®‰ pï1FI0ßJŸ¥ññ1ñe#Ü.ãÑå7!¬Ù©iùЧ¯ŸIÇþûâ RRRòòò†)/›+áïŒg„zLJ•ŒŒT;çéã®»—òN}=y†Ç„Õ“Úž—•d”ªjnfªÄ{z»éá%nûá“Ýy¯Ÿ7­C˜¡BŸaœ^èСßÿeïŽü°°°nݺaë!„žÌ¶n±Æéí&”n³•ݐ+ã]J ¡ûƌÙ1rɂ–÷”Šz׀–ÝžÑÊiŒP¥]o;4zñQºrvåïۙ¥—(oÒUâàÞð)j÷wєW>”S\9ÆÏ>û,44488XUUN'!$==ý… qqqÏ!ô$f3%„€íHôòEÑRp®Q¯ïÛc[벯\Ždí¥Ä¬À¶ýÇœþŽB„ÓkVdÕîîumý§¿\¬×²Ça=Œ5Č-_-ÜzþZŸ" ùàËöáî‰{–Œ»r}lj•šmÜ¢†O‰T.‰Ïqãs6­=Òîq5hì¬oVæ[íZcË·Š÷¯íf`ôßðpœ@êÉÝ÷j.™ßýšçÿÚԑ̓œcw-~ï×57nùGŽõ‰:Ÿq Š¬¶šýôšå™µ:{Ä®ž³özÔSý‡ª¹qÉÂßöÅvziø‹šx&åô¶é ։2qöhûÖû}#LÚü€Ë'ÏÅœœNìˆþ#†ïóæšÞ-ª0D¹°þ‡kU;…&¬žý[\PDÛáã^ 6çáb\4®nÿ9ίM=ñíÖ»Ôñþð.˜“ö/_üÝÁ˜Ð‘mÚ±u„Ÿ3ó—g€R:kÖ¬úõëÀ™3g/nތٱcÇJø•Á«Bèîǝœœî{uœ^_ÆÍ<@X£Ÿëóò럛]B‚Ü©š+€o_1Ší”œIµH¿sËÞ~ŸËŠ4A.=žß Ã<§ço®õ΂ű°sÎÇ_o>ç^ÕÏÉ`@jFŒFÊ2ù×þX<ŸW×÷ŸÈ.ìݗ¯q¯V=8ãÈøáƒ÷@Aê埿ø`íU2Îþ6ç­gڏ\”€ò‡Ší·.ŸQm °– UË9Dñ؏c^éßïÍÍ FùúòwŸkÛvØO[“™ŒMž~ðr&œÛµÇêä{ܘ·þkÊٟßëÛ}üg»³X’žk°^Ï\`έú߈~=_ˆŸæfP.™8öÝyG×Î_úÓÙ ®í˜7iP÷§ÞßLœùËëÞ~ëõ=wéàŽö#Øf ¯åúç×3ÇŒ<ãhbŽúw§†b±X¯û÷ïïxa6›+ç(9l=#„P NNN#GŽÔjµ÷Óâa˜„„„5j” ·Ÿµ~{ǹ»¿ÙÖÈ*6»bTÒ¿ûmù¹ ˆ¯æÌj®KoéÔ~rôÅÎÃlTHqiõÓ쉍ùžéÃÞ:|ä¿ÿ}BݱƒÆv®b ͞Pgâé~#F¿¬wýž9Añìðâž¹ýZú:k-Ïœù”7lI›öÌ×[“¡»*ŠÝ*•š/ žÏœ2êÝ­3ë$EŸºæší՚QÏ÷¯óAÌK£Fõ”T° –‚;S˜^²Âš<œõ !6‹-%ŽëêÇԕ.NüúN{ƒ_Oš§4oØjQÜ­ìŽuœ£^žÐÕ×Àúsü'#¶ì̂vD’8&}GýJ{Oùìú¿>Ó¥~ ”Ÿ\{Ìþ÷߈òcÿlâ>òU¿x· ©(Phö±áwïŒ÷bãÀ£.矙·: :Ÿ?Žz]nÖÊý3Ú¹íêù£(ˆ÷r‚t:݆ >ýôÓ+W®4iÒdÜžqM›6­œßCŒg„*A„áÇ{{{ßÇüfãÆG-ý‘")Q]Z›4,k4ˆé²kXTTpx7ëd2œ—a¶S0<5øµö¡žrFšÑIOˆdÒwÖÔÝýLj 0<3yÛc#œt¬V§uF À1’(Öhü|ûց.:°'hÒéÔœà`/0èóe` q ږòÅj­ºœÔ­…—†±;»1`V`uÚÛòŒíЏÆMù2Ñdä$k~‹6®ÛIÏòTï—[žÊéF—ȰºÁè¡ \orbAeÌqۛ·žV „ù¹Qo–TEñö oÞ²¥ŸIìê~)ÇŠUdÒŽõ3mÂŒ” ˆFikŠY`ÃâÁ%åHú~¹U “³+ËÉ ÈùVÖP£Y«FFðŠªãîëDšz/'HÅÖ­[GDDÔªUëûï¿÷÷÷ÏÎÎÆxF¡Ç€¢(ááá~~~÷·º¿¿¿Ýn/ã)-6lX–d)Ù"æŠ* UUJ€šà€a€RUU)Fðhð̲?[$ÅìÓcxóOÂsæ= È ä+SG€st­gîéÔwxϙ놶šŸùÍVÔ»®eR ˪TE` ª€38 ÔF ™Ž¹çp‰aUU›–c€ ¥ •H €ªR ,«UR·¶ê3òÍŒTËçÊÊ7_øRf :¯78ú$t !zV%”R77“£‹au<£hJnÿ2¢ 8ñ,È*刪È@x(•r,bEЀ=.ޒm'Ì=řªªîîîîîî#FŒp\{ÎÊʪœßCŒöŒBwû7ó>–·®¶N‘ãÚœqðfnAfÊùs¬†ÐÎA5N¯Ü±ìàMÛÆO†eY:?UӛÆ' €*À° ž:|$>‡T‹zêiN4g‹¯1H'>XŸsgë…É&g%&§g»žxzéR~±–hìSzä88¶ †çxëñéò€2z÷€ÐАàààààÐP_WÝn&¥%® cˈOÉŽxžyºÂõ§ldõ’@käÓ^7wuÀ=s—^ûtidNçÆîz}êþkyÔz}í÷ó’›?[ß(Jʝɝ*¥@ª2ðõkFyü±îµ—f|÷ًQ\º•Á³ìœœšÛ×,Ÿùæ›Âó¢ÕVÎi>1žBèÁç=@•/R ûŸM7'¯j¯Ýh¶Ó‡sŽpÿªkB =š³âØòfÞúâ1Ë0˹0ŒN |܂O:Uõ$ÄmßqÝÄn,†uî<ê£[±#ë֍ړ:îN”qÕû|Ø'hj:NÞõŸÙ wm»ˆ9&#SÖ®J€(á©#«º2ưÏÿmX ªŽXó™Ò¢¿x­3¥FPõéWVïÿ¹zΖ5§'ϞWÃßÍŠˆ›±M›6%%U­ZÕÃã’þHD£ìììž={b= Táúõ뗜œ|ß«¯\¹²wïÞe| ªŽÿ –›\øŽã-E²[̶;Ë©¥^QJ U¬áî’eÁjKnªpUÑZPX„œÀ*ʔ–Qr±×E¯dÁj“Š¿Q²ì² ¹«{AáŠU¡ÀNéÍœ‹_íÕ ·K IDATqÉe‘RɪÜYoq;Ò~I ¥ÔRžÉòö­Ä>Èvɚk“TJ)=¿¬{PœŸ¿_ÎŒSKÅ,_ŸŒm۶Ǐßœ{÷å˗Ë;kålèQÂÖ3B=„8šœZ£AÇÞŸšR §1:éŠz›ïÜæS↟ÂEœQ{§ ÝñV«×ñÅ{Õ !Ž­ñzq4Ã5=ÏÞ^€xÉÅ^í"«Õë8Ç–qeí)UŠÆ` @)Ñ4£M»Ê'Ú¬œž)và¬Û©  7YÞŸ•؇ŒýzûÖ:aLßæ]†om7 _Ã` y‡”,Ëe š„÷VáÐ0„zhMJýQÖ{÷°zkßœr±œ÷º‡lü'z§÷öfý\×#ØPrÒqïÆ}.UÿÉ&)ñj×}ö‰ÇNÆd u~zo]ÛzþL¥~ÎÆ3B¡J‡R WŸÚ®>P"D)¥R¯%ü³d%”R–×W­ÓŠj6Å·ñ_ÊfŒg„zÿ°røOëßõÜÕŸÿ'ÉZæÂå•pÓË`<#„ÐСC‡>ÿüs›ÍæxVVÈ£Âóü†yÖÏ!T‘6l8pàÀääd†a 233EÁjy„ Ýœ{÷òF„a<#„ЁR1{ölǟ‚ ÄÄÄ<ŽÙðŸA‘$IÅÇnÏ1žBš"àøŸ‹Åb±`™g«óâ÷_`9µžÿ̝@H±ç,ßçô/’a<#„ú·éLŽÿŸû*i=n@õ»ü4œ·Œcá‘|(6?÷ÝMmBUIŽ‹rá=ÜT•%QRTJŠž£0žBÝ?u6%Û¿Nˆ‡› Õ¢tšìã1ye/O5;ñäªÅ_ÿžvWbž Jæó·þú˚=§¯Ù „`>W8†BOsZŠ9ÝÉÇše €É»*Þ¿š M\Ê^>mÿÛŸµ 43zʼnäÚç|ºülÃ>›vìž:dæˆÎþ«ã!„пnA³„° šE­^™(ª\ÞâiÇvšCº-šû*wzÝè±³'ýiø|çÞñðÏó~Ú|:ûcV8ìÜF¡'ÁÙYã$ŠâÈg)?WkU žýù]—“Yžc'˜Áœz=_ÆÉU£ømoÒÍø«‰Y¬Ÿ«[Ï!„þ-J0~Q‘¡¶ŸÐœƒ_u׫V]µGŒŽpÅzþÀ®$Sƒnƒ Ò¯;“àU³Qí W×zíj­øù»o2uÉñܳo ןÿáó‰ö7³õ>®‹UŠñŒBèß"@H£gút¹0kåӎÎlŠynć Üɖ÷ûW3ö…MëÖ8('îØ’ÏV59³v+ç×áÍÉäÀ™{@¯/wr‡NޞÕcóH`dóŽÕ]ŸÜ)NèiÂñ©œœœ!C†DGGcU T±ú÷ï?wî\ÿÿòõTGœšScŽ=›b–\ŒjuìRßTUíqGgk6¯çgÍŒyñb’GDí0Ó_Å/¥ôñ™ë[Ï!„*qˌPJ‰É¯z§^Õ•² J ÃꪵèàÈ\ƒgP“¶APtßóí¹0KÄñã2Cæc‡†!„ÐЀpü—#›Òâ1[kÖ,ŒgŒg„ª\ªV­šP³fMG÷}hÚŽéСCÓÃOMM]¶l~ 9ŒöŒB%4iÒäÔ©Sÿæâ«,ˏïá ‚pW·”ÃxF¡G¯U«V±±±iiiOl,‰¢hµZ“““322DQħRa<#„P¥Ð»wï%K–BžÀ„&„ˆ¢xõêÕžžž›7oÚívü>`<#„Ð#æÈãŸ}ûÞºuë—_~yœšÞÞóz”RUUÝû,ËþEE!Œg„zHmGGð̝;wɒ%{öì¹Ýµûï©ìµK¿KËYz%–|‡B.møaéžøâœÓŽdŽü£2‹-2L){Œ1žBè$ŽÑhÜŽiÓ¢E‹6lØ I¥ô®»Ríæ<‹ æìŽŽô¬³€!D¶[ l6ÁšŸ™ži—Uª`ÉMKKKÏÈȳŠ”Bˆ" VÁV•‘––U`—%U rÓÒÒÒ³²óeGi¢­Àj¬ù™Ù HûŸöêÞžŒÌ ‹ Zós-v…BQe»ÙR`—TR~ÌRJÍfó̙3ÕREÁï Æ3B=š„6 ß}÷ÝîÝ»?ûì³+W®äææ ‚àæ¿h;–?‰°úõf|3mTg_ßàz^X}4®¬ŸùöÄ ŒÛ¿FXˉYù÷œûb·*áÕjDÖè9ñ›óI $î\ò¿QÃޛ1¶c«ÚŸŸa¯~üKF €^7Ž»opXd“æןL€ž-ó'LýÞ{ƒêEvX^ÙIªF^ùM J€ªë¬@ßÈ»UÌ7Š Ó/‘ëV¹›sÀfñˆ¹áçïŒZhòüÀxáœÝa÷“rª)aŽŽ+E€ë„“A‹ú˜ð EGBUÇÌÄÈ€f ðÒèHžeë[wÓNó™)ŒoޝC$Øì”””ßÿœŒŒ<((ÈËËËÇÇ— ,Ï óa¬Ù$I:;;;;;ôùS§NíÞœ»nœpÔRJ*¥HqH hÚRGMɪdUåë8EØ$…™ O…Åè(M!ŠÏHKº/NI‘Ö°)- —¢ÍµU”Þ*n•ª fRǬÝÂÞFkWý®íVV©kÞk@k@ð‘)^"‘ÈÆÆ&22²€€$::ZQQ‰<öŒÁ`0éCÖ,e¡PXßð3‹Ï¢ÿ,Š <áÁÝjUƒVÆ<ŠF”XR³I™š‘zì!âÜ{çŽrˆ¶†Ê@ðØ… I 2@’uív>éd­ÏÒ2µ0¶›ðð‘#‘»—Ìš@# $RšªÙòŒ£,J‰I2Ò¯¬ëâ9™L ›<Áh G @™ÌP¿eˬ͞÷ŒÁ`0?b…ˇççœzG‹¹¥YÙÃvV†;•ååUªRšvܲvÞÄ-#úþe§ ÊO~­°*À Ã.ÏOØ>ßûÞAõŒ‡§G̝Ö]ÀSoŸc¥ßôM?uŸÙM‡U¥aa;?x-!©ªš„ߏ+±pÐÐss6ìmÂØuÞV=˜Ðê? ;ù1Ã6A$I†……%$$ˆÅbÇÌ`|Ü$–g ƒù‘J ßìÉ-«ž—VY¶îÙ£#X^žÊßB›8Nó—G¶µœ™RŠØJSíº÷r2±P¬ß±sÏnÌY…e=ûwÿy°@ƒ€ÓqɪWûž'eÁnfÕRŸV?ßå@ ÇeÞ(ø90:ò§Œ"±‰ \ERՄï(Ü_ÀhpJ@uuµ‡‡‡««+Ç«ukøðá87±Ð®×š–œÞ^AiX¶ïôö7¡`ÛkŽm¯÷u=U˜œŠÔo­Ç˜æœwWB¡u—1­»Œ»föÎfï|#t=†{SüÏíóëïrïŠ ŸFQ”……ÅÀ¹\î‡wÑǜc°Ù/-·Ÿç¶SŠk¹}O#ßÌÚ^M«ëŽZ¶|£§›|ŠºR%‰ê”g¬ÍXž1 æÇ€tš:«#Éù˜Àœ».û¥cçôKÄb±k=óžuú'w‘<3‡^^mIX_±2m‹ÅIII²S%Ÿ ‚ (ª¬¬ ç&–g ƒùAše.++«šš‰Dߣ¹!„ûÐXž1 æ„ÅbñùüÏÝŽéÈ3ÇÃãÐXž1 æGCII©yóæßï˜l6›Ïçã|ÄòŒÁ`0?!.—[çžß]DpË3ƒÁü |Íå¢ç×öžŽg)j¶ëîîÒRëÛ $Öæo>PƒÁ`šPO• ˆª._œ>þ å>Ú|!µ‚ @ó庙^wË Vo9¹fxΙ‡Ù•X›±‚*ô²œ6耪ÂÃ]gÜ{Æ`0Ì×B `Ó#J"Xl»‘‹ûé_ïé÷Hâ}ñxÀÌ!EqgÎeüæ=ž™Š#ùÜ{Æ`0Ì×è3X ñ}=cÓì)ˆTµë1}þ4 ؊º|eE’WՈ§ÀDp”ÌœÂbŒÞöŸí‹š¥²ˆFùö7ŒÝP !Dðn{1Œ'î=c0 Š1{ÐÉçñëRY™63+ûíMæ©wbmþÎÁcÏ ÓôŃåƒÁ`0 –g ƒÁ`0Xž1 ƒÁòŒÁ`0 Ë3ƒÁ`0Xž1 ƒÁ`yÆ`0 Ë3ŠÉ"Û*è+ýÁ;Ç}=M3 ¿2TM0Rž¬âOà¿Þ5ì»Í96ÛÚÚcÓÆŠ¢JKKqÂ~Aê©««ÑÔ¶Pdƒ*..þ\·\.WYY¹©EJ±X\^^Ž·ëh"4Í҂åóÍ (*55µ±ª<¡Pxöìّ#G*++ãŽý\Ο?ïèèÈb±šNõĄD*•Þºu«_¿~çÓÝJ$’N:íÞœÛÈÈšéÔ¹²`”––nÛ¶Íßß—ÕŠ€D"ù駟vîÜihhˆË3€Åbéëëgggœ6oÙ²%22ò͛7êêê8m?‹”””þýûŒ9²‰TOLhšÞ·o_```BB‚©©égù>zôèuëÖµk×®‰DŠ À›7oÖ¬Y“™™) Y,.~M-[¶Œ;6((ÈÁÁ+tcVò˖-éð=BÓtZZšX,¶²²ú²ïqU]]|úô騨XMMMüi}njii¹¹¹ÍŸ?ŸÍfÛÛÛóêIŠÍÛ¶mÛ¹sgLLLóæÍ?=H̓ŽŽŽ;wîÆÆÆM$Rùùù«W¯~õêÕþýû¹\..«MĀџ}ûâââ={öXZZâ>4–g $)‘H®\¹âææöÅÚ,‰V¬XqóæÍšš(mmmfrÇgÕãÿñ\`j"''§µk×VUUuèÐáVO²ñ搐'NDDD‚OÌVÆ­,ð:tÈÏÏß¿¿¹¹ù·Uh朅……K—.-((ˆˆˆPPPš30HîhEù(75ûüóñÈJ…““Ó«W¯8 °B7Zòâévßo£õ͛7AAAcǎµµµý‚A,ϛ7/33sǎººº28а‡¶¶¶#FŒø>Ÿ@„PCÚô‘۟΃-ZÔ»wïÙ³g[m Œ~ýzppp«V­dw 6nÜ(•JåÆb±XJJJb±8 àC! ùóÏ?Ú·oÿ e¥žžØ×חÅbmݺUQQ±m–J¥aaa³gÏ€”””„„Š#ˆŽš¢ŽŠ­ªÁg!æ0ÈŠS|y³Aæjݺuÿý÷Š+3®š¿¶†“àûESSÓÍÍíðáÃÅÅÅLœüYÎ.\Û¶m“×fˆ‹‹;t萺º:¯.ø|~AAÁ‚ D"Q“ùßEœŽD ‚ޏ=uðСёGÅœ‹9yøàášš‹ÙBâëcÁŒÔÁÁa͚5>Ü»w/Ð4ÝP5ÝàÝ¯ÑæU«VݹsgíÚµŒ6Ë$;;{ÕªUššš²¬är¹***ÕÕՋ-JII‘‹¬8ùùùõìÙsñâÅ>¬ÕožŒ5n»ƌ͛7 kX› &Nœ8gÎæbbb¢§§çÁƒe‰ó©‹%jÂôØ)ÞSòàßÖfù ~‚ PÊÕþÉù²oA–¶sæÌñððXŸ|yAAÁ¿\B~HðÔ°ïØŠÄf³]\\7mÚŽpáÂύ;xð`||ŒŸŸþ‡®zõêõÛo¿Õç055õôéÓ¹¹¹Ÿ;áèÿš9ÉòYÍm-4ëz@”òèæŸé…\¿ôÙ±øçÖn- šâ+šYõéeÜHÙA„œœ}—.]N:5aÂ’$×­[wùòåŸwqqñ÷÷ÿhóêÕ«=zŽlÙ²6mÚ|زµµ7o^-·&Lðññùõ×_óóóÕÕÕesŒe‘š5k—˝1cƎ;llld~ñÏ?ÿ̟?¿Ö[BjjjQQQÁC‡1µyÚ\TT4bÄ{{{>Ÿ_Óù I==œØØØÒÒRŸ¯°žâªÒÌôLžŽ ™ŽÂ÷/ÅÙǏÞ_{äßÿBMI²’ª•-[4Sùðþ•“×w=ÑÛÎàk>’$'MšŽråÊ/^èèèáééYRRR«x±jÕªvíÚášË󏌊ŠÊرc÷ìÙ³iÓ&EEÅO·P±X,fîë‡K$’†zB!A$YŸé¥n³¢Aí„Öò}ü ŽÄý¡£\z"'Ïrê}'ÍèP%aqøi‡DŸìºdɪJÂâ*›šÔzò3‚&YÕÏápÊÊʘõǏwww·³³£(J&iiiaaa(Ï2m^»víœ{÷–-[fggWg1`‚AÓ4“wb±x„ ŠŠŠ£G‹ÅGŠÍÌ3²Hy{{óxŒQ£F9r€e˖2ŸSSS_¿~V^^.{‹¢¢b=þOF’ú޹žžxРAœzõš={vhhšP(‰D4M;88,Y²Ä×חÃáL™2¥¶B×1²Œ» ÿ°èùóp¿Õ »N.× Èçú>ºš7Œœ¥®¢BpÌXPïƒò¡šº÷þ}/˜Þ¬ˆE±Ã'_Øw²Y¯ï³ùœz«†ÊI/wU–¶</==ÝÌÌL__?**êòåËÌ4{‡S]]­¬¬>ŸÖIIIŒÂ5b (jÆ }úôyüøq}YÿðáCŠï‹ÚŒy³¡¡¡ŽŽp¹\ uuu===ssóV­Z9òÃWÐ4}ðàAssóäädÙÅšš(ww÷CÅ,oDê«©˜`9;;VTTPEē'O Nž<9pà@„P|||§N"""ÞOœš¿e/NÏè­¡Ša=}eT…PÅý¹]F¬=ö !!Tþäè6K—•F-qPÒѰ›¢áuàĎ¡»øŒ‘& ˆzÇÏ^œzUYY)•Jk]‹Å˜/ŒWÛ·o?qâDppp6íIJJš8qbBBBfffJJÊ£GþùçŸ{÷îùûûçææÎœ9³–ùñð—_~Y·n]×®]SSSeöm™aà› +23º àîî>}út%%%æÕ‰D~ w‡‚ƒƒ£¢¢d“ã£CqÒUŸŽ3¹n=wdnrLh`ø%‰’Ãwò÷±Ž»ŸV$Žu#=š ßÄÌ®ƒ‚vŸ9¿Ž?ÔL];hÈ ¿Ña¿šŽþiМr 誧ç6Žw–Ûaý¢Ã7EH€Ëý=ƒø>kD„Ž‹œ°žÅå9Î¯]ŒÏ1øÐ™Ã»=\]«…PÊnË~57KEààÀz³iÖo³ü.§µ•!ŠVžOu_sòàêysÕÙRšÔFìf,6µwÊôsŠÎÚŽÖL]€0léÔx&OœŸßŸ}{f ÌG]7<Æü5pHVWЌq9 D"í`ׯBC•@ðI ØÙZ(p4 h:™ŠŠi;]C5‚Ï!‰”æ°8”€bfÙ\×_–©#‘:ÚŽ¶ÔRg‘%eAP€¢CÇ.cžD¯¿ŠšyAdjÕŵ5§Î!lBÅÕÕ¹oð©s;oWæŸáthçÒ΀4úÉÄT™Ç 8< E#®’JÚõ=Ý[ÍEÊjä'ô‹‹‹“’’dœI‚ ŽŽŽüüü˜Å?_ŸûB¡044tÒ€I‡ÒÓÓkXç`éÒ¥gΜqww—×€7n 0 ((HCC#++ËÒÒRŠÍòܺukذaAAAyyyÌ»***ŠN:eÊù Q5nÜž±cÇ6V o Á±~ýújkk=ºæfvvöˆ# TZZª¯¯ÿÖO‚Ë嗿~6Â^ ”F/›É'€?fߙÑÃÎÜ®>öz³w("iŠ…H1Í[®šFÌÊI1+'@K¢AVìÖDžP(D“,à-®€­lMtù‚ –"Ÿ‘bãƒÖ¯»3Å«+wqÛéA[֎ë€DÉâðX ¢fxWà:¢Ïè[~kŽ_»r`æ³2^óàHZÛá‚ýó5<Ö܋˜g® Irjf„šxEnOêñËP}q;Ÿkǂº˜*IIY@5K$RÊZ`ac€/k·Ÿž>¥Ðœo>€ш&XÀ#h$€ZŽ4Õçs @Að’íÛ·{zz\¿~D"®·?©aŠ“àÇPhù9JŸÂÿ?L@œ}‰DJ𹄛@ –@R]ł’siªZ\‘CFðš=CRDj)‘aGAãxÍ`·è¯C ›H‰” ‘ìùe5­u ÓvÝÆôs·dхû†šlYõ$MI¥BÕdbF'ÿyôüîs$èî=réÂã&äꭇ]Šèœ{‡Ñ ºn»ÑEQ4@lݎ[ŸŸ¬Ì‹÷|ºí§Õgjº³VPïÔX"Š®3Y ±ôœï„ùüù˜ªjŠ’Jn¿B’ŸU‚iӊɏÈ`°/Òf \÷ôùۗ¯=I©žÒoÖùŽWóïTÞWŽë¹é*ðU•‰7Ù®?”\Rj8:Ÿšá¿á‹O“ž^¿pân®ˆEB4F!PRPn5ØB°iãŽãWâbw. âr4€âŒ{ۏ%dªqÕJj|ŠF…†_©”Ðò2–ÿìÜ*ÿPõñÇ(tšÞÃùþ럪È>qíá³rR¹¡¢¥¬â—ç#÷_œŸ PúgÔñØ+w_‰Ù¶ŠššlŸ²·hÇãü)! +“¶4ý®AFÓ²F/¢‘D*¡mçÙµ?á;Ë?(dþ0õŸ NrXutŸ?Ì šŠ‹‹‹³³³Ùlv=²²²ÊÊÊäçùc°qS4M3uô‡£•õ/ššÓìY«[Jp€c+ÞàÑ큘îî9)hÅx>€‚žys‘6‡E£ÀŽ›ì!Ýžl"” ~šxx—oŠFÃ'Ç×öە[ŽØáÝï¬MX\WòrûÅíÐân£§‡vh§¬g֜Ôåœýí9ûåEï‰ýn]LlÍÚµ±`&ÕµíÓF‹Qgæ9ž†M;Mù ºÚ·p5ÒtŽïlYs-Fjnz'g["ŠôÍZ:·Ý†øì«þuÞâ>]ž”žbþÁ«ŽÍõå+ŠZÝVšŠmmm§M›V+1B={ölt…æñx³gÏ^ºtéòåËMLLj-"âr¹Ã† ;|øpVVMÓÌõóçÏûøøøûû7¬Í—.]òöö^Žh‘ 35!$‹Y,ÖÓ§O[ŽhQ«™biiùÿÇ©UV™‹ÆÆÆ×®]ëÖ­›P(”•O‹õòå˹sçêêêŽ9’Ëå›™™Éo‘¥iÝmkÚŸEÓÇ rÝFKªÆ¬ÞÝZåՒÃù.ïnË¢õ„øœIî+g^šÐˬý€Y3Îš·`yéÚß÷ÜsâXGß ±aK’$B¯§9ªpuÍ[Sjl`ñ5L­ìxzªbP]¹óæÐi ǹÓäÔ+íœ=3 -ʋýmò¯þlÐuð[¶ÖÃZ $o.ïŠi=v|W%îÛ1{Qñ­?c3ÌúE¬ê !Bs&Î<7Ävžeö®u  %À1šŽ&v’ @õ«Û·.²$NníµË.[qêJ.¢9.>ÍéŸv¿_7 Ÿë=!eãÑH=mCÓfUÊܚ©nÖÚ\G ’£knS¥Æ_ÍÄÊNbš!y*Ö3|WÄYŸÇ¥ëC÷¶ŸZPßZGy‘677oݺu­âAQÔܹsq üñ·nùÏ2xðàîÝ»3FMMMŸÖ ß¿```eeeö’LMM]¹re|||}‡eQ’‚ [ëAE±5äšçïÖ=7°ÎøÎò_æŠ Â¶­Žå¿¯÷µ›4dŸ¥ü:uÊÖ.³cWød‹DëÜœðIlÀԙg†­8ñë(æMûyëFÆ?žÙöýnAœ ?ežegg¯_¿Ÿ¬¬ÌËË«¢¢Â‚™®UgÛšá6Ðô, ‚H$>>>![̈́P(J$___GGÇV­Z͞={ʔ)öööG Ô©ÍgϞ]žpáøñãÛ·o/kÏ€ªªªµµu}²wMggg???ww÷úöÞa.fff2äÑ£GwîÜ155œ}ûvÿþý/^T7DȞ¬cÝs­ÿj}ïÝ¥išUž>î;÷òŸücïÅ ïæÝTŸŠys”÷lÇçåš—G†oœ‘9Œy󩟟Ó$B988šªªþ %÷ž1?žžžéééþþþªªª²¯ÅÆÆF"‘Lž<¹Îi·ÌcÝ»wo`~u%'Ê4Þ9"ß•¬UGÉÞ®Èk¡¬ ^Y&>OþNíÝ$䌓UµïŒ£JSŠÉΞc sùÞ ÌiáÃ$¡fρî&²N¶º’3#y?Ƶ+/¹Ë5ž¥¥¥-Y²€²²Ò×חÙñŽ¢¢B,×9=»qµY։äp8[·n6mÚ²eËV¬XÁe!]§   ­­}òäɘ˜˜‰'¶mۖËåÊÆ›kÅôäɓ£Fj×®-gÿTUUµŽŽäóùõU²[ó?~|èС©©©ÌÉ`õõ¡MLL®_¿Î]©Tj``°~ýz__ßÄÄDÚÚü6”udk±x¿çŽÞ/“òr)¯j@uˆ|-ÏÞFòÞøPí4¬õÔÊ,ù»$ ú_+ž2{R­éPg,ÒömœñŒÌÑ¡•0þÈ3òç­¡ý‰·ß‹ÌãèèèÕ«W1B[[›qU\\\Ÿš„D\’ñ<ååëBš§mß±®BmÃLTTÔŠM›ú÷ïß©S'Ùf2͛7o2[ÿbyÆ|o ]ZZêëë‹Ú¶m›lW‡¯;Sò=»ÙçԆ٘ð }©?6u=ùîÚ§@ŠÓ§OçóùÞÞތ63Û2‚SžeA‹ÅsçÎÍÊÊÚŸ}»žž^­ž\ºtISSÓÜÜ<==œY³f²ŸŽ|¬Oœ8êæææêê Ìp5EQÿŠ6×j͙3ÇÂÂb͚5ÌÆd (4EQLûR6Ž€µù+ÓÿÃ+òÚÖ»wïΝ;˗++«ú†À0Xž1ÿꊋ‹-Z”——wøðaŒcÀ璓“3jÔ(##£ñãÇs¹\fæEQ –––ZZZÿŸ$Èóž{÷î‘#GäøSˆ‰‰ êÓ§O-mÖÔÔŽŽŽdšqßDê^Œx±dÉ==œÐÐP\öšǏ éׯ_-mföäix» –gÌÇ:<<|÷îÝzzz_wôÞìû!ˆ’’’Ÿ}ûº¹¹ñxsRGB®ÎébKGDÿÿÿ œ§“ pHYs  šœtIMEÙ pí­ IDATxÚìœy”$W}çû¹7"rÏʬœª»«÷nu·ÔZ„ØÉπ1xûÉc¿c žç°Íâ™3ǃÁØã16Ø,¶ÁÀaxðl $dl@RK-õÞÕÝÕµWîë}DdVV/RKŽÔUÒÓUY‘‘‘wùÞßý-ÊcAA„3Ðr AAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAA¡(‚ ‚ ˆPAAD( ‚ ‚ "AAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAAD( ‚ ‚ "AAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAA¡(‚ ‚ ˆPAAD( ‚ ‚ "AAŠÂšÃ#7AAùKø¡±å<÷PJ³³IAVÛ|õD¿ "…gh%fŒ9¯0Á(‚ ¬Ø;õŠÄŽÁC„£Eá"ˆÃގÔét¡™ůE&#¢QAž„1™² ­5(ÐJwç³Îœ&bq•<3#Já9!ψab"ƒïûA¿ŽÁDæ ­‚ ‚ðŒ E@kÝ…ZkR©ÚÒh¥cñØsŒpi‹âsP4F&" BªÕ*·ß~û²‰?>@n’ ‚p©cǰˆçy|úӟfó–Í(­Î¹S&‚Q„¢ðCÃοKbàDQD³ÕâĉLOOˍAV%ïyÏ{šT–â¹KGضݵ&cºFA„¢ðCˆE¥Q†ñ–³çyx®+[̂ ªÇ÷\ÏÅqœ®£6"E( (Šb¡„øŸ EÏsœ ‚°êq]ßóQš®ï¢Ñ²å,BQž(t#œ£ˆ b¡è{4š ¹9‚ ª§ÝnÓn·°,‹P…ض-‘Ï«±ë>Åb†øžOàrcA„UOxžÏ_Ÿ/Ù9D( τH £0 ãçûž®+7GAXÕ(¥â­ç$[Ǖ*Š"¹9"…‹«ã€Úa>aÊ=AV=~àw]§Î¬2&ˆP.†FL¬Š„ÚAbŸ¿X矐×Aáé…Q·8D7ƒ‡l?‹Pž±Ø‰~ŸXE¥­v‹;׿þõÔëuq,A.At¢°ºšççÚªÌÄ~ÁxñT(,,,P­Vå& ‚ -ÏY9L¡(úяrèÐ!Y¿~=7näŽ;î Nóá˜zœÎ/þâ/²}ûv”RxžÇ;Þñr¹ï}ï{9qâÿôOÿÄÝwßM­VchhˆÝ»wóŠ[_Á•{¯”üY‚ Ï#±x.ñ(óÀ¥E|ŸÃì™Äó<>õ©Oññœ\>ÇßøFŽÖ|ààË_þ2Åb¥Ÿÿüç9|øp÷}Fƒ¯}ík@l¡üÆ7ŸÁýÑ144Äk_ûZ6mÚÄ?øA>ðþÈA„KŒX…§ŒRŠZœF6›åŸø7ÝtZk^ò’—Ðl6¹÷Þ{ù…_ø~â¶ÛøøÇ?οýû¿ñò—¿œ(Šžçž{º¢Ð÷}²Ù,ïxÇ;xó›ßÜ=ÿŸ}ûøÖ·Ÿ%7ZAD( k‘|.Ïë^÷::D­VãðáÃLMM±}ûv¢(b˶mlÜž‘Gö=çv Cîºë.víÚŶmÛÐZó#?ò#xžÇã?N«Õ¢Z­233ÓõiAA„¢°Jè8OOO“N§XáÒë/²oß>Þÿþ÷„!c££€ÓéÕ`rÙ,·Ür ûØÇšÕjŽZ-þáþ}ìcôõõa"ÁøÐ‡>ÄÌÌ  vë} ‚ ‚ BQXeŽÝ6wÜq7Üpï|ç;±íž™ž®K:ŠP(ð¹Ï}Ž?þã?æ5¯y ¯|å+вTáÃþ0F£{®Ûo¿þÊWøæ]ßdqa˲xéK_ŠÁðƒ‡~À?øAÂ0äOÿôO)•Jd³YþË;þ _¿óëò AA„¢°ÚÈçò<üðÃ]k¢RŠF£Á† 8pàǏçÕ¯~5».Û ZÍûöícÛöíÝsmÞŒ™+÷îå›ßø&³³³ÜrË-är9Œ1LMMqôèQ^÷º×±{÷îî{<~ û³RJ"ÞAA„¢°è²¿øÅÜsÏ=üùŸÿ9×]wÿú¯ÿÊɓ'yík_Û€ããã|êSŸâ'ÿÃORYªð¡}ˆx€fff˜˜˜ NóS?õSŒüå/§P(ð…/~±ûYÃÃ̍qçwrÛm·Q­ÕøÈ‡?̃>H.—còÄ$ãcã]‹Š ‚ Ï.’GXA'ÅÎüÁð›¿ù›|ìcã7Þò|úӟæw~çwø¥7Œ€WŸò•üîú]ŸúÕ¯òŠ_}ðÀ­·ÞÊg?ûYî¿ÿ~Ÿôå/W_}5{öìá†nàºk¯í~֕W^ɛÞô&ŽÖŒá oàío{»víâïþî˜àÏ>øgÔj5y(‚ ‚p‰PFêä¬ya„Ÿçãº.FƒF³IµRarr’·Œå-LOO?åsv,‹FƒãǏ311A¡P8ëïm·Íôéi6mÚÔ}œ^è>1Ú9‡1†#G²n|œL&Ä%œ*Õ åRY¶AžÃŒ÷œïe||œ={öP*•(öÉçòd³YlÛÆ¶íUÁ„gÙÓÎ^=ôøæóù®ÿ`çµ^—IgVˆÄ'ˆœç?ó÷­[¶¬xMkM¹ÿ,a*‚ ³‡Htá‚ÄÜùÞ¥ºAAD( ‚ ‚ "AAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAA¡(‚ ‚ ˆPAAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAA¡(‚ ‚ ˆPAAD( ‚ ‚ "AAŠ‚ ‚ ‚EAAA„¢ ‚ ‚ BQAAD( ‚ ‚ "AAŠ‚ ‚ ‚EAAA„¢ ‚ ³‚1fUžëÙÆ–Š ‚ ‚CƒRªû»RŠ(ŠÐ0 ‰Âƒ!Âó ?­5Zk”R8ŽƒeYÝßÏõgþ.BQAa Ď`«V«:xÓ§§9=uŠÖÜÍÙZ3³ŽkUÜF“vÛ¥…Ž£[k²™4¹L+"Wî'Sì#34D~hˆ|_›6mfÓæMŒŽbÛvWh®v‘(BQA„çœHŒ¢ˆù¹9fff8°?ßù ŽíÛGÐn°sd”ýŒ ô2ØWÂN§ÀI¡3YP€VD&¢Öö˜mÖXlŽ9>3Ã÷ïý.µF‹;¶³ãš«Ù±{72::J*•ê^Çù,ŽkR(®3ésµ! ‚ ‚pqçÖ øç¯|…¯}æ3ô>M_³É˶ocâúk)–JÛ"ÄÂØh±,°,”ea”K£,˶è/”tÖ¡l‹ÛopRDQÈáÓ'yèèqþå[÷ÐÎçQå2øû¿O*F)…Öz…`\3Bñ\E)…1fM;f®%:æð3ÍÔ"Aᇛ_Ã(ä—^÷z6T«üâúu”¶lИ+@ÊAiM+ŒÐJamk ŒA¡0 ”JtñÏF)Â(‚ŽÒøÆEÛë'˜Øž‰WŒä%œœåÞäŽ_û5Þó®w111eYX–µâÚVµPìݯ?SöŠD‹Ï®X<—`±(‚ OŽÎùôg>ËÀ‰üĖ-lî$Ð@bÝ£3¿ÀրB%¯+¿Üù³B‘ÈÇä­:~]“Œ¿–rl¶l˜ ¿Tâàg?Ë=wÝÅk^÷Ó€œÆÇYý[ÏœûõÂ0Ä(DQ &±øŒ ãÖ§Ñ À²,Œ1]ótç÷gºA‰åRö!HÛžkÏ6¶Þò[¿Å¿Ÿâe ”¢TŒ¬z¥2‰hLÄ`¡&>‹ØWQ%ê“X­øïÚJT£KÓ?0À^ûÕ᪌€M›6‘Édº–ÅÕtís=øŽÕÐ Äޟ1ĖWCd"ˆ’#\äV¯P"µR°[–uV#}Š;“ úÏÝAþ‡}®+·Žç^ûž˜mÃtm*ÂZoœóšoã‘AE†¯>Âë®*áXv<¯b@+ŒÖ‰>ìI9­J«XLÒ»³§’ÿtÇŠû/ƟH×þØ1RšxkÚm»T«UšÍ&ZklÇ~Væö§%{·51]«a'Щ©SüÍGþ†;ï}ï{Òcže^úҗrã7òö·¿t:e[XÚ"2Ñ3:cp]—üãüÍß|”ûî»cBy k”oŒ‘¿øÅüÞïýýýýe0š››ãŸø_ü?_â;ÿöm\וœÉd2üÇÿøjn¿ý•üìÏþ,Žã\”ï׿þuþñÿ‘¿ÿû¿§Õjɍ^£”ËüæoŸ…WŒâŒô¥/]Ûv˜žüˆŽVü¯~ÀT³Í;^þãžaJǖÀÎÞqg޵TwsyåØyÆ,¬—_ínU/˜P6„‹s3Œömoã–[oÅ÷}–––°, 'å`'‚uÕ Å^ßÃ0 £ÀhµZÜ}×]|þoþ+?~yŽ_ùÕ~Öœó? ÎÏ82Yç;‡îâ7}”÷}è“\{ÝuD:¶ídœòÌ<‘|þÅ_arƒüâÿó>~{t=ʒ‚>k•éǘ<°k^ô>ñ‘¿äæ›nêæôzª“1†/~ñ üÕÇÿ‘­{_Èxó;yÓ{6bَÜè5Hà{ì!þùßÿ‡ùCþ¯_~#—]vÙÓ>ßìì,ïûÀŸq|®Ê¶œ?Ê_ýÓïb;)فZ‹h7ð¶·ñÙ{ïe~~žb±H.—#—ÏEQ×ÍlÕÅÞ ”®%1ˆ-‰û÷ïçÝÿéMü·_ÚÃÍW ÅÇééÏjcÆ0±ŸÀæ‰¡×æCúGü?ÿår9’Z…ÑÅ’Îÿs?÷ó\û²WóʟyŠ(^aIӚedÝc6Åÿä¯ÿ×V&&6<­~aaßÿÃwóS¿þN¶_~Z[Æ#7z bYšm—_ÍøÆ­|ðÝoctx˜7’ÍfŸò¹Ú®Ë7ŸùMŸõýGø™7œ•ÑuݹEf5š €³Y®{É­\vÕ ùâGþ˜=»wóªWœj͊ÄÎÎ)@!“ã—®Ÿ–o=—еÿ1~úŠËÙ82J©ÜO*•ÂIg°ƒm[XvòµZ^øh*v±ˆwb#cð1aÈ¡ãÇøö#ðÍäU?òR>ðö·shfÿÛߊ^¯Ón·ñ}Ÿð ªŸ\R¡Ø1ÃvnœøxžG†|ê£ÿ“7ߺ™¿aŒ–+[Ž—Â~î›ðÿå$ÿý¿Ÿ‡wœ÷¿‘J¥°m›(Šºþbñ…ÿ÷ l»êEÜúú;‘šx¢1¡/ë0Vή舱/+Tš>óõö“žcµ(È9ñj±í‡<8F‘!ek[ÑòâçSÎ¥îKÓtN/µ ’À±g¥%%}ý%·œ¯]ãO>ðþôýòŽL ŸþÌgží—~›W\óŒ¬~K1^ΑIY+wc#C¥é³Ôôˆ¢‹kÑ0Æ0XLSÎ¥ˆŒáèlãyá‡Ùq?ÊKŒéwßÃ=_úG^tÿýÜtÓMOù\_ûڝ|៟Ákù7]¿‘(|â>cŒ!íXŒ•2dRv·E„QDà YjºŽý8UɅŠ›ø,†¬c¡€ÖSè»ç»NÛRL æIÙõ–ÏÔR‹è9Þ>⯋¢Ÿò /ú‰Ÿãλÿ ÖsõÕ׬]¡h¢®È³ŽÅîŸœß{sõ*_;vœï<ô*2”ó9r©4–c¡,›ŠÀ²I¥Ò©4†v`€¬V(mn±ÔlPó<¶nÜÈ­7ÝÌþÕ7¡óyü(äàÌ AÐn·q]ß÷/ú<~фâò€¶Òšèû‡y€ÿûŽ=‰—zï_VàÃu®çÅ}7à»Ñè‰ïÞw7ÿÄOŸ•)à| Ò\»e ¹†XÜF&엚.Ggœ®­)±h ؖb}9Ï@Ñaj¡Å”^UÄÃxŽuå4K ŸcóM"c-¥¹fóS•³U— zöےç¹ìžâz>ó?ßõŽïK­Ö``ÝvÔ3ŽE’v,v¯ïc ^`E‘¹šÇä|“ƒÓUŒá¢µ)Œ—³ìë##ŽÏ5Íóiœ1Œ®› @S¯ÕžÖyŠOŸf¡ZgxlæB™”Å®uñóîmgA ÅéJ‹C35*Mÿ‚ΧTuºq @Áaj±M³ÒzÚM“4²|ÊậƒØZQkùÌ>äâϏù1Ÿë6måäÁyè­i¡žÒcËDAP,ôñꫯF)š{>³­³Í‹^@Ýw1^ÏoŸGh Q"€•mC6K)_€PÈ1T.³ad„ŸŸ>R…ZÛxZ£=£mPš(ZŽéÌá«Ò¢Ø¹šÈ,¿ö|09:yŠÁþDF\KVË@>PÎðècx®‹VñJš÷9^¬Ntèà^ñ£?·Œ¥x4KYà HiÍ`!ÅH9K.msz©E­E¬X…GÆ •B',2ñkÉbÝÖ±ðEѲgŠŽîäªR=+Æ'>O˜4lK)Âä|œç°µÅÞM%ŒéJ›02Ý ž(ùŒÎ`%_"Œ »×/çžÿÈ|üYÄçáÉ õ¶ß}íÜ×ߏ³®7ùŒîgŸãØ ñKƒÃ>xð‡°>…qֈîr‘ÛzÏχgêÔÛAò<CÅ4ãýYr)‹SKMšnß»žçÙ–a2!h¥ÐºS0 ŸÏœíÇÒñF3—0ªEËsIüÒIŸÛi‡çzNœç_nOI/xr\·ý&¹ÙV<ï'9晚@µe%“Vôެ©õZ•ZœA6W \žÊìa€©Å&óuK)Ҏfb0ÏÎñ>[sïá…V—ð<ã@ÜO4×lé' 37¶>'}·{o;}·§ÝœßÊ­*Šq¬8ýI_.E_Öa©‘޳³,V+ûšJÆ sõy•,Æõ9r;ýŸsösµ·È,·ÇÞöÜk)6†ךÏñYjY,ô•qCͱcGמðí¹cJ'æ ÕËњb¡Hi`€ÚF96ÚÖ(;çZŒ ʲQ)åd0:ŒF+КÈÒqʝx°H>cå=7gŽÿUgQìM…ceëû>Ÿo?{añgb&ž^ãÖaº„–e¡µ^^‰\$ÁèùþŠLñJÓ 84]c®îbiMÆÖŒêÚ d›m#E9UaŒ”eËH‘“‹ ,K³a ËɅûOUÉ:š-#EÖ÷gQŠ—\öŸªt·|µRŒ”Òì/‘q,”†¥†Ë¡é&³µv·³e‹Í#E6 dÑŠ+.ªÒòbÁџOsùú2M/`ÿT…Ë7”)çl‚ÐðÀÑ%*-BÆáª%Š?Œžb¢Ÿ\ÚáðLK)®˜(џO‘OÛž~ÈBÃãþc‹8Z±q0ÏP1Àæ‘ý… ß;2OÚÑôçS]kpgÀ*e6 ç-ePFqºÒâÐlƒFÛïZØ®Þԏ¥4[à²u% ÆÀ±ÙÇæá…Yo:99}ß{Zƒ«Z‘öᙎÎ6˜®Äí]kE)có×lÀ±-²ŽŠáÂH1ˎñ"m/`ßÉ ®¢•âº-CXL-¶8>ß@kÍÆÁ›‡ äÓ~QiúQ"e[›«£µâš‰2ƒ…4ٔ…„ÌÖ\~pŒ‚ÿÛäÅŽÍeëúš4=ü b ˜bçxÇNÕXhx+úHƱ¹lŒÈX9M)N/µ˜Zj3_owÅ[!ã°e8ÏX9KF,5}Oש&}ÞC>msùú2¥Œ1Š£su&盾~ØŽÛG ¬ïÏRÈ8QÈb#àǗpƒ0ö/t, )v—È€4ÆÀé¥6‡fêԒÏz*èD$AðܘT­øûâÀTœÚF'ù£È`tQˆ 5?V±lT²1«" ðAÇBÞDmƒÑ ­Lj0& z1°VÌoöʕœYöSô}<ß_ú‘žêðŸT˜Z‘ß2Š¢Kþ¬LÏñõ,oMFÄ«öBÆf¬?C.mÅ¿gmæ“ÁÿʍýŒ÷çÈŠâ÷3ZÎÔ©6}‹ñw!“Š;drŒc[,ðð‚\¹©Ÿñr–lÊB)(fRXÀÁdû*e+Æú3øaD:¥Ø8O,NpÕ&žÿè"¶¥îËt­ … õXœm̲y8OÚ±ÐÉw*dšnÈñ¹¥Œƒ“l˖rٔÖš|ÊfŽ”Á`º×_Ê:\>Qb¬œ%mÇ⌐sÈ¥möŸª²Ôô°ŒôeI;šˆ2yl+žˆ3Ž&2†#³õ§%~!ñ¬ TZ‘J-Ù”ÅÆ¡|܈¥f¶:}ëñYíǎ‡òØ:Nš_4±5-?d®ï\³¹Ÿ±r–”•“µ)çlfj.MwíLÐO«¹tü UlM[hx4Û!¥,äS6 *eWL”/gp’>“ÏX\­¯ 0Œ”bŸiÛR äÓôåâÔM›†òlÎÇ M¥0Æ&—qhž!N×ϱ]®”¢”w(fmN-¶Xš{€‹ÑRŒÈ]hžۋú²ÛFŠl-J*z³ë²ÜóØ, 7À±-öN”+gÉ8qBš¡bšïš£Òôéϧص® y;6ä36…ŽÍƒÇ—°4 Ó\¹±ŒmYÄ )lú²édÁT%°q0Çeã}2N÷yäÒ6–¥øÞ‘™L;¶DK­|I©Ô $ªcƒÔɟ J[ËÛKÝÔ:ªÛ¬•e%I»×Ž®Z™'2ÝÜBœ{æÂj4+‚ïùøŽO8ÚY!ö/% ;Ÿ¶ÉŠ,Ö ä°µÂ#ækmH¶u"O/¶˜©¶˜œo21cópÐþýÀšØÝ Œ“ó-æª'I;µvHÚ7Û²ðýÓK±+Jæj.KM­ÿúØ,ùŽCÓ ˆŒ¡Úò“E…êî,ϋ€2€m›‘R† Œš4\ÚAÀBÝc]ޱrËÒDAˆ†KY޶8<œÈÑÙ:¡‰w(Ҏf±á“r4ãýñøul®Î£§ªñ˜N.4YhxØZ3ڗA)ÃéJ+^h††Ýëú(åSl)phºŠBáØš‘Ÿ [G ÌTÚ|û±6~dpƒØý"6€)ÖäðBÃ\­Íך m_U»B &±ƺQÅ?º–Âä5+I»­V6”Žÿðò®r¯×šBYz9 £¥×Ì(}VÂí0 —KôE‘”]ZÅt¬¿œ~Š«âº „a’Æ$4xaÄљ‡f뉅zy}ÒpCêm?ž •¢/S¶ÅM;‡ÐŠnºŒ¬£Ñ*Ž›‡ ôçÓÉÖL‰jÓåÐtC3uŒŸ\*”šw u} ñ_¯Cyœj%ÞÊ BÓV2at‚KLò³1“¿”r6;KFû²€SV·ˆSGTôN6ÑyžO1ã`Y? 9]iÅÁ2Ê0_£)³¶EÊRžþ²Hª4œ®sº—„M[Áí9ž pïáyæjñö{ʆÁBŽk6—Ù9ÞGÛylªzAçiû!‹ 7ˆîË0TL³w°XwÙ?UãÄbó œÉƒ0¢é.ïŽøa‰¿§VëŽÕ”Åö±"›Gò8–ƶb¿°lÚŠÒô˜«·í˲s];×õÑrÏ484S£á4<Ÿ…ºK9ŸbãPCZnÀäB“‡&—x~­á-œÜÛŸéDS†ûÒ\·µŸ|Ú&íēy2å/÷¹$û‚1`TÜçËy‡]ë‹ 3dìåÔg[Ö Ê(&s€l 7É€l6ôgÑ*înٔÍh1Å©¥Øÿ0ãhÂ(¢å…Ý’cóž>oSÌ:ñ1nˆFhÓÕ6ÓÕ6ÆË"›ž7Œ•³”²‘!ÙʎÏáù†S‹M6 (fS\»e€ Šš4<8ºÈ\=$2†™J›þ|šBšBŠÈÀôR“CÓuN,¶€gâB·vsb)TÄÛÊôˆ>³,ü:Ho9ċÙ$hÓ)³k’Š,=ÛØ –5²Þ[){|;[Ï«ÂzÖs7¥ŠìòàAOºe’Fz‰[ß\µÍ÷.2Wk/ ²n^ҕÏ/"‚ž6ËäBó -ùœm'2+kžö>?ˆðÃ׏š5ã÷ iù!÷ìŸcóPž±rœ7°/ëpÅÆ#¥ wî;Mî|xšm£ùÄ·Î!Ÿ¶¹l]Àõœ# q»~އ¶Ý—uÈ%ù4—šmÂ0ö»»~Û Í±$Àc¬œMü9Çh?©Ÿ¬Ãµ›û)e™­µ92S£íG\·u0ΰ5©ØaφŸÄ¢iqÃö¡³®u×ú³5ÈôF8/ÿ=ãhR¶Õ]ÇãSì†Ó œNYŠlÊÆ £Ø?VA€ahpýxq2µÔ57À‹"ŽÌ6qýӌ•³q`]Æa áåW®ãkŸf¶Úb߉ 'æ›l+RÌ:d›uýyÖ äùÊŠb— çûüj’íäNÎÈDۙÄà`ˆkmÓpŸsh­H,š¶F}YÇÑ8]à ëJ¶Œ)e.€Yš»ÔÛ…ŒMË ¹÷ðBìž²I§4m?ºà­Ê3ŸVYÇ¢qXjžœXlQÌXì+²~ Ç@!вl‹RÖaŠêrd¶Ép!ÍÄp–‰MÓ xðøó5—áîûÎýôû²ùtœù ÞôW€™IٚlÚf ¢±©Ž|ZnH)£ÙZáG†‰ý…4ՖÇñ¹&õv€ÖŠ\J“NÚèp_–‰Á,‹uC3 \?ŒÝošìŸªÃ@>•Œ•–ŠƒÞüÈpdŠÎAcØÐûg— iF iæj.}YËRì?oUS\œy€”m1^ʰPwŸ Î'Ü{·}¡JY˖eÕSçYõè Õ3Ð÷Ì]7DÓµ\¬Ô j F=Ÿi5¹„ (v N`•·a•6£Òý˜ IԘ"\ØOX;ÊF¥K€6Œ"ÿÔ¿cŒ :U"µéå˜ÐÃ?ùmL{þ"fã5qþ8;‡J—1­™KZµa9%Î%~fçë’ª¥ç»š®±®œaš˜áòõ}Žýˆm£JY‡GNVxôT•­£ö¬/3µØâè\ŠÒNªžøQDŸ§?¶8íYW€éElÉSΧØ²ÊŸ“• ·ø…`È$ùÜÚ~DÊVX*Ž4.çŽÊqÙºb,ŽhK%ÛÔñ9FKYÂÐpd®yÖøTiú,Ô=ÆÊY®ÝÜÏ@Î¥Ø6Z B1µÔŠî€¬çïjëh‘ñþl7Of1cӗMá‡'â-œ¶D¹ŒÅöÑÕVÀH9­UW(Š,Ŗ¡WnêçèL“‹-Z=í'4Oñ׉έ·|J9‡]ëât,ëû³l)ðø©%š¬RÊ9ÜŽcˆtÊæþ# ÔÛ 7ÄE…(yÇâ–=£øaāÓ5æj­vœêÄëæÔ[CÞðOì‰Á\,nTŒ5>E+Åþ“‰/pʉ–¥/e(d®à³«N'à'm[lèÏ%Qç[CÁ`.EαØ:Zèš­Pÿ ¶ŒÄŸ­¶¹{ÿ,žÆF'c,dxÁ–8ÃÂö‘"ß9<ÏtµÅP_š­ÉûÚ~Ȟ %2ŽÍÁÓ5\¿ÆÉÅ&;×õ±iž€c[4Úë³ 2Q•ÈDL-µÙ9^dÓpˆØOúÚ-„‘ᛏNÓöB.+²}¬¹Z›}“ê^H;qGñ’’k6—+ç89ßäðl–&‘Ý:Îñ|¯º› ““Ó³œŽÜ[yBõî>CÆfE­gHÜŽŒÒh•X&?ǵ‚œ ÷âüEù d¯úuìÒFTº¯kê5~‹š9Kë%˜ýVf€ÌîŸÅx ‚ů‚Jõ“¹â ¯F0w0ŠñÚìÑHoza} ÷±¿‡Ð¿D·juönõ”&…•GŸZlñý£ l)råÆ2~dˆGNV8žä{ìdKǓà 6÷'–J81ßàðL79µØâþ£ l.pùD™ ‚ yôD…ãó̀ʅ]«ŽÎÔÙ6ê‘1<~ºFvŒÙ³ŸLÅ[ޖn“K;36§+p|®Á¶ÑBŒ-”s˜­Ÿ|8ˆ"î;ŒÀ–‘<[G \±±c ázÆñ‰Á܊…QŠ›œZhqt®›Ggëq„ñºu×g¶â2]iQʧQ@Ó 92× Ÿ±éË2ޟMrÂ©*§ZmpÞ¶±¢Év*2$/6œ€?8Ϟ }ŒÓ ÷ â§ì?UÇ #æj.ß?ºÈÎñ"—o(¡kélµÍãSUcXjù|÷Ð<ÛG‹lícçºXüT›ß;²@ˋž³Û„Z)FKÙxqEa®â29_gr!)—‡âc ìÝPf°˜æ…;†h¶}æª.ãýY šxpdŠÎæ‘<›G žaȑ™Nר>ZdïŠ~ü dºÒf¡Ñ&—²)çSL.4é€K*Š+e0Æpr±IEؖî&O¯µ}Š+mÆË9Ö ä蛪px¶AÛÙ»±ÌîõåØõ%9tºÆŽ/Dq ԃGØ:RdëH¥AñØÉ*NUˆŒá±© -Ïg׺{7ö™ˆJËçølƒ…$2û‘“UR¶Š”Kó¢íƒh+®öñȉEŽÍ5á¡ãª­€ñr–ë·`%‹§Ç§ªm>ÏF“slXtZ𮣷rèlAwý=ÛÌ$[ËÉÖŽŠ…&–^¶ö9L{ %µù娥€·ÝNŽôØ9žqiïû$&t1í™øcÀ„ÉÿITš¶PŽ2Æ@äÇÓNÜP¢0šVòZ<@9ƒ»qÆ®ÆLÖ!ò’k°.q[¿ôµFçê.÷š£å…4ÜàŒ]À #N.¶ð‚ˆÅF\«·#Ã(âX²-SÌ:ho±ÌÖÜnÂívq`ªÊl¥M:euÓ;,6GƒˆzÛ'›rhû! u—\Ê&“²XhÄU%ŽÍ5hž>…$²é†LGmî;iÛ"›¶’ÒoÐrŸªrz±E.cc)E˘¯yŽýžœ\lQwƒ8eXò™O.ÅíšµœÃðäB‹Š$®Qd˜«»ì;QádÎ!åXŽœ€j3 áƖ°Ž•Ø "ú2)G„‹8€…€ývžk.m‘KÅ۞ՖÇ|Ý}NŠ@j{!œ¬’q–sF&¶Ô6݀JËÇMÆc ó5—‡O,їu°-M­íÓöBN.Æa±[‹á±$©­ӕ6ՖÏáÙ:µ–O&eÓöãèå\Ú&ekj-Åœm{!Ÿš`[ªE­ÔʅîɅ&~u³#ރˆ“ q–ƒŸlœ»°ÞXjtÚX<Ö™«Ss i¥®0SiÓrCPІrt¶AˋȊ¬$-®qÞéM7à‘SUrŽ*…뇜^ŠÇX,5=ŒÓ!³Õ6ùŽÖŠzÛg±áᅡøþ÷æ‹VË!‰ –e+â²Ï}l{ÔI%³2ïb甜ù;®ÌZ­HÇžf-ŠæZ¬”¶°öÙõZÂêIŒc_Ã;òÿÅ«|mÖ§pÖßLX=÷I¬4Vÿe˜ E0už‰Cò؍8ë^„UÞBTŸÁŸýÞá/€²ÑVgçë±ú·ãú?šüìÑ«ÐÙA…ÇhïÿTŒÍ1r-Ί[Pv{x/¹ëþ3íýÿ@X›Œ$í\Ïèɞ[¯šŒXӘ8rž=|.kaçµ ŒXš»ñ€xƱJ)Z^À‰… ñ3S+ü0;“DµåSmùË9¯8ÛoŽý$çiºO×VŒF3•63•öŠþ°ØðXJjÌvÎSmEñ5(ÕMxŸØSAkEµåQmyh­»ïky‹•ß]õ¶Oœíwýëz4$"vŠŸÂ²Î{//Æ¢ãR.@Œ ®³|¡Vi•èJ3@ëåûw汑1,6<^÷ÞGg̝yO×ÒùÌÞã:åÍ¢(b¶Úf®Ö^Q>­·ýzA<‘O«vb™:»ýzAÈT˜¥”ÂDgº—\šñFQ‚îbŽ•ˆ›ÉùÆ?ë02LWÚÌTÛ±ÝÆtJdº+Ì¿ —ÅŠ·²ï6£Dªn;YÑw{*ÕÛõvýŒý«w<êÅ âÄûqÚ2sV&±pwÝ>¿¢$ߩ酙­ÇÖ®3òävÚóBÍe¡÷ÜœåüTœÃ¶ÒŒ’ÅÒÙçyn ŸBÛT="ðÌ*tZ-'ÈNžIœ`;i‹–f9øE/E'éoŒ²–+±hW*Šßž¶…b/ÏzÂme£ hmáWÌ>‚IüvLèœüáü#¿Ž *@áB1ƒ=r9Æ­ãZ9Vy™Ý?‡Î¢,QaVÿV0þ±¥°Ê[I^Ò)taDÙV~$ŽÂ=ð9¬ü8Vv n?¹AT* skk퀕jÛ²ÉçóeÐ*ï{²cWÖÌ5OZR¬sÌùŽ»Ðó<Ùµï<RLçzk·–u=…ïM7êùɯ÷™ióóó Òéô%ŒOçó–ï÷ùß¿Rèœ]wõ©|öµ¡åú•mã¬Ï7ç>×ÙíKš®¬Ó|ß§Ýn“ÏçcëÈEjOõýœ÷ç ߟ,äLdÎyïŸøsŸŒüà“]wg}¢6-g×]^ùžèIDžÞņ:ï5FðœŸ6B¥85uŠ»ïº›WœêUòŒ2ÝŽ5gâJÅépPËÏ\iM· žÒq>E¥—­Œº³¹G>/ïˆÄžô8ZuۓA3 ÈjåÉ34?ÛßCÛXÅõñ³kϵNwMŸ EäU «GˆZ³˜Ð;ç*¥Qve§AitaöÄ-Øý[ P»ëx‡ïD§ döü *;œ¬ ”&5vîÁ¡þõ·Ì>†JI­¿¥,üÓ÷âÏ> @0÷(Í>FԘZsè­¿ýV6lØÀwÜÁÃ?|–°Z-ýB³ `Ëêq>±öÃN&Oõ|Ï$óóóÜzë­\qÅüå_þ%F㜓Ñêž$.ýœîœû‰ÎÿTŽY ýà T*ñc?öc|ãëß /mU êœk!ùìÜ× :Å'>L]€±N=o¶šÿáïÿ7¿ùÍìÚµ‹_øÅ_àû8§pïXYU7Ç¡ÂXVWðÅ ¶ã<µJ[±`Lô‘é€*ë€3ëI¯Ó+¢”²b!J'Îڱ讟`¥PvÇq=¬­|o—­Z;qFöb`öA¢öÞäØ#W`DZG®Ã?ñµî;ݓß!˜º ӞÇ=üO؃;âÈ%eՏÇÂpx7Qc†ðô· p/IÇë œÿk­ÑZ¯xí\ŽÛm|ßçoÿöoùüç?O?¿ó¶·qã‹^Äøø8###ÏOÚí6Zk<ÈÛßþvÞýîwsà 7ð+¿ò+ìÙ³‡‘‘Êå²Üšçç?:þìwß[j&&&žýöÛùùŸÿyÆÆÆ’2 Ï<Ï£Ñh¬L§×³ímzŠpŽˆŽ%ºÕjQ¯×©T*IRŸv«M&“Á¶m,Ë:+œÚ¹>¯óº1Û¶©Õjž®KµZ哟ü$_úҗ˜˜˜à¶Ûnã§ú§ÙŽiÓrD³Z®Î·ýŽ%Ñê|  cŒÝÇT€Ñ±ß€V@OäsÇ"©TOm©nP‹^Ρ#Bñ)EDí8u‰²³(»€ ZˍʲQv6¶&†î… vN.b0€Ö݈=ž;^)€âmk•*¬xXŠœˆ œ8wuЌtüræSM\ПõÑšT*ÝÕQ*•BkM†žžG#étQQ«×ãrŒ‡nÛxž×}ïââ"‹‹‹Œõ·›±±1^ö²—ñgögâàüܗ Þh඗î.,,àû±¿U³Ù€ÙlòÅ/~‘»ïŸ›ááa~ï÷~7Ÿñ"žTªUæççWL•¥åÔR­V‹Çœ£Gò‘|„Ûo¿ßú­ß’±ãy2~>|˜»îºk¹ðC2§„aHd"LdºÕâ(ê)ïû‡a\åhߟ}=vŒÉÉI²Ù,Žãà8¶mwKÓöV!;³*Yç<@·À}÷ÝG,›*• •J…ðñ|þóŸïqç0+j¥É_©x·²g{:þݱqÅ[Í]#bœCÙÖòv¶Z[[ΫX(D•#XÅ ¬ò6¢©) á¬ûqÒ;_Cžx€öãŸå‚ê•)M·š“_ÃŽfðë“…Dµc+lþ&ôéúDáŠgºjoäóþ÷¿Û¶q§kEìt¢ hµZT«U~ùo<+ãÞ{ïÅóŒ§Ìf³lÜž‘™™™çwòÕçQòÆ7ŒaEûhµZ=zô¬cûûûÙŸ};Ó3ÓÏŸï²ð¬c"ߌïOøä'?µâõÅÅųŽ ‚€k¯œc “““ BñyÁüü<Ǐ?k7«÷ߎ5жíÇi¥ÑVüs__ýýý¬_¿žB¡@¡P —ˑ΀ql‡T*…Ò:¶ã%ïïœ÷|ŸJ¥p‡oûÛÝ*s™L†«¯ŸšÝ»wsË-·°sçÎ$²Ù€¶“ •Nŕn%Ÿžê™•TVIŽé͗ëEëŒúÎ+}Š;"Òt"ªµ^3ÏyæQô *Öf°Ê[p6ýQ}4Q¹qR[_‰UE9)ÔcŸ¹°É°µ@؜Åî›ÀŸŸïÐP©>ìõ7CèVŸí$~Þê =%»Ž×ã¹k9Ëá]ïzÅb‘r¹Üµ(ch·ÛÔj5&''ùßø >÷¹Ï)÷º×œŽ/ùË4›M®¿þznŒñF^ð‚pÍ5×°cÇÒéôª‹+¯OÉÜôÔï –e­h ÅäÉI~òU?ÉÒÒétš×Œæ5ìÙ³‡«®ºŠœ{÷²yóæyÂV{ÛëÖÓcŽâ]ï~·ÞzۊûúÝï~—oŒ­5›6m╯|%Û¶mãÅ/~1—]v}}}|àï_ÅãÆ“¹Ž§=~Ü|óÍüú¯ÿú5W(¥žÿþûgϞ=”J%ŠÅ"ù|žL&Óµ,>`§-[¶pùå—sóÍ7sÍ5×pÍ5×°k÷.rÙív›€vê²%šSÅše `Of•ˆÁnRmº›ÊÉÛ5Š“š[/[c?È䜝:ÒJ­Ý~—|€ožÆ=ü%²Wþ2©±ÄêÛ­¢‹ë±·àMÞCØ8…]Úüd­…šr˜pîQœþ­8ëo†ÈGçÆHoýqÂÆ4ÁÜŸ§²Ì†(6e[¥Í€·ÿGŒß"jL]²§×qEÔÛy£ç`ïÞœÝ_xà \u啌/‹ëUl1êøµlʓMÙ,6Œ$E†ðÃŽ¡}Å>¶mÛÆÞœ{¹þúëyÙË^Ǝ;H¥Rkcú2†áŸ ƒù‘ýSU,-bàiµ ΎÂÍçóÜvÛm\vÙeÜx㍌ä%/aݺukŠmX–b¬”£˜qºcÇjÈCû\?.ZÃ'œÃ.„믿ž·Ÿõ­Œð…/äšk®aóæeœÐq¯éˆÞnÇ® L"š•B÷–îëVeQËùžuo՝ÈGœBšÎÛtJ¯ñ~—Ž3G>þäWÁJጜgÝ »$šN⟌÷`ï¶ó¹ÂŖ“dFSxG¿ŒÎ` í&{Å0Q@X;MûñÏašSq„ô¹"šWÔéCH0÷zh/Ny#:ÿS„µ“DS¬%¿ƒ·Œå-ž®Ëèè(Žã¬`kKÁö±"C…4§k"/"}}}Œï}ï#_È3<4|V4üjo#JÁh)Þõ%ÂаïdE„âEdǎüõ_ÿ5}¥>J}¥5wý–Òl.°Ÿ?ËÁé³µ¶”°{bŒáÊ+¯dçΝd³Ù³ gë+Nœ ]ÁhT˜ÓI5žNrµ,ö–ý{j:ë^՛ø1êå„ÝJ+Ö\e–Uµ21†ÈkàÿQå~q#*Ó~‹°6IX9„ñë±l/ÐÚ÷wú˜VìtmÜZþMÒžŽýöê§püoôôFt~äÿgïŒã€ªÎÿÿŸeúÌö]vX:" ÒQTPÔ|UŸ (b‚ÑXcIì=A4±`ŸËϊ1QÑ(*4ˆHéŠ4¥,lï;;õ–ßwæî,`Ãvá||­;̝¹;sÎsžó9OÅ ×`„«Ñ*×YÙÕzœØöÿ U¬A¯ûÌ8 ¡w^ÿ<Š¡AŽL ­úKØZzWÌHFýŽv3áÉÍ>77w¯…ÓŸNÔÖ)OIŽKú¡ïl"µ 'سž¹w·Ã.²G³û!¥ nêÁÒL4}7S§|Ç}ÛË@|C IDATƒu é²9 Vƒ*‰~¿ŠÁ÷¥&»øìYÇZjñì¢×-ÞgîùZio—·dÚÎ)ÓLëmQ×7ᾒڏþp»Ýtîܹ]“Y² âË|ÝÔD1Œ=æµyÞ “:"Õ«cî±ö÷”5»zB’EûS ø·7ÝÑæžVì}*9ÜçXÚs*%šI6\i&€©ëZj±øM{B±{9·˜=k J"™¥UL`D*1"•H_$rÐõ«†ÅЍh=±mŽ\ౢߌÓbbMÓ@«Ù5d œEåzÓЈ—.ßKЌHÑoßkù\žŠøî…PÒ|ŸöDÚ/ønâû}ל.•.Ù^ºæP M³:œl©&»dâsªìª ٝO Ód@QY>'%µQ¶–7 HÙéNúwÊ@•­Î.«wÔŠj˜˜x*GwL Ÿ)F‡L/Š,ñõîú–Ý"‚`À՝HnÜ} Òè”åÃçVˆiVǎUÛk Ç4z姑Ÿî!ªé,ÝR‰ªÈŠI:ez©kб±Ž˜fãwÒ»0 ¯“pT£€>ÌæÒF»7õðîYx\*;*›Èò;)Ìô²aw]¢Õ[ûèÝ|$I’p*2ý;§‘åwãu*Dâ:•QÖìšÅ¥*ôÌó“éwRZbk…U&F‘eŽ*p±³:dõ[Ö z€Ó1ÃCšO¥²!Êîš;«C(²„Ë!Ó¿S~—ÊêíµÛ%§*³vGUA¡;žÜ& kK‰.*©åk’ÖAIƔd’É.É€3iLTIBVZ’IiÏÞ}íĒ­¶‹É5M«ž¢ÔJ =%MýûïóÄÊÄê-I¢LH&‘’$Ñ;?@ï‚tÛâ'»TŽíš‰¢Hl*mÄ0L ³Œ Aim˜p\'Ûç¢cŠ—,Ÿ“í•A$ wa€£ Òpª Ši’îs’éw±vG;«›P‰Œ47>·JL3p;T¢ºf÷dV¶§_:€¹Ø5 °z:{œ*^'º_—ÔŠjfy0L“õ;k ÇuŠLa†‡NÙj‚ rNFõé€C±º7øÝ*ÙintÃdGU-ª‘p“îsðšVo_I¡ÈÄ Cè6š;I⹂4ºwHOÚûp;UÒœN"1Í¥(ŠLaŠ·SåÛʺi¢ÈÝ;øq« ;«BH@¯‚4vÍ@‘¬’)]rT 3=&”Ö…QdKw€yŒtªø=ªp‡샥ÒlFLZMɊ?4S’Y¬ß&Hê^UۓbÙ¶'‰dªåRnwœžÛG~vª©·µî÷³ï(Ñ H²}Äu/Ÿ­aÁºR¶•[ >?ÃrI”ÖG0L¿ÛA†Ï‰a˜ägžq;¢ºAeCI–éÕ!€CUøŠ¬‘…_—±­<ˆ×¥Ò£ƒÔ>ïNUàۊ6ín )ª‰‰h‹ÊO‚ytÃ`kY¹«Jø¶Œ‘˜®“—îÆçRØ]Â0¬Í??ÓHžT™€Ça˜T6D1%“£ Óp:dªƒQ>ÞPʗŵè†A<™^‡œYȒDÀí ¬>̗;kšiŠí•0"Ð6xCvÀE^º Ó4Xœœ†¹«w³£² U‘É žð8ª£èŠI–߉*[>K—C!Íã$ªÔ6ÅÈMsS”íÃ¥*ìšjbÞºRvV‡ð8Uв=žTÙv9˒„Ç©°¹ŽmåAjB11‡dŽdCJJP‚$Yg¥=^Ÿš)¥Æ?·Èž–¡rJƳܜõ +ˆE6`1Ò ƒ÷WïÆãRp© ^·š(ŽeârX„®1§ž:H·ÜÙ~'»kCtÊòâv*l(®CÓ!×ïÀçvŠjT6DˆkPŒÒÍð“ŸáÅíPZt#ØVdíÎz€ÄéTð€¶݀Å[ªžœªLÀ­ ÉšfâtÈ(²ŒŠ›ì¬ Ò%×O—;«Bø\Ò=êšb4F42œrn4Ý €6„ŠIԇ4*ê#tÉõ“é SR¶7Ú`Œe[«‰ÅõœbÚÎ!¢¢!ʂ/ËIó8Pd‰t#ój@eY¢€6D4Šã÷8è’ëa{eˆ®Ù^LÓ€!£º)ʈül2|BÑ8¥uaŠDY]˜Â 7Ùi²üêBÍîå%õl,mÜ«ö­À6F‘j54[tj1Q,Ëbâ²i×ä¶j4›‰.,VOg¥Å±#ÙÁ%ՒhõnÃ#ˆ¢ÀákH¬õLŸ“Ü4'…™>ª,ÙIqÝ Ž&B÷Œ4.^'—µ4vׅ1L·Ãú·S•é•À°‰Dëz,QÔ5®D5+‰B²íBÑ·ÅœÁ§*tÊöã÷ésàr*(²„‘ÈR%‰Òº²-ÙI÷8HóªÈ²Dc4NDÓÉò¹°’gв|ä§{eð8­Í¡Z–¢€(„¢†aŠÃCײ¯JçL/9é>'ª’R/ˆiu¡NU&?ÝÍîš0yénÂ1êŠ8†aHUYF7 Ž*HC7LK!¡H&ê~œúpÜNŒñ`E3¥€vJg€Ka2ƒ¹¹[‹åjNò?+Ž#Y›ñ»g€æ× ¢( p°»¹µ/áRN<*¯ÛAIu_í¬ÃïQéS˜žš}`»ò†(qM'Ãï€w~NEŠŸ)FM0–ÐÖý À!¢¡éVëÆòú(7t[%&èºPôm]>\…ÁÝ2é’맺1Ê¶Ê NU&7ÍMšÛ ²P^¡¶)J–ßMÏŒ.…`$NuC”žf ÉŠ‡ŒivšašH„š FíC‰™ B6Ú¶Œ˜&tÈô0 s:Y>¥õa6î®Ç¡È è’ÙÜìM–ØZÄíTÈÏð’‘—6Lqur"†]’¬bná81-©;"h†I0ªµ ±xûJÑö/Å%mJŠE‘‘”öý'ˆ¢@»‡"KžœûeÃ$Ýk¹Œƒaµ;ë©Çè]†mÞI@Ó Êë#䊹pdºQ™ÒºšœiÔG¬â¬šÛ+ƒT4DH÷:É ž‰ë:a€[µwCD¢·ýïrš8ö0ÛºAÀí 7ÍM$г©Žo*‚]˜FAJ­3Ý4Ù]"?ÃK~ŠU–(oˆRÕ³,‹žn¢(&U 6”4àsªäйQdË ­Í·4²ÑV «2.UÅH¢qÂ 7~·ƒÆHŒõ;ëšiŠÑ;?-•V IPŒRŠ“íwÑ»0 $‰ºPŒ†pI†ÆšF4®#IÛ*›(¯ð8)ÌpÓŽÓÑPU)Em ù8§„æJØv}CÓþm—>²ÝӉ–¹R sŽãI„75×T4åqR;Z™"ëYà íƒßWêA¶ßŀÎ{þ-® ه@Uœ4'9³<Ȳ„ªÈö:ÕM“І…™\M3šjŒØt2Ö †ãxÝ*œóøÜ*yi.ºçØ]bwMHlÿmM÷c% ì’Éž÷Šú(1M³Ld‰ ¯ƒ¢,/³Œ€yvCÐ “’ÚC¿K j‚QêÂV"JSD³âUóütÉõ×­¬çny>Ãq‚Ñu¡æÏ$ä€ éŸƒþÓE”›9öʠ][V‘r.|n•.¹^‹`ÊÍá1M§²Ášÿ¬€ Ã0©nŒZ.II¢¬6B¶ÏEAЇ^ùÜ™‚ Ýóül. RгO8è'†â—ìÄ"I‰¢Ùv!ÝLtl1ä©EE’uå=:€IvãhQGQ íÇÃÿ{Zß5Ãç$÷w{¹šÆ;ª›ØRÚ@AЇa=²iÅ)¯‹pãu©dúœÔc˜ŠIecŒÚŠÙ7;k‚Ô…b¶;*Šé,ÝZE~ºåúé”í#Šél¯ ²©ŽÝl>HJ²$ÜFm@6ä„âîS˜¶×uE ²vg-ëwÖÑ·S:};fÉÓØU¢)ŠÑ=/@z"žU7Lšb»kšè˜å%3šnŒ¡éF"aÊdÕ¶ À(Ûˈž9Äuƒ†p”õÅõT7Ælِ±I‡^GZºÃE†Ïµ×õ†pœ¥ hºNé ìšI,n°«&„"I€{<ªƒQ$Y¢žº‰Á]2q:"ñ8¥uÖ!S*#¬øVãžž9fzè”å%Šëì® ³©€žH\ÇçREqíCJ-Š.É Š¬ØÏ%‹ŸK’Ò¬XtŸ¹ð¶i¹—“$?áf–RþO*‘”›;µÐ“Y’ ,µZœl÷¡ùmºimÎ{º›eêšâè†ÉƒvV7áqª„¢¡˜Î®ZËÄÓÑ0™ÉfŠËž¬6L$®·PÜ5ÁÑx=»ªC8™šfЉŽZ…àC1ßT#É2áx›nã™ôn™­q“6÷ÝL¶U6QÑýŽXr‰P4N4®S\¢!ÇëT‰ëõ¡²$±³*D0·:o !™’wŽk4„c-þ^T3ØPRǎê&<M·ÈeC(Ž‘è/Œb[ E¢)¢¶îÅöP/T3 Ö×±¹¬á;uG}(N(г¥YÔôÇv;iŒÄiŒhHRÔVnÁHsCx—S!àR蕟F–ß•èŸ`YŒZSà!lÐÑZlŒÉÏ€é)Ÿ©-o˜VrŽ„Cuî×û+++©¬¬$¯cÛŽ5„ã4„ã?øÚh\§¢^ß«Ÿuòœª"“îQÉñ»é”ã%7šš‰ïYºÄ€1¬ÑÖöÙ[*÷èGÞVå£%‡•~ùK®Íh$Úâ~må«J’•Ñ^û#»4E4šlݑ˜”õïvª€¹T:f{pš2ºa²¹Ž¡Åx%Ç€Š)šøwtä* Í4Zô«—ZX¯ÚⲬ (ŽÃfWEJ”¹A²ÈŸ©ýüLYNtd±J#%ÜÍס¹ºAŠ«Ú”šÃX’uI”Ói×1ŠVáOӄžE…”–4ѵKz¢€ƒ`‹‡òŽPR¢_¯B@BQ”ÄÉ€u7I’8ù”“ùò‹Å 9i\óßiCd`ÿÞ×|Jn€nFôÌF’%¢šÁ¶ò ‘ž¶×ßù¡ö‡í©_¯,˔íÚN¿cŽÙ¯{TWWãòp{œ)6†ÃA>€VU–9¹_>Š,¡éVRËÆ’FöîÏŒ÷Az»Hú±MÓP…ãÊçN®)×@,³KHµ•ïß²‘Da†‡A]3Qd‰˜n°£¢‘ʆØ^ëá‡e¡ýèI’š®,ÃE”>}ú{«,)-€užiîÈb[‡¿KÏIɌiÓΆ·¬®Íõ›;Œ€Æ-¶“ñÙ瓲Œ¢XmÊr º°±žÑâՂ$òªk_ïj¢K÷ÞȉX8Y–‘YX­‰>}úPŸc ñXô0{+þ€1¢QZЬ6Â×Åõl)oLžOy—$ Ã4)Ù±•~Gµ_÷ÈÎÎ&àón¬O–ÇEGLÓ)­ QQakY#v7Ѝ¶Þ•äaŽ¢€‡dâö‹Lv€S~µ•å‡uûʆPŒÊú0eõa6îjà«Ýû:DfºÃ0©,݉GÖèÖœûá"ù-~µHJI’Ç€1F¶zûÙ=ž“ÓÄrO[Ež±_HäÃ$£v7:jªHX€ÃÎöRdƜuÿïÅ¿!™Û1 €×ê8žˆÅ B¹‹‹yi‹›ÿ0 ‡Ãa[ú’„±µ,‹’$qÚi§ñ朷˜÷úóœ8î2sóP®ÃF &¿F]8΢MU‰“¥d%€HÊáG$ˆG£D"aV-ù„«?â¹§ŸÚ/2‘››Ë„óÎeꎫ8ö”s0l$þŽ4E=lHcrþo®¶÷Y–eå°%‰±h˜ºê*þߌ[™zц ²_Dï̳ÎÂíròÔËÿÇ ãϧ°K7ÜnßaG ªCq&t‡$I(‡­|†NS°Ê’bæ¿þÿžúòÉ :ìð8X‹IQRÚó&È ¢$ú6'\҉‡È²ÕZ–1åD÷)µÕ_Šõ0ï(Š#љ…æúŠí‰(ʲÜâGUU:tÈcÄ)gñ×9/rµ®Ò¥ƒOÀÀÁE°>NIU˜g>Ó8÷‚‰x<E±ä”ú­öpÇí·qÝ ¿gÕ¢÷éÖooÀZLíá`= 5•lYöwÞöGrrrm’ðSâÐz÷îÍà}Yôö‹8U‰ìü"\n·èÞ^‰¢aÐP[Iَ-Œ:n§ŒƒÛíÞ¯{y=†N—÷?`ݧóhj<ŽôÌŒzJ ]"0Ž8¥Å”~ó%¿7гÏ>»…>hÿß1ÑVÏlnݗŒ`»¡­š8Hfê>›²ãŠ&ÿ&»¥6hI&»$+q¶“€6u_›€¢(šªŠÃéÀï÷3tèP²srxû“)û¢‚ÒŠJtCÇ0Ì}v<h-kF³¥°(?ƒììB®Œþ—äåäàp8p:ÍVEÛ¬Ý:I.Éy-**âõŸÆË/¿Âºu‹ÙZQ†Šéb‚Ú§®§C~ùùŒúÊ äåæíEþ~ª|<ñÄ|ùåz>üp›–ÿ›Æ†¡Ú)TU¥SQWÆÀ¯~õ¿(ªºßÖ"Ó4)((àÉ¿ýÿ~ü1 .dýò¹èBwŽÏýH–p¹ÜôíןÓ'žÍž±ã~ò³­BÓ4dYÁHä¯XXL»E_ó $vXيGŽö\ËÍlåʉR:Ø©f׳)Ëv)E9¯(µ²žo‹¢"ãt:Ñ4 Û®ëtîԉ_þÏyD"B¡šŠÇ‰Çã"v±Õ7t³…e×åráñxp¹\€§§ãñzñù|žÝnœN'ªCE–d ÃH˜¹Ÿà¥fnªªÊe—Ms˜ÊÚþ¬ßTùèßÿú÷?F Аòaš&Š¢0vÜ8Ǝ'ô°4hHí^Æ']tK¶}˰=P俢Ù6Q”åæ¶{Rs?gË£,%º¬€X VE«ÙK2™¥¹¶¢i[+Môx ÇÝæÉ¢ºç€ËŠŒ"+šÕ²Z¹\ž4 ·Û݂ÀÄb1t]G×­rŠк‹ÏJP‘U—Ó‰ÛíÆåráv»­Çn‡Õ¡¢*ê[žâ œ!B6Wœ6nï=ö8=rsÈÏËGOÄ&­€–DjîõLJMÅf¡Oyº¹ŽN3ùTìk† ¯Ÿý6>Ÿ¿Åz‘¥¶×°AM&B†aÅ%š–ËY×uð€Šë¶+Úívãõz‰F£Äãqt]Ç0 $SÂ0 !q­š “Ý=¹yì+Àérâõxñx=–EQµˆ¢eB—EŒ˜€€€€€ÀØk‡ÆŠSÇqÞcOðȄóÕ¿š¢6g3'‘¬­h²ÒÂðh%·$KM@•ìëÈIÒi"Éàp8(-)៙3ùÏâÅLŒàBëö‰|ƒ¶ˆEY–-W£¢ât9‘$ Ÿ×‹šøN§“X,f“DMÓlK¢°(¶Ÿ§&% aÒ²èr¹p9]8NUÁ4,k¯€€€€€€À÷CQdÙ ³;å¿ 3;›‡Ÿ™Å3+–sùqÇ1šWoTERP””Bي‚ÝÉEnÎl–’Ü%¥E†Ž®膁Î¶o¶òւX°t ²ËÃégŒÇçóYû»¢"+²ÍÃÚ,QL’EQP ÉÙli”e‡ÃŠihš†ahš&HâDrÜEAQUTEÁåvÙBår¹ìŒgCžz~YT…@ @Ϟ=ùå%Sغy3.YBèÝwTTÄ/¢÷.äv(@2LÉâDVÉÓ0¬9€dš€a=o„Yœië·}ËósÞBVUÙYvëN  -- ŸÏ‡Ïç³öv‡Ó&°mŽ(&ƒ–“¿•D-!).áñxÐ4 ‡Ãa[-—³5@¢x` ¥Ä)XÂ,£(*Š¢Ø™Îªš8H2š© ¢( ð#÷XEQðx<øý~²²²èÒ¥ iiitêRDYiåååüí« Ô~ò µµääŠÈKËÄëvâqžñzÜhŠA(%€éÔ44PR]Mmc#º®“×!ÏGÿáÃðz}8TUÅãñMnn.YYY€¥¥áñx¬}]jƒDq_í…LÓÄát kÍV­$a4 Ã40 ‹ZZÉÂçÉùHuC˒Œ¬Z¥ÄŽ( ðãÉ¢,Ù€---¬¬,dYF×udI&##ƒÎ;Ç‰F£466‹F© ‡©Ò4ôXZ]E:UÕòŒúýtÍÉ¡·Ë…ÛåBN©wìt:q&’S}>ÙÙÙdeg‘‘‘ÇkU6QUµÍíç¶ë9µB²¬a 6·ôK’Äd–³ ˆþē$IStòq’?‡ôôt>ŸÏºæp¶ØãÛQÜ× &›Š Js!è$IŽzšmZÂá°}*ƒ466RWWGmM- L˜0œÜœ6IS­„ßEäElš€À¡Åï®úº® ¢(`ï{nôuuu“““CAA€6FUEErY].n—×C,#ÑÔÔ̵kPäæLiY–í$Ó€Ç5IeEANÐäÓéÄã±JÚ%3œ>¯õœÃ‰Ëé²=…m êöÔD—ö‚`0ÈèÑ£Ùµk—Íþ5MC‹kĵ8Ši2þ|òóóÛÙJA-þþ÷¿³sçNÀjgxíµ×ŠA9ÂÉaò÷òåËy÷Ýwyùå— ƒ„B!6oÞ,« Î[Òò§$*‹x<ü?ñxœX,†Ši455qÎ9çàr¹ö ÿ’e™H$œ÷ÞËÉ'Ÿl'«‰TUµ˜$›d8VY»d“äßOõt¶%Ÿ¥þB²¯·uf͚ÅÉ'ŸL(jqÍçóñÑG1bĈœâ ÚÛiHÅÖGyy9åååtìØ‘ììl1 ûÜ`Âá0Ó§O·ŸûӟÿÌÔ©Síx'#’$±â‹Ì~e6+V¬`ɒ%{œfâĉtîÜY V›·Ôߊ¢Ø±‹ªjՓvkn4Mã€Q'±dÉ&OžÌÖ­[÷º×•W^Ée—]FSSS3‰”­Š²"£*ª]©D‘›\’äpOOn[Âa[¡Ù4M† Ƨ‹?ÅétÚÏ'»›\zé¥,X° ƒ+wäȑôîݛÂÂBŠM›ÆÜ¹sijjÚKƄܹÌ'‹±cǎæFY~ø¡ ‰G(zöèÉðáÃY±bÅ>¯Ïš5K Ræ ©I(I  Ûeu£KOO'3#“xûlü~?;vä‚ .hqÈ82qՕWîõÜõ×_/æEff&]t555sÌ1dffÚ×.žàÒÓÓÅÁ² ó…äï=³–+++™={6ýúõcÔšQTUUQSSc¿·W¯^|ðÁvñl¯×Š;L&Å8Nœ+ã9ÕŝŒElëÖÄÚ(ŠøÔ©S™={6~¿ŸE‹ñá‡Ò·o_jjjøÃþÀ!CèÕ«oœõV‹S†À‘‰™3gîsÁšŠÉ¥S.eøðáB>Ž`̚5‹íÛ·ï¥oŠ‹‹™9sŠ # I]°fÍ:wîÌúõë‰F£¶\L:µÍ’œçQ’$jëê˜2e G}4—\r 6l 77—÷ߟÛn» €ÂÂB/^lÕ4NŸÔ¬çTká÷q”¶ùH™ü‹.ºˆk¯œ–`0ˆ$IŒ7ޝŸúŠÕ«WsñÅ“——ÇÖ­[9ïŒóÈÍÍåþûïgݺuû"Ã_^W_}µý\ZZ}ûöeùòåœqú€¥¥ ¥„ÊFc0ȋ/ŸÈUW]ÕB'†Áu×]ÇK/œD}}œÐG$Iâí·ßfĈÔÕÕ1~üx6nÜXŠqãÆ‰AjÐ4O>ù„I“&‘•™É‹/ŸH<gìØ±Œûî»TTTpÆg‰De™×_ŒŒŒ1Սü]?í ò‘²ˆüqnºé&ªªªìø²òÊ+¯°víZ>úøcN<é$ªªªžë®»8îžãèÖ­Ï=÷œ}¡ü y1M“©S§ZÙk ¢žaÃúôéÃ˯Œ,G°l8æÎËßþö·œ®?öØc|øá‡8Nq8 IpÍ5×0aÂb±>ø sçÎ¥cǎx<^yå1XmxZöö IDAT“xúé§)((`̘1¶ò®»ïfóæÍ̛7³Î:Ë~mCCóçÏgäȑGÄ> iB1}útŽ:êšœ˜} `Ì)§ðé¢ElÙ²…ßþö·tìØ‘íÛ·óë_ÿI’žýöÛY¹r%º®ïSÐ/B0pà@ÀŒyóžæšk…B\2ù|ðA;ÞUÈÀ‘¥C\.YYYßùšÌÌL<‹Ã\$I¢ŸŸž‰'òä“Oâr¹xá…l·$X™°§œrА…6J7oÞÌôéÓ \qÅTWWsôÑGóÀ`š&÷Þs………¶Á ‰ /Œ1cÆŽ»²ûœšB‚¿Á`7rë­·²`ÁÀʚÎÌÌäÎ;ïláš<”B¯éñ˜U5Ÿ©©‰ŠPˆ†úzŠ‹‹¹òÊ+)//“¹Ÿ(..ŠššˆP(„ÇãaÞŒyœqÆŒ5Š… ¶Ë:£­{š†#$VUW1lè0¶oßNAAŸ}öݺu³¯›ŠICCééébÐ~÷ß?ôíÛ×êV’Àçõáñxì‚Õ?·uªŽ^œz5“'Ofûöív5‹ÓO?éÓ§Ó»wo<Ï^ïÙ×}ŽÈBD¿>Ÿ¡C‡2þ|ÊÊÊžúê«éÑ£\sÍ5H’Ä 7ÜÀÒ¥K‰D"û<±Žï ¡sçÎÜ}÷ÝšªŠišœ~úé¬ZµŠnݺ±hÑ" Y»n­K8ôA’$̟?ŸÜœ\¶oßΰaÃX·n] ’˜<@ˆLçC?gIÔÔÔðúë¯3hÐ ÌW_}…ßïçâ‹/fÓŠM|ðÁ{챞Ýû: ¢(°—¥ C‡̜9“/Ÿø‚µk×rÁVLÒèÑ£éÕ«÷Üsñx\X³ù¿éŠ›ì¬6Ó44hkÖ¬áŒ3Π¬¬Œ!ƒ‡ð¯ýKXs} I÷Þ{/§žz*`Å&.^Œ˜œœœïŽ4 œphI}0dÚŽiôéӇóÏ?Ÿ5k֐™™ÉoŒÁƍyå•WèÝ»·˜/A[‡0xœ^ À?þñªª«žýöÛéÕ«»víâÞ{ïÅét2í7ÓXøÉÂail¿ðûý{UðŒÿþû\qŘŠÉĉ¹ù曉ÇãbŸ3Ò‡™2e ÷Üs.—‹‡zˆ'žx‡Ã!Fƒ®ë,[¶ŒË/¿œ@ À3Ï}úð›ßü†ŠÊ a‰8LæÞ4MzôèÁWŸâÌ3Ï€¬¬Œ‘#Gòøã‹ùhÇ$ä‰'žà€DmÝ /Œ•+W’™™)Öt˜I’X·nC† aàÀüþ÷¿§ººš1cư|ùrV®\Éý÷ߏ¢(bŸQl{„ÀårÑ£Gyäâñ83gÎdàÀÔÔÔðì³ÏÒ!¯gžy&sçÎ¥¶¶vŸ§$ö5ï>¯¹sçrÛm·F¹þúë¹å–[ˆÅbbnÚ ‰ÇãÜ~ûí\wÝuD£QîŸûn^}õUœNç^º^àࢮ®ŽwÞy‡Q£Fqì±Ç²jÕ*\.çw_}õ}ôÇÇëõîso؏=NÄ(xœÒX,FII /œôwß}·ýšœœFÅ£>JQQÑ^ïû¡û‹ŶwÒ]ºt)£G&3xð`>ýôSŒ^¯ˆ‹9Œ B•ºZ×uN:é$–.]Šªª,\žN8A¬ÝˆŠQt:455ñÇ?þ‘7Þxƒ²²2Àê˜õÿ÷œ~úédgg‹<@ÅƒŽ‰8NºvíÊ]w݅iš<ûì³ :”P(Ĝ9sèÒ¥ cǎeΜ9TTTìE@Úþ\']ÑÇ<7nä裏fÕªUdgg³téRûº˜S¶G×¹žüü|–.]JϞ=Y·n ‰‡Š¢ ë:kÖ¬áꫯÆï÷óä“ORSSÈ#øÇ?þA}}=_|ñ÷vJD±Ý*%€Ë/¿œe˖±yóf~øaÜn7}ô&Là˜cŽáœsÎaÆ ÂbÑ £ištïޝ+VpÉ%—‰D8ñÄùË_þÒnà ÎkvΜ9 4˜ªª*Î:ë,V­ZÅÑG-Hâ! ˆ‡ƒ×_~ýúq 'Ø}Õ¯¿þzŸþúk>ýôS»–±˜A[¥dO€,SXXÈM7ÝD8æ_ÿú£F"óïÿ›~ýú1hÐ þùÏRZZºÙhÛsìõzyñŹõÖ[Q…›nº‰Ë.»Ì®±)æQ@àÐØ ÃàŸûîc„ èºÎå—_λïŸk—4$äàèKEQ(//çÕW_eÀ1˜6mÅÅÅté҅oŒ‘h,Ê£>J÷îÝíڕím~Ú«7IÄ(¶!J Œa”––òÞ{ïqÇwPYY @VV={öäoÿ÷ 2Ä~ŸˆQlXŒx1't;v䋕_ß!_œˆ“CP¥íº®sâ‰'²lÙ2Þxã &L˜ æ ïy÷ÝwO?ý4õõõƒA†Î}÷ÝǰaÃl×òžºò‡tç÷œþûޛoޚß5Û-¿ïoï©S’^ªŸòÝ[Â¢ØÆ6°¬Œ;vdÚŽiTTTðþûï3räH QèuèPzöìÉóÏ?Oqq1Ь (ŠÄ6ŽO<‘êêjúöíËîÝ»9ª÷Q,^ŒXDC€o¿ý–Ÿ}û²lÙ2rrrX»v-&L„ÿ“Ã$˜7ocǍãî»ïf÷îÝH’ÄÈF2oÞ<>ùäFßïÇ0Œ}’+I’…Bœy晌7ŽqãÆqٔËxïý÷1 cŸ¯_·nüñ>õîòå˹ꪫZ„ýyH%zuuu<ÿüóƒA$I"röÙg3vìXN=õT.»ì2;ŽýÑÇcá…->‡$Iìܹ“Ç{Œ†††ƒºo¢ØÕgœÁgŸ}Æ×_ÍK/œDǎùæ›o˜:u*ä„Nàã?ÆãõÂØÆç3++‹•«V2eÊ8å”SžóÎ;¶Bøñ:õwÞaРAlÞŒ™Aƒñõ×_3`ÀaÝ?€ãžÛX,ÆM7ÝDÿþý9ãŒ3øhÁ.¹ä^{í5ž}æYúöëKSS“MݺuãáGæµ×^ãä1'óùòå444ìóµÛwìà‹/ŸØç5Ã0ˆF£-É%Ò÷Þ‹µk×îå6ïС<ò¯Ÿú*Ç< , ¡¡ËŠLaĈûü|É6±?ç³üTšB„Û.öTX¹¹¹Lž<™É“'³hÑ"Š?ô«V®dÙ²eŒ?ž‚‚®Ÿúj†AFzú÷¶<8tóérºxþùç9æ˜cøÃþÀ<@yy9ýë_Eë?DT’kê™gžaÚŽiL™2…çŸþ;u®@ëÀ0 6|µ_|‘¿üå/8È 7Ü@II :t ##Ã0~2ùq:äææ’ÍäI“ùӟÿDEEÅÅÅŒòÊ+D£Q4McòäɬøüsV¬XÁĉY°`Û·o§ŒŒœ!C†0|øpJKK™1cÛ·ogÔèQLœ8‘YŸÅîÝ»©¬¬€S§Nüîw¿ãùçŸg˖-Öߜ<ÀÏìWf‡ÉÍËåŽSO£Gögü裏žêª«p¹\ös‡ƒÜÜ\rrr˜6m×]w555ŒýöÛ 8x<Î?ÿùO²³³9ýŒÓ)È/@’$¶mÛÆë¯¿Î…^ÈQGբ㌠Š‚hX ‰Q£F1jÔ(***øä“Ožçž{ذa·ß~;>ŸŒŒ<Î?ÿ|ÛÂ(ÈGۛÇßÿþ÷Œ;–SN9…gžy†O>ù„Å‹“››+æK@ Ib'Näõ×_¬nY]t‘Џ˜˜Ï™3‡Ûn»mÛ¶ÙÍŠM›Æ7ÞH×®]q:<ðÀv_æŸ Y–ÉÌÈ€©©‰`0È/ùK223ùtÑ"JKK9öØcq8(ªBQQcǎeÓŠM̚5‹N8ôôt.¹äV®\ÉÖ­[©ª¬"3+“SO;­[·òòK/Yqÿ&Lž<™ÚÚZ\nsޜCŸ>}0`+W­dñg‹m¢šë:’$ár¹ŸWÎ233 ƒ„B!âñ8¥¥¥ <˜Ñ£Gcš&ñxœºÚ:Š?ô_|1}úô9(^DAÛ©U*‰ÜÜ\&üï~õ«_±èÓOyàþûY³f Û¶m㡇B–e~øaÎ9çzôè!¬ŒmŒ,0€ 6pÚé§±vÍZòòòøðÃ7n\«T ©„¥¬¬Œ³Î:‹•+W’““Ãk¯œÆ/~ñ ûºXc­KKKK™7owÞy'%%%tíڕ3Ï<“‡~Çód~õiÒªÖÐÐ@mm-™ìÚµ‹Õ«WƒiRU]M^^ža‹ÆØ²e +V¬ ÓÔÔX•*òóó)(( ŽŽ”P(Ä®â]lÙŒ…††‚Á :t oÿŸŒ÷Þ{ÖßÊÈà‹/Ÿ`÷îÝlÜž‘h4J~~Ÿýù¶ïØÎ±Ç‹ËíÚës'‰^c°‘ÆÆF222ìë#GZñš>ú(cǎ¥ššˆ/7|INvåee"™EàÇC×uB¡ÇÀ‹/ŸÈ»sçòÄOМ{w Ãà–[naðàÁôïߟW_}U X#‹:t`ù²å\ýõœvÚiÜò‡?ˆ L@ ˆËºuëèÛ·/+W®dàÀ¬_¿ŸIh=}öÍ7ß0fÌú÷ïÏå—_NII Æ ã?ÿù«W¯æÉ'ŸÄãñŽj\iš|ûí·<ñÄ̘1ƒ¿üå/äççÓ¹Sg6mڄÛíŠK×®dddP[[‹Ïçcǎ¬]»–ªª*ºvíJzz:ñxÓ4)++ã•W^áƒ> //UUùæ›o(**"''ŸÏGiY•åtíÚMÓ6ùíoKnn.:t ;;›!‰Ê$ßlý†~ýúÙÏIìÞœ›™3g2cÆ šþC‡¥cǎ¶ûœ¬¬ŒH$ÂÀill€©©‰O8‘ûî»Ï®Œ’ŽÒH(÷ÜsÏ=BÄÛ7 ÓÀÐ 4M#¢( yyyŒ=š¹sçrÁP^^Î7ß|Ü9s˜>}:Ši’››KffŠmeŠóÐ(W°ŠÌž~ú逧§³páB-ZÄʕ+?~øàŠ‹‹ùõ¯M^^›6mâÚk¯E’$nœõVŸüòËŠl±ù|‘t3wÜq”••1`ÀæÍ›'H¢€ÀÐuÕÕՌ3†—^z ÇÃ?ÿùOnŒñF±~Z†a°iÓ&n¿ývEáÁ€žž˜Ÿ}û2kÖ,B¡×]{-ùùùeïøŸ9míùޟû¥ZPSß0?· Šû%ä:uâ™gžaýúõ,]º”sÏ=€éÓ§3xð`Ž:ê(yäâñžP®‡hÃs:,Zވ[oœ•X,Æøñã¹òÊ+íë‚À Ž\3’$±víZú÷ïÏÿû_233Y³f 矟°ÆÿLò ðÞ{ï1hÐ  ğþô'Àª}žvíZV­Ze— B‡Q<‚8îžã˜3gõõõ\wÝu±sçNnŸùfœN'×\{ _|ñ…£±§ò8p€^UUþô§?ñâ‹/âõzùûßÿιçžK]]] w†€€X3óçÏgøðᔕ•qòÉ'SSSCïÞœ÷:( üxrXYYÉìÙ³)**⬳Îbݺuäääpùå—S__ϋ/ŸH¿~ýp:û4J¢(p˜Ó4IKKã±ÇcíÚµ|þùçL:€'g>ÉqÇǀøãÿh·„ñà̏iš\rÉ%¬^œš®]»òöÛo3`À¶nÝ*È¢ÀOh’òÿûßÿžÓN;X,ÆÝwßÍüùó…Žúzgç͜uöYôë׏I“&Q\\̀x÷ÝwY»v-Ï>û,iii"Š]E#0ø|>†ÊsÏ=G0äî»ïŠK—.lߟ‡zˆ@ À¥S.eéÒ¥vÝ)¡œÏ>ûŒµk×rÖYg‘™™¹ÏœC@Ev@(dI €ŸyŸ€ñù|ÜsÏ=|ù嗬Y³ÆÎŒ~éŗ9r$ýúõ㪫®¢ººZ(Œƒ@äý~?K—.åþûï`„ \vÙeBa ‘$±ªºŠ!C†ðÊ+¯ŸŸÏʕ+™:uªˆGü‰ãVÖñÀ9ñÄyë­·p9<ôÐC|õÕW,_Ÿœ‘#Gpr˜מge1Ÿ‚( üÜFbI͏­K?kÑ&áv»éß¿?O<ñŠi2cÆ z÷îMii)O=õ999Vg˜E‹š««ÛçiU u ( wÜq/¿ü2‡^x‘#GRQQ!Æ\à°'6Ir³xñbrsrÙŽiýúõcýúõôíÛWÄŸ0–ß~û-÷Ý?’$q×]wñí·ßÒ£Gžxâ "Ñ(·Ür :u:x:E²Úï)ŠòÙ‚( ŽÆ„Š'UŸ§Héþ’F€›oŸ™M›6±qãFî¹çŒ^/oŒñ£GæØceʔ)ìܹS,ðtê˜4i_ý5EEE,]º”°xñb1懵ìK’ÄôéÓ9ùä“+6ñË/¿$''gŸºJ`o̟?ߎ;¿û®»+{ùË/¿d˖-¶çè`5UU[9’û˜@Y{¢àvû?꺎ŠiÄb1ššš‡Ã466²{÷nÎ=÷\®Ÿújt]? 'C§Ó‰,Ë,Zވe˖µžVXXÈ駟N ° Ž ŽîÆér¹˜5kõõõLœ8‘‚‚1Ö n·›3fØšh4*åÊûÇÌúõë8úè£9û쳉D"bp~Àx`š&•••ŒõÖ[„ÃaûZ^^ÿû¿ÿKZZZ‹Ê{^?ûì3®»î:úöí‹?Àﳊm»Ýn»à¶8¢(ð3ˆ¢a6Q …BD"©««cŊÔÖÖ‰DìkšŠ¡iZ«‘Çä)0IwìØÁÒ¥K÷:1Ž3†üü|âñž 2­šdEaǎ,^Œ°Š«Ÿyæ™hš&èÃårÙÝ?&Ož|Pú®‰2 …xçwìçÎ>ûlº®‹úŽ1s8ÔÖÖ2þüŸÏÇèÑ£IOO·uöŠÉ€‚ììlü~?ŸQtºœ8TG wŽ€ ŠûAMÃ$®Ç‰Çâ„Ca"ÑMMMƒA›0†Ãa‚Á Mc±Ø#kŠ¢ Ë2˖-cñâÅÔÖ֏ÇËÊxòÉ'Ó¥K»çªÁÖóõë×óÆoF),,äÒK/%ˆñ=€ðzœÜpà üõ¯ma­øùe™’’ž{î9B¡iii\}õÕqØüŽñŠF£”——³hÑ"Ÿúê+YYYŒ?žŸ}ûÇ‰^eUUq:8N|>>Ÿ¿ßOFF†ýoŸÏ‡ËåÂårÙíûQDQàgEÃ0Ðux À°aÃx衇J<ґ„dL€eË–ÑØØ(ågÊ®aÜ|óͬ]»°zÐ:TÈmŠu»Ý,]º”矞m۶هîã?ž‹.ºˆnݺáõzÛ€þL dY¶¬†N'§Ó&ˆ6It8í$AQhE²˜LRIZcÑ(ÑXŒxÿ~ûß\wÝuD£QFÍ_ý+YYYGŽWA’$Ün7»wíæ`ùò唗—бcGnŸùfŽ;þ8òóóX ŽVý>H-ký&,‹Š¢àp:PE¶\Ó©µEMEAZ(&§1i-LÆ,&Lӎ㓯o‹S/Ë2^Ÿ—ÅŸ.fƌ¬_¿ÞvM§§§ó‡?üSO=•‚‚TU®é¹Ùx<ŠL™ÂÛo¿ ÀŒ‡æâ‹.²Oêû‡ÌÌL<¡PšEg"'›º®ó·¿ý?ÿùÏH’Ä9çœÃ¬Y³ŽèƒŒªš„Â!¶lÙÂÓO?Í믿€Çã¡S§NÜ{y晄ÃávgmµÝÈ(r3!TY‘-²(º³¢(к$1µ?sꏮ똘º—fbî•ÀÒV§?©ù°2Ç'NœxĝN'’$ñøãó /°yóft]G–enŒñF.žàzõê…,ËírŒRÉ_* L’Ç€•1õZRNYDQ •cêé2519Íßõ»­Ÿ@].ëׯçŽ;î`ɒ%TUUÙ×ÿô§?qÞyçѱcGœN§åVRœoK…ª²dÉÎ?ÿ|***èÞœ;ÿùÏèܹ³ˆÝx<žDQÔQüqPT…âÅœvÚi|óÍ7ø|>æ/˜Ï땶a IDATˆá#Žžî6ÉøëÒÒRÞ|óMn¹åûZAAW\q7Þt#n·›x,Þî¿ë^ÄQjvIïI ADQàÆ}=Þ†ÙþHA2–±ŒŒœÏ?ÿœG}”ÿþ÷¿ö†Ý»wo~wõïøõå¿¶]ZŠ`Œ{“EE¥€€„ /ŒE‹áóùxíµ×8묳¬WŸ4–©DQŒß³¹sç2eʪ««8p ïŸû.;vlS±Óœ,'5/^Ìœ÷ÞËʕ+©­­¬Ú‡·Ür ƒ¶;кL¢™îI¿ë±€ Š? ;wîä¶Ûn㣏>¢¬¬ÌV2wÞy'“'OŠšš§Ó)j I’8ïŒóxûí·1M“|[n¹Å.Þ+ð#•h Qøa̞=›I“&pá…òꫯqcÐØØÈ’¥Køý ¿gÆ dggs 'ðØcÑ­[7!(‚( ŽÙš©©á‹•+ùûSOñÖ[oVÛªŸ}û2iÒ$nŒñƺ8±î{ã>逓X°` ׂ(¶ê:MŽÓ€I“˜={6Ï<ó —_~ùaïbÜSOÝvÛm̛7;vйsgîœ÷^N=õT:vì(t”€ ŠÕÕÕÜy睌ùæ›TTTØÏßpà \qÅtéÒ·Û-*eCZ·n'žx"òé§ŸÒœ{w1@‚(¶Š|ÕÖÖrÆg°|ùr233ù׿þÅØ±c[B”úœb±[·nåñÇç駟ÀívÓ©S'~øaÎ9çAQ8 º±±‘Õ«W3k֬}ûrñÅóÿÛ»ïøÏÿã¯³OÎI"'±‚õÕb¯¢U[­Ö*U£vÑ ŠRJ[JµFcÏUµÕšZ£*V©=Š VÓ™gÿþ8=wO¥F%ù<í'÷Œî“s¿Ïu_#22³Ùœå?€œç~õêUZŽhÁöíÛ d„ têÔIn`ê}uôèQêÔ©Cll,¥J•âÛo¿¥`Á‚Yâ}5sæLŠOŸÎ‘#G”á~ú÷ïOûö퉈ˆ€($( ñŽ„F«ÕÊ|À7ß|Ãï¿ÿ® -ѵkWzõêE‘"E0™LòÁ ôêՋ©S§žéÓú÷ïF£‘šÅþœ[±b-ZŽ<ÓHîØ±N—ŠÜ2ÃùúžÏüÁªU«èÑ£‡²LŽ9èÚµ+ÇG¯×Ë (ÄÓzãJJJâСC,X°€3f(˄‡‡S¿~}† Bppp– ŒŸ7ŒU«VѬY3jÖ¬Éwß}‡Ñh”œÅûÖ£Gf̘¡t”ìÛ·>úˆÝ»w+ÃwÕ®]›Påù*øûû˛BHP"#±ÛíŒ7Žšš(®_¿®L ØŽiSÞò>ŊSMgÅ`}òäIêÔ©Ã¥K— b÷î݄……¥«A‘ (AÑ÷}sóæMš7oΖ-[ÐjµÌŸ?Ÿ6mÚdÊ/IIIìÛ·>}úpðàAÀ3­cåʕùâ‹/ ˒_:…E!2UM€Ífãȑ#|ýõ×L˜0AYŠH‘"ÔªU‹¡C‡f¹ÞˆÞóŒ~ý:]»veÕªUèõzfΜI‡ä $AñŽï—£GÒžqcΟ?ÅbáÇ$"""SüÞøžC||<~ø!k×®%&&€œ9sòÑGÑ AòçÏ/QHP"³lj'2~üxbcc•Y"4hÀàÁƒ)Y²$i‚AfŸxË¥[·n̙3—ËEdd$cƌÁ`0ȍP‚¢bǎÔ®]«ÕJåʕٵkWŠú\°ÛíüöÛoLœ8‘I“&ž)÷Bó„2æÓ1ŽjÕJ¡ (DV ‹N§“#Gް|ùr&L˜@rr2… ŠZµjŒÿþû<÷ÜsYêÆ°nÝ:7n @©R¥Øºu+‹%Ëß³jPôý¢4hРƌÀ{ïœÇˆ#Ðét™æœ1þ|ŠL™Â”ÞËïŒó:t lÙ²2F« (DVŽ ,`äȑ\ºtI™Ï·\¹rŒ3† *(µŒ™œ,._ŸLÙ²eùóÏ?±X,ìØ±ƒððð¬ý!šƒ¢÷ý`³Ùxë­·˜;w.ƒÉ“'Ó¥K— ˜nBpíÚ5Ö­[G×®]•ph±XèÔ©#GŽôtî$ ŠBåFrüøqÖ¬YçŸ~Ê­[·ÈŸ??åʕcøðá”*U*Ӈƒøøx:wî̊+0Œ1‚þýûgÙڔ¬œ×ùÚµkÔªU‹Ã‡“3gNÖ­[G… 2lHôó¡C‡1b;vìà?þ<3 0€êÕ«§iz"µ‡B‚¢â®7”o¿ý–þýûKRR|òÉ'T­ZUf'³ÝTŒç2|øpFމËå¢ÿ€þŒ5­V›ån Y%(úÖžíß¿ŸòåËžæ»wï&{öìöÚ§€€pèÐ!"##Ù»w/TšPšš(J”(!áPHPBÉïcßct8\Ÿ|™I“&1nÜ8t:¹råbäȑÊðO… (ÄcÊï7õE”RS‘={vJ–,É AƒšS§NŠ  DFF2wî\4 £GfÀ€YãC4Eßñ4k×®­ *œiÓŠ ù^²d 'NäçŸVØïÖ­;v€bŊšÕj ‰BHPâÉÖ`ìÛ·^œzqâÄ ¥–1 €/Ÿø‚ƍŒF£ÉÐ7(ïq:”Ñ£Gãr¹hݺ5sæÌÁd2eêof¯Q<}ú4UªTáÚµk„††røða²gÏþT¿}¯K\\6l k×®J[âÀÀ@Ú¶mËgŸ}–%g_B‚¢Oa`Œpá[·neâĉüòË/€gžråÊѳgOš6mzÇ]F³mÛ6j×®Óé€X±b¬_¿ž‚ fÚ°˜ƒ¢÷Z͜9“Ÿ}û’œœLÓŠM™;w.Ù²e{j¯¥ïq8q‚‘#G²mÛ6®\¹@¥J•x÷Ýw©]»6‹%C9B‚¢™849r„AƒM||<&“‰Q£Fñú믒¡k“’(Sº4gΜÁd2±mÛ6*Tš9?D3QPôŸ×Ün7Ÿþ9ïœ÷àDûÓO?}*ߋŸÇ”ššÊñãljŒŒdǎ˜ÍfJ—.MTTåʕ“p(„E!2N`Œrå ?þø#3gÎdÛ¶møùùQŸ|y:uêěoŸ™aÏ/%%…Ÿ}û2cÆ Ôj5ïœ÷£FÊt\2KPô^7»ÝÎ+¯ŒÂÿýßÿ¡V«YŸ|9M›6}ê•ïñ€€€0aÂ-Zıcǔ€8tèPš5k–åfQB‚¢™04^Œx‘~ýú±qãF¥-#Àȑ#éÔ©Ù³gG§Óe˜ž÷§M›Fdd$v»öíÛ3{öìL5œ[fŠwšy'W®\lݺ•bŊ=5×êöi6ÿøãŠNÊ'Ÿ|€V«%GŽ|øá‡tëÖM¡…È|ñÚµklߟY³f±aÃÀ3|GùòåéС;wF«Õfˆ› ÷øvíÚE³f͈%<<œõë×S @LqÏèAÑ{ Ÿûî;ZµjERRuëÖ嫯Ÿ"gΜOå5Z³f ãÆc÷îÝØl6Þ|óM:vìH•*U2Ì¯^»Æ ÷ÞãÛo¿åæÍ›ž\.ÀÓf¬G„††¢×ëŸê›¢÷žnÞŒI¥J•8uê[·n套^Êð7ôŒœeîr¹?~Œ2œQóæÍYŸ|ù~Mno¢ÏæÍ›éÒ¥ qqq€çñr˖-ùâ‹/Ȗ-›|x!AQˆ¬ãââØ¹s' ,`éÒ¥Ê ŽB… 4mڔ>}ú`4ŸÚÐå=&›ÍÆ Aƒ˜0a*•Ёò駟fìÑ ^£øê«¯²zõjŸüòK:vìøTœ÷OŸ>ÍèÑ£ÙŒy3.\ lÙ²ôíۗúõë+CõHí¡…xŠ6l³fÍ"99Y©e|ë­·0pyóäÅ`0<ÕáwòäÉôîÝ·ÛM5øöÛo ̐7ûŒÿüóOªT©BLL †Ý»wSŸ|ùÿìøî×jµr&æ ‘œ#ÙŒy3àéäATT•+W–p(„E!ÄœnŠÉÉÉìܹ“… 2þ|e™2eÊЬY3zôèAHHÈSwCõËÞœ{©_¿>qqqüïÿcéÒ¥ÊÔ鿟‘‚¢·l7nÜțoŸIll,%K–díÚµäϟÿ?)ûÛâ”)Søê«¯”Y` zƒßL˖- —€(„E!ÄýÞ`œAÅétòñÇ3mÚ4âââp8Žiӆ!C†ðì³Ï>•ŠÝn7+Vdߟ}hµZ6lØ@­Zµ2ևhŠŸ×|ùòåŽlÙø»=ây<.—‹ëׯ3}út† €F£!$$„>ø€·ß~[¡…âŠ›ššÊîÝ»Yºt)3gÎÄétP²dIj֪ɀþȓ'ÏSqãõîßáp0lØ0F @Ϟ=™2eJ†oñiŠŸåØ¥KæÌ™À„ èÓ§ÏZÎ6l`ÜžqìØ±ƒÔÔT^ýu:uêÄ /Œ 4¡(„E!Ä#ær¹˜4iü1 Øívj×®ÍØ±c SjŸ† »bÅ ÚµkGJJ µk×fíÚµÆ§>$<ÍAÑ[vÉÉÉÔ©S‡;wÀʕ+©]»ö)Ûۃhbb"Û¶m£[·nüþûý᫯ŸÊäɓ –_^!$( !žd`ܳg+V¬`„ Jç—bŊQ³fMúöíKá…Ó‹ÿ*Ð:tˆ–-[rúôi (Àš5k(Y²äSŸÖ è-³£GÒ A.^ŒHDDK—.¥hÑ¢O,$z÷ñÛo¿1zôhŸÿþ{Ξ= @DD‘‘‘4jԈ\¹rý§ïA!„E!²,ߛï—_~ɐ!Cžqã†2Xñ‹/ŸÈšQ£(SŠ &“)MðyR7mïþ¬V+•+WæÐ¡C¬X±‚f͚=µ!âi ŠŸeŽnÝ:7n @©R¥Ø³g2îæã*GßýÛív~ûí7"##Y¿~=ƒ¢E‹2qÒD^|áE ‡B<åÔRBdo„*•d:uêÄï¿ÿNtt4C† !$$„íÛ·S­Z5J—.M—.]8|ø0*•*ÍzOâU*F£‘ƒòÑGžÞéØ$LÜp}÷Ýw•øÁpðàA ƒRΏ+è{۝Nž<™ªU«R€HÖ¯_J¥bðàÁìÙ³‡ƒòâ /fºy¿…È”Ÿ)R£(DÖt{OØÁƒsñâE¬V+EŠaêÔ©T­Z??¿ÿäØ|{薈ˆàÇmÛ~ªj ž–Eo™$&&òÊ+¯°eËæÏŸOûöí{™¹\.nݺÅ̙3ûŒçž{ŽóçÏÓŽiSÂÂÂhÓŠòxÓwœÇ^Á3æÞ˜1chÙ¢…2'ñ“lGùŽ…zïy>œJ•*‘ššJdd${÷îE­V?²rñmKxùòe"##)SŠ uëÖåüùó-Z”)SŠÃʕ+ə3'R!D&¹/H¢âŸB‚·)::šþýûsðàAe€ä   &MšD³fÍ0­–Ñ»œü‘ƍ“@©R¥øé§ŸøÏjÿ‹EﹺÝnºuëÆìÙ³ÑjµL:•®]»>’²ð݆Ãáàʕ+ôíۗ•+W ÓéxöÙg™4iuêÔy,×\!AQ‘a#ðWˆ‰‰aýúõ|ùå—ÊœŒAAAT­V•·º¿E£Fk@:uêoŒñûöí#{öì,[¶Œ—^zé? *O:(zÏñêÕ«4lؐŸþ™9r°lÙ2ªW¯þÐeà[{èr¹øòË/™7oÑÑÑÊ2}ûö¥M›6”/_^¢…âÎaàøñãtïޝŸþYiËš×뉊Š¢uëÖ ÑhY ð~d9NêÖ­ËÖ­[˜2e =zôPjڞTpyRAÑ7À=z”ˆˆÀÓÙhÿþýäȑ㑜·Ëå"%%…Ù³g3`Àìv;jµšÀÀ@Þ}÷]†*áP ŠBñ`ñâŋ¬_¿ž °sçNxñÅi×®­ZµºãzkâĉDFFðÚk¯±xñâ'`žtâŽiÓèÝ»7‡ƒvíÚ1}útL&Ó¿.ÓۛŒ;–Í›7“@£FèÔ©uëÖÅl6KHB‚¢B<\h}:M›6}ìµ_3(z=..Ž&Mš°cÇÖ®]û¯Úú–ÅþÁØÏDz~ýzŽ?@á…éÙ³'͛7§@ä……âŸ\œz•~ýú±dɇ¬† Bdd$‹­VûÐá€]»v,\ž€éÓ§Óœ{÷Çxwâùóç©P¡×®]Ãb±pâĉª-œœ÷òÕ«Wéß¿?‹-<5œùòåcʔ)4hÐ@¡B‚¢âÉò qqqlذÅ‹³fÍe™—^z‰–-[Ò¡C‡Õη³ÇŽiÓèÙ³'-[¶ä«¯ŸÂ`0<–ô8‚¢÷8çϟÏÛo¿Mbb" 6dá…Ý×yÜ>òW_}Åܹs•Î?={õ¢íoðüóÏ˛T!AQñt…Æøøx†ÊܹsIIIÁårЫW/L®\¹ž–ѻܑ#Gx饗žqãyóæåÀJÏ`ßõ4Eßs?~<ïŸû. à³Ï>{ààlµZ™7o}ûö%55•J…ÙlŠOŸ>Œ1âÃžB‚¢B<ñÀ˜À?üÀÒ¥KYŒx±²LµjÕhذ!oœõAAA÷lŒË\Œx‘7ß|“-[¶`2™Xžpá#o·øš‚¢÷˜l6­[·fÕªUšÕjæÎKûöíÿñ˜}Ÿwï^ƏÏÆ¹yó&uëÖ¥cǎ4lؐ€€ ‰B ŠBˆŒ'55•OFbôšQžÝn¥–±M›6|2êòåͧÔ2ÞOøhÕª˖-`ÈС|üÑGÊw”EPôÇõë×)Y²$W®\!88˜;vP¬X±»§ïëv»}ûöѳgOetFCÕªUY°`Ò9E!$( !2$ßàc³Ù”ZÆùóç+ËT¬X‘Fѹsgòäɓnœ»™7ož2?týúõY¶lþþþ6(z÷¿qãFZ¶lIBB5jÔ`á…äɓçŽÇçûÚõëי0ak×®åðáÃ(P€îÝ»óÚk¯Qžpáû.#!„ („È0¡ÑÄÜn7cǎeÔšQ$$$àt:hÒ€ £F",,,M[Fßç’~ýõWŠ/ŽÓé$$$„_~ù…üùó?Ü‡è¿ ŠŸó5O˜0AiØ€IŸýöÛ»žxf¥¹qãï¿ÿ>³gÏ<Ãåʕ‹)SŠÐŽiS ‡B ŠBˆ¬}ÒÖ­[Y±b , 99€Ò¥KS§NÞzë-ž}öÙ;†$￯]»Æë¯¿Î?ü@@@QQQtìØñ_‡ª‡­QlÛ¶-_ý5à™†ÐÛ[ûN`ɒ%̝;—7*ËtîܙvíÚQœzuyÃ!$( !„ÛífΜ9ôïߟÄÄD¥–±R¥JL›6ˆˆ4Í]ÛŸû?€>úˆaÆÝ1`>® G… ˆ‰‰`÷îÝTªTéŽ×étòÕW_ñÎ;”„J¥Âh4Ò«W/FV«•ÚC!„E!„ž“;v°lù2æ~9W™£žX±bÔ«W®]»ž.Ì©T*.\H§N°ÛíÔ¯_ŸÅ‹“-[¶ ]œÛݺu+:tàâŋ”(Q‚5kÖPšP¡tµ‡ä‹/Ÿ`ݺu\¿~ðŒ7Ù±cGš4iò@=Á…B‚¢"Kò JK–,¡wïÞ\¿~]©e,[¶,ãǏ§J•*hµZ¥m J¥âüoç©\©2üñf³™£GR°`Áûoñ~‚¢ïñ­^œZ¢§I“&¬^œ:Ͳ‡ƒÃ‡Ó«W/vïÞ xÚ–/_ž¯¿þšÿýïrÁ……âAâopÛûó^V®XÉ… ¹|ù2à™Ëž^œztìØ‘òåË+ë^¿~Î;³zõj4 3g΀S§N÷÷!úAÑ÷žz÷îÍ€I“1bC‡U–‹g ¬þv5û÷ï _Ÿ|tîܙ֯·ŠhXÑt¡S!$( !Ä¿ ŽÞ@õÿ÷DFF£ŒËÊì9³©_¯>*• •JÅ;ïŒÃäɓèÜ¥3Ó§MÿÇö÷ ŠÞõœN'5jÔয়~ÂÏϏ5kÖP»vm\.ñññ >\ *• ‹ÅÂÔ©SiÕª•„C!„E!„x>ÌÒ¥KYŽhçΝScݺuéÒ¥ ÕªUcݺu4mÚ‡ÃAµjÕX¶l¹sçŸkX»[Pô.ìØ17n̹sç(V¬˗/'<<œU«V1wî\Ö®]«¬Ó¶m[Ú·oO:uäb !$( !ēäö¢££éܹ3§OŸVjsåÊÅ€I“š\¹2¥J•"..ŽÀÀ@vïÞM±bÅîü!z[PôÝdž xùå—(^Œ8{öìa͚5tïÞ]ét£×ëyë­·øôÓOñóó“ÚC!„E!„xZãɓ'Y¹r%‹/æÈ‘#J`|á…øõ×_9rä:Ž1cÆÐ·oßtm!ïV£8lØ0FŒV«¥qãÆäɓ‡+V @•*UèС-ZŽ 888Ýq !„E!„xŠBã/¿üB¿~ýØŸ}ûÛöìٓ)SŠ€Yïö ˜ššJƒ غu+àé@ã+Q¥RQ²dI-Z€ Ù#„…"ÆóçϳbÅ –.]ÊÞœ{Ó,W±bE–,YBÁ‚•ðç]ÿÔ©SŽjՊƒŠY'wîÜtèЁ7ÞxƒˆˆˆtûB ŠB‘CcÌÙzŒÕƒï¿ÿ>Í2}úôa„ Êr¿þú+Øl6e“ÉÄŽiÓh×®]š±…B‚¢Bd¢ÀxåÊ–-[ÆìÙ³9zô(F£‘ÔÔÔtëœöÚkŽk׎FI! !$( !DV ýúõcãÆX,¢££•eêիNJ+0›ÍR{(„ („Y90Âßm¿ûî;4hpÇe„B‚¢BãЧûzëƌC¿~ýÐjå6"Df&5ŠBˆ'êã3|ØpªT­BçN©Q£Ï<óŒŽ 55•'N°aÃ&OžŒÃá`ƌŒúê«ò(Z ŠBñàŒÂn·S»vmvîÜɺuëšW¯žNŸžN§“ž={2sæLfΜI×®]¥p„È„ä+Œ≈ŒŒäÀìÝ»—2eÊH Tåœf†3fPŸ|yºuëFpp0͛7—"³ýÎK¢âq[Œx1¯¿þ:G¥xñâ3 ïuìׯÓ§OçØ±c*TH F ŠBqA"11‘B… ѬY3fΜ)!1“ÊŸ??-ZŽ`üøñr… („÷gÓŠMÔ«WTk*œA $“Úûó^*U¬„ÜR„È\ÔRBˆÇéÛo¿å•W^Á 7HˆÈ: "ÝœIDAT€Ün7ÅËc±XXœzµˆ…âþlÞŒ™6mÚÈãÈLJ¥Ra0(^Œ8k×®•B‚¢BܟS§NQ°`A)ˆLN£Õ`±X8xð †…âþK!dr*T˜L&.\ž …!„E!„x€!œ…B‚¢B!„ („B!$( !„B ŠB!„BHPBd42`· î-„O+E „ÈH\.*• •JuÇ0èv»qãFÅß=­3c¯ë;ͧ,s, !$( !²,·ÛËåbÿþýÜžq#]PÔjµ„††’7o^ŒF#*µ ­F‹Z­VÂefŽÞ@èv»•2ð Ï……Y’Ëå¢mÛ¶œ9sæ—­Zµ*5kÖ€e˖DDDàrºP©3G˜r¹\žqs+þ*µ ³?jµµZ-aQñÈHE!D†áv»±Z­èõúûZ>::š#FP²dI&NœHª-§Ó©l+#s:Äœ‰!88K…€ä$Ox”(„x„€FQ‘¡xÐ×÷ߏ •RSh·ÛIHHàȑ#DGG³eË"##¹pácƌÁét¢Ñh2t`v¹\ìÚµKyí—ý¿PµjUå1»BHPBdy… Æ`0 Óé”åt:)[¶,¯Ÿú*‡âwÞ!))‰qãÆQ @ºuë†Zíy ò(CՃֿÝmùûَ7uêÔáÓO?Å`0PŽhÑûîà"µŽB ŠBˆ,! 0³Ù„N«SB7N‡‹Å‚ÅbaÖ¬YŽiÓ€?ü—ŒLþgò£ÓéÒš{ñí,r·e].—ÒNð^Ðw;Ÿ¯ùnÇ[KŠ›4qŽ-f³™7ß|???4Í÷ëí)Ž Ü.·tzBÜ7i£(„ÈÐ4j5µ­V‹FãùS¯Óc0 ${öìTªT‰¡C‡pãÆ ¶ÿž§Ó©„*oM€ÃáÀn·cµZIµŠ’ššŠÍfÃî°ãr¹”Àå]Þn·c·Ûq8X­Vl6‰I‰üôÓOœ;w›Í†ÃáÀétb·ÛIJNbûöíìÛ·»ÃŽÍnSz.{ÿ÷îÿæÍ›üžíGÎÆœÅjµb·Û•cö†FœA¿¿?þþþèôžÐëݗÍfÃjµzÖu؉‰‰a÷®Ý€€Š€Û¯BHPBdzŸCÄšÕj4 ~~~Y‚š]»6‹€9sæ€ JN§§ÓÉÆiÞŒ9¥J•Âäg"44”Zµj1rÄHââ─èýóó±c1 èõz®_¿Nûöíɘ_|‘Â… Ó°aC~ûí7RSS3f ÙC²óÒK/Q±bEÌ&3 ,Tš7š.^Œ˜ððpBBBšQ£EŠ¡`Á‚DEE‘ššú÷þÝ.~Úþ“cÅétKîܹ1Ìž=›iÓ§‘/o>Š)B•*U aÉ7K”} !Ĝȣg!DŠ ŒÞš7µZÉÏDîܹñ÷÷'..Ž(áЫk׮̟??Ívâã㉎Ž&::š3fðý÷ßSŽhQ4 6» ›Õª,[¢D nÞŒIéÒ¥‰%66–Í›7S§N ,ȶmÛ(R€§OŸÆétÒ¥kŠ—(NÙreQ¡bÞŒytïÞ=ÝùüùçŸ 8\¹rѪU+t:N‡“””e™[·n‘=Gv’““ñóó#..ŽAƒ‘””„ÙdŠJ•*ìÝ»«ÕJ‡7;`ö7ÓžIãtŽ…—Ô( !²DXŽX,˜L&RRRHHHÀåra³Ùøàƒ”X«V-&MšÄš5k˜;w.]ºtA§ÓñçŸÒŒys’’’p:žœž@ß ž}ûv-ZÄŠM›ˆìÓ€óçÏÍàÁƒ9xà˖/ç›oŸÁÏÏ€Þœ{c³Ú<­èÑ£‹-bçΝ̛7ìÙ³0oÞ<ÏŸÿê°c·Û•ýÛív\NÏãpoM¡ÍfcĈìÞ³›éÓ§³qãFrçÎ @·nÝHNJN׋\!$( !²LXôþémè¥Ñhp8;vŒI“&бcG>ÿüs4h@Ù²e©Q£‘‘‘LŸ>€3gÎМ{wÏc[wڀ5yòd (@Μ9 ¡Q£†+¡¬}ûöäʝ›ÐÐÜTšPÎ;pùòenÜžËåÂßߟõë×Ó;2’^x P¹rejÖ¬ ÀéÓ§ÓAßýû¶·ôêÛ¯/-ZŽ gΜ„††òì³ÏòöÛoàp8žt钄D!Ä=É£g!DŠåžâããIJJ 00FƒÓé䨱c$%%a±Xh×®¡¡¡¢Õiq9]R³fM^{í5–.]ʞ={ˆ‹‹Sjœ²gÏN¶ lFlV9säT–ñ3™ !00P™=%<<«ÕJ||S§N 44”Ï?ÿœNJýhBš·Ôî°síÚ5nÞŒ‰ÓéôÔz:ì\ŒxQYÖ; ŒJ¥ºï¶ŠB!AQ‘eø>.ýðÃ﹬ŸŸ5jÖäýÁƒ)X° ‹œ^J¥B«ÕâïïÏÀùý÷ßY»v-çϟ§Eóé¶S€H>ûì3‚‚‚0 8ìŽG:Pµ  6à믿 f͚4lؐ#GŽðóÏ?píÚ5zöêEö&L˜.pÞkÛ÷ ªBq7òèY‘±>Žþê|¯Ÿ‡„„P©R%FŒÁºuëøì³Ï(R€ÁÁÁ ¥­žJ¥Âd2d b̘1,\žâŋ§Ù^Μ9ÆwÐï»ï£ØÖ¿ÙžBHPBd:Þ)ùnNŸs;ß+ ºÝn\n*TxþS¥×ðQ+€·gþA|lß©Ýnwšãö²-ã$ !$( !²4ßph³Ùèß¿?:Ž°°0:vìšLÁw·æt:A“&Nâ·ß~#$$„wz¿C€Àc«Qt»Ýܺu‹É“'sãÆ ^oó:e˔UŠ ŒŸ}zÏÙívsæÌŠL™‚Óé䣏>Âb±HHBHPBo`r¹\$&&2uêTåõ P³fMenãÛkÝn7N§“1cÆ0|øpòæÍKûöí1›Ì¥FÀårnj3ž|ù2ŋ'¢Djµúöév»q8œ={–I“&ðÎ;ïøP3Ù!„tfBd*.—‹äää4!êÕW_åøñãž\.\.Wšàä YÛ·ogäȑ¿Ž«Õª<~\ǚššªÖÔÔTOÍæ¿ÉN§“ÔÔTåµä””ÇzìB ŠB‘ñ‚¢Û•. Ùív^{í5~ÿýwœNgššD‡ÃÁüAýúõ±Ûíø$Å'Ž”¶…ýýßîÓ{.^N‡ã®[„B‚¢BšÕjbbbèÝ»7V«§Ó‰ËåÂétGœzõp¹\h4²gÏ~Ï0v?íŸ^KóoÕýmËÛÑû¿BHPBˆ‡T®\9ªW¯ÀêÕ«éÝ»76› ‡Ã7ïœ÷'Nœ OŸ>„……Ýu[ÞÞÅÞÿN'‡#Ík··ôí•ì]Çéú;šºœ®»¶!ômwé ·.·ÏßåѲâ1“Î,BˆLM¯×óá‡Ò¹sgŽ?Îüùó©U«7fâĉ̟?€^xŠM›²ÿþ;nÇØT*×®]ã… \ºt ›ÝFüȗ/¹sçÆét¢V«ÓŒ¿èmwOtt4111\žpB… a4±Ùlwݟ7/\ä—¿pòÄIœN'ááá”/_žüùó+ûB ŠBñ/‚bpp0ãǏ§U«VÄÇÇÓ¶m[FÅÇ @‘"Eøâ‹/ D§ÓÝq;Þás6nØH—.]žyóŠÒÅh4b2™øì³ÏèØ±£ÞÔjµ§ÖÑéàÜÙs4i҄˜˜˜45F ’Ÿm'œ=±wîÜI«V­žzõjšGιråbŊ”+_V'Z!AQ!”F«%[¶l/^œ±cÇÒµkWÞÿ}Ìf3QQQäșV{ÇÇÀÞÞÉï¿ÿŸ2üLpp0 ÀívóÇpãÆ ºté† ˜5kþþþʺgϞ%ŒX8jµš²eËFjj*'NœàÔ©Sé#;N~üñGêÖ­ @Á‚‰ˆˆ@£ÑpøðaΞ=KµjÕ8wîyòäñ Ú-„…âþ©ðÔ*úùùQ«vm>ùä† ¢ü|Üžq”(Q‚lÙqØéÖwãÆn·³yóf%$6k֌îÝ»c6›q»Ý$%%1kÖ,V¬XÁòåË©S§íÚ·C«Õr+áíÛµ÷‹Jł¯P4¬(&“ §Óɹsçèܹ3W¯^UBªËíâÆŒûî»T¯^#F„J¥âÖ­[ôë׏={öжm[6mڄäD!Äã [„™ÿƒN­ÆÏϏ`‹…f͚Q¿~}úõëÇË/¿LPPFƒñŽmý\.ϔ~;v T©R 2„°°0ž {ް¢a-Z”¡C‡òüóÏМ{wì6;v›³1g9vìà©Å¬T± ä™gž!oÞŒäΝ­6íwv‡ÝÁ¹sç8r䃁wÞy‡ R°`AòçÏÏ3Ï<ÃÀ8vìçΟûWã/ !Ä?‘E!D– ‹&“‰9s0nÜ8êׯOºu ÄÏÏï®CΜ.Î_8O\\ݺu#Ož<)/À?£ÑHdd$»ví`ïÞœ”/_žØØXRRR0›ÍT­Z•àà`eț݆ÑhL³?o'–sçÎ)A5**Š€€4 ày,}óæMT*6›k×®š;T.²B‚¢Bü[†ÿ4y4Žkçy4ìç痩CÉí¡ÍívsàÀåµ²eËb6›ÑëõJ €Z­Æl6S®\9e¹}ûöQŠL.\ž€Ñh$GŽŒ¥WŽ *õ‡Æ9}úŽ/]º„F£I7£L‘"E0 8R›(„ („E­V£Õj•Ž&Þyï5²ËåÂb±(ÿŽ‹‹Sjön¡7oÞTþm±X°Û턆zjúœN'N§:mà»SÛB§ÓIPPþþþ|þùçäϟ÷µwè·???räÈqÇcB ŠBñ€aÑÔîOŸJE‰%”×V­ZEµjÕÒ͐âr¹Xµj•òï²eË¢ÑhÆh4’˜˜È•+W(Q¢„2Ÿ"*î:3Ká…HJJ">>ž|ùò¡7èÓÕ* Æ4c5 !Ä#ý̔"Bd%ސöO!ñ¯€ˆZ­Æ`0Ю];æÏŸÏŠï¿Wfeñþ¿gÏ&NœxïΓ'zœžgžy†üùóãp8xÿý÷IIIÁáp(5Œ.§+Ý>5  xñv8ôïߟ›7oâoöÇl2ãoöÇßìËéâœ÷ÞãòåË2­ŸⱐE!D–r_чF£A¯×Ó³WO6oÞ̕+WhÑŒ9-[¶äù*Ï£×éùù矕^üýý6lƒ£ÑHPPŸ~ú)͛7çäɓ*Tˆþýû“'OÔj5W¯^%%%åï‹ ­VK®Ü¹èÝ»7$..ŽððpºvíJDDqqq=z”å˗£×ëéÒ¥‹E!„E!„øÇ Èj  Š"Gå –&“‰ù °`Á† ž={X¶l˖-K³nxx8£F¢hÑ¢˜ÍfŽZ-&“‰òå˳dɺwïN\\~øáÝC¬ 4Z f“™-Z`·Û•qg͚•nªU«.?h B ŠBˆÌU*ôz=¥J•Â`0P¬X±ôHîÃÃùqã¡¡¡ø==¢5 ق²Q¬X1æÌ™Ã²eËøé§Ÿˆ<ÓéU®\™×_Kp0–  ¥WŽN§Ãb±PùùÊlÞŒ™M›6qìØ1Nž<©ì×ýW– E£Ö Vyw[‚-ŽnݚbáŘ=k6/^Än·ãççGhh(­_—ªWÇßßµFMHöʗ/ÃáÀl6ßµGµBÜ÷gª[žW!sp;sæŒÒ9ãqs8$%%‘€ÝnÇìo& ƒÞpǵœœN'V«•[·n‘’’‚Þ '0 “É„Z­Æåra·ÛINN&))‰””’’“0ùùa2™0™M˜Mft:ÒiÆ;g³wݔ”¬V+v‡·wÚ>ô @¯×+ã)Š€€˜˜HRrÉIÉØÏcmƒ??f&?n·›ääd“Q¡ÂßßÿtÃêãÙhÄE‹IfY ƒRÏïÖNeÆs«ÙâÁ€P(˜ Á`0NJ,¶×$³~,nŒEq‰ µFǃó”v—XI¿ûxÁ“}Á`0ùzÔ6^h#;Æ¢žvl§Ó€¿yófŸúÕ¯²yóf”R¬_¿ž7Œá lÜž‘Ý{öðя|„Ûo¿·Œå-„›/}éK<øàƒüÑý™L†gžy†/~ñ‹ìÞœ›\.ÇÆyíÏŒ–‹.ŒÈÔØ2 †%$\¯Ìo„¢á ÆÓE†Œÿýïgߟ}Œöµ¯edd„o|ã|÷»ßå?øÃCCüøÇ?Ʋ,Þò–·t&ƒ/ùËX–E__Ï=÷øÀ°,‹×œîuAÀÇ?þqzè!î¹ç3 ÃÄÌíF(΁A>19RŠüÇdýúõ\tÑEŒéMo¢ÑhÍfù¥_ú%ŸùÍorèÐ!†‡‡Ù¿?÷Ýw÷ÜsJ)Ч§å®»î"ŸÏ066Æ?üÃ?t„¯™P ƒÁ`8;01ІÇ+_ µ&ŸËó‰O|‚B¡À®]»xþùçÙºu+B<ÏàúWœŠ xê©§xþùçéééá²Ë.CJɆ øèG?J¥Raûöílݺ•©©)sPŒÁ`0 g!Æ¢hèdŠMLLN§;–ŸîßX–Å<À·¿ým”Rôöö2==MÑ®CJ.»ôR.Ÿøbîœ÷^nžñî»ï>~åW~…ááaŽÖÔëuîœ÷^î¿ÿ~2™ ù|žœ{÷šó© ƒÁ`0BÑp¶R«×øµ_û5Þüæ7óž÷Œˆbƒ “É`Yÿ÷Ï{ßû^þöoÿ–믿ž|!σ?xïÿûë”J%~åmoãÃúÿúíå¹çžãÿøI$xŸÇwÞÉןö5>÷ÙÏrÞêÕ þìÏÿŒœ{÷šF0 ƒÁEÃÙH6›å±Çcxxž#ÛçF÷÷÷#„à‰'ž n¿ývr¹år™r¹ q\a"‘ࢠ/Äu]ŸùÍo"„`Ù²e!ƒ§Ÿ~šÞÞ^nžñÆÎgoy~ Ÿïw~6qŠƒÁ`0œ˜EB€Üxãüû¿ÿ;wß}7ßûÞ÷øøÇ?Ί+:‰+6lÀ²,Ÿò•¯ð̳Ïð§ú§Ü}÷Ýh­ÙôÜs4 „ pÙe—ñ…/|µkגÍf£Î&%\pûöíãßþíßøáÈïÿþïóÈ#Ðh4ØŒy3Ÿï‘h0 ÃY‚õáøÃæ1,>ŽÖ³4}ßÇ÷}ZžG­Vã[ßúïÿûOêZB.Ÿøb€”ÜsÏ=|ç;ß¡Ùlò¡}ˆk®¹Û¶9íùxžÇœ_¿—{d2É»Þõ. …_ûÚמñŠ›èíéÁqšÍ&{÷îå­o}+6l@eY,_Ÿœr¹ÌßýÝßqß}÷±|ùrþðCÈþýû¹ÿþû¹å–[Èd2Ё ƒa†!wÞy'?û³?K2™$™Jâ8®ëbYÖK>ÄÁpæڔL_”(¥ð<Ïóš×ëÔj5ʕ ãccŒûÝïfϞ='-<ۃ·V«111Áʕ+;ÿ×ýûz£Ny®ÌÐÐPçýsssär9€”Çœv›©©)R©étºó³s³ò…šcš‰Ä`0­V‹õë×óùÏžB¡@±T$J“Édp]Û¶¹NÎ^LŒ¢¡#Ìڂ.“ÉeÕënéTšt*œà÷…BáEa÷Ïíß÷ööuÅB±óƒÁ`0 g#ë Çt/×5^Ìgk¢Á`0 F( ƒÁ`0ŒP4 ƒÁ`0¡h0 ƒÁ`0BÑ`0 ƒÁ`„¢Á`0 ƒÁEƒÁ`0 ƒÁEƒÁ`0 ƒŠƒÁ`0 # ƒÁ`0 F( ƒÁ`0ŒP4 ƒÁ`0¡h0 ƒÁ`0BÑ`0 ƒÁ`„¢Á`0 ƒÁEƒÁ`0 ƒŠƒÁ`0 # ƒÁ`0 F( ƒÁ`0ŒP4 ƒÁ`0ŒP4 ƒÁ`0¡h0 ƒÁ`0BÑ`0 ƒÁ`„¢Á`0 ƒÁEƒÁ`0 †³­µŠƒÁ`0 F܍✍¶éBƒÁ`0–Š(l‹9­5AÍf“ç7of×Νl}æöîØÅØØ!ÆÇ&š6ëÌÔjXBM§(å ŠV¬XÉÈè Vœ¿†+®ºŠááaòù<®ëbYRʎXìF( ƒÁ`0œ¥"Q)E¥R¡\.óŸßÿ>}ï~è!Ö ö³ºPà’Bž× öÒ»v5éT á8ˆda ЀÔT*“Õ:ûœ?ÿúי©VYñÅ\wó«¹üªWÐ×ÛK&“Á²¬c ÕsV(.Ň`0 ƒaq D!õzM›6ñÕOý5Ï<ô×õõòŠóVò‡?ÿfÂd-$¡e°Ñ¶ËBH œøoÛBØ6é’ň“@8!ޝp À'¶l柿þu>ýœ›ÞøFn|Íkxå+_‰mÛH);÷KÇÊh¿”Æ8ƒ9ÏÝæs#Î ƒÁ`8öZ©µf˶­|îÏÿœÔÎ]Œ©¯—÷ÜtéLl›šÒˆ@Œ^/l ZE2H„@ BjHGxÒ²žôâK¹ì²Ëiynyžo}úÓÜÿÀŒóŽ;èí댑Kº-—¬P<ÒÇߍRÊÅÓØñõoƒÁ`0 µÉw¿ñ-?~ˆ·\r +{zі…†öÚ) m/ó‚%UÌÿ­5Çâ·iAôÿZ“H'¹îŠ«X1<ÌÇ¿üežŒü2~ê†qÛ¶;Î%+»…‰Ö­5¡ c aËâi@J¹ ³µ6 ƒÁ0OËkñÅÿçOøÂ­·RÊäЋÄH·`‰ø:ŠÑ¢Ú–59/$… ¶2F‚RBJ42z¯Ž£Ëؒ+Vpë5Wóo|“ÕkÎghh×uI&“ŽØ×íŽPìv+·ÿ@$ µÖ(¥PZž·*¡ø2 @ :±ýDz,ŽÖG‰Ç—ãò^ÜéøIÚ²3ÖÛ¯aQö‡nCÀO:¶µÖùʰøûÄbŸçTšØ51Ɏéi6fršÎwR`ÙQ/"¶,jސ‘ø‹~h K!Ð€èØŒšelNìšN:ÆG­Á’6åJ…™™òùÿ¹¿c×®œžžX»n7ß|3ïÿ§`à%/Ý ÉØØõWɃ?øOž}æ)³‰X, )×q¹íöÛ¹õÖ[yó›EÏ÷žçË_æ«_ù <ò0Ji#Q¯èâ=ïùoŒþ o`íÚu‹V4¶³œC2 üŏæ·m—«VžG ,Ú%£…è®XDŽŽÅ¢ˆ•Ÿ vT/†"֘±i™q€E­2Ëû_ã–[o¥ÙlR.—±, Çu–Lœâ‹b»£A€ÒŠÀ˜™™áß¿ïí“üô…I~ûëH§×af„—ŸV3à™Ïs÷Ç~í¿ð^n»ýg)Kضµ—ÒQ‡=ŃîÇ=ħîú,‰žeŒûî"WìÃ(ÅÅŽÀì仞šknº…ÏÝõI®œö\Ç=iqО„ÿúÓwñµþ.¯ŒùvÞòßßÈÆL‹‡0 Ù¹ùIŸú¯òÔÓÏrÇÛÿ +W®|I×RJ±sçNÞ÷?þ€ÁUòš·ÿ¿ú­Ds~â™#ŽŠ^-óè÷ÿ•/Ÿý]üÏßÿ^{Ë-$‰Eû}?àª\ŽÿqÝÕÜóì3ªÌ°zp˜áŸ>2€ã$:nd –ƒ]1‰bþG)-ތ¬Œ¢]úFRàûµz@­Ræ»=Ì·~ø ¿ÿö·óÀîÝLNN’ËåH&“€Ói޳4Œ®v·ÕèÄ"†AH|ãßàKŸü ŸøW°fY6VÕf8ž ›+/,ñÁ^‡?¹÷3Kò‹¿ø+QÃÙ6J©—eÀÝñŸ‹k_÷^󖷣Th,G‹ ”ú(^3–“àãÿï'ø‹?`ýúõ'ݖZk8È_üõßðîßý–¯^·(­ç:–e±öâ+Y±š¿úÈàï|GÇ=v2ÌÌÎòÆ7Ÿ‘7Üñ.Ýø*7aBÛ!™\žWœþ-¬¹øJŸü÷048ÈÆ­PTJ¡ C#ünO/ŸyüqŸ¶e?uÞ*®=o”åãخÆrleEž9KÄÖAæã…¡†„aˆ B¥Ø³?÷=õ$ß{ôq^{ýuÜõÀÓ{öâmÛFµZ¥Ùlâû~ôž—a>cB±m5h[©|ßÇó<Êå2[~ü/ŒçkÙ°º@Ë3¢átfЬ^–篩sÿîåÀu7°lùòN| O]z†|á _ࢫo▟Dâ YŽÖXRЛKI8Žã6¢„0(&+-üPbÑì-ŽŽ\u ["… é¿ø>¯ŽÆµ$–%hùÑѓqɧ]æê³5ušâ>E}õM?Cun’OÝu7ŸüË?;é뎌ïx÷»ù}’¡e+ÐZòû*$Iºv§EV+ÒPiø”›~äÖ<ş;\Láڒ‰r“Z+XÒs[ìe#[èá]¿ýîÿöWyõ«w°~ýú“ŸÖŸÿÅ_qÕÍ·³ñ§n9áÜӞ'r)‡žL¢ãÑ:jãV ˜«{4ü0vï‰5FÛÙš [*ªŸ8w Ÿ$“Ž CÍá¹^ –üzgÛ6+V¯gÇèŸù/ßa͚5ôôô,ºï¡”ŠD™))fóüϟy=R…üç÷öSH'ɧҞ‰ʲñ, ËIàº6BZø:$Pš„ˆœÎ~R|ÍÎ2]¯128ÌOoÜÈoÿoÇÎåðTÈÓ{÷âû>Íf“V«…ïûKF$v„â‘; #kb£ÑÀ©ïç† #xŸ2"ñ ‰Å Ô\µŠÈ6íbvnŽþ ’=•劔Rüû÷îãUozZ‡'w¶%Y7˜cEvAE| é재±g²ÆlÝc1ž)µ!4=ék†²ži°oºþ¢šábŠáb’™ªÏÞ©ÁÊþ ëG l:0K¹î£Nc˜¯Õä‚K_Éÿ÷鏜Ž>*cdt¡zyÄԆÑ"ù䂄:¥¡†©J‹=“ vŽ—ãö9uŸ{Ɋ"Ŕ÷MRkçÌÆshô­V KÔq,!>‚вH&“29zsÖæ Ü64H±P ™Ë!,ߖ„^ -m²£Ú–Ä¥”ìÛq=w&çX$zŸG«Õ¢R£TXMˆ‰H:c(ä4›5jµ­V«SÐóÈ,õŸ”§Ÿ~š7þÆyh}rïÁ™ÓU €]‹ÑÞ4ëGòh¥™‹’R:®i*•FÆÿެqtD”,)dìj a×w<ò5m‹žRóQ›Rˆ8fY,ž†×Åj^ûuí+ö¥X;”gºÚ"TKÒ¹ÇöuÚ!-VüÆPiÖ/Ë3RLóèŽIB Í¡™~ ™(7;Ÿ§utÝ÷jÅ%:÷ÿ^Ä.=ÿß±Ÿ÷‰&Ïbï{wïyɇ–׌7%/oß?]g²ÒB °,A_Öež”&åZš­ÓôÂØÒš¬®SB=IKÑÚÕ0âgÛîÛWH:å†×iÃùæÛGñŸvèn)E\­`~Á »Ú·ýù×èîÓ/g&±Ö˲Q¡êü|²âr|œt®ØÉ=™•aŒÜ`¢ì¡58¶`€”bíPŽlÂæ?·Nâ‡a絝ç·Ÿ”óOű%W¬êa|®ÉŸÉÚKc÷ûñx9µ²˜v)€Ýèږ€/›`ŠêÑ ztܧæçŽv¿ZØïÚ¯kî|å•hîÑ]s•h÷±Nߍçª#¿G×q¬ùnŸŸøÐöËú†–1]®Q­Tï:©»žD;Q„Öh)±‡‘L–喍Žm„m!laÇö2["€…plD"Å(Z6ڒ %JJÑÙ µç‡«KE,ÚÝ"£-}ßÇ÷"3j UôÀL%œ3·ó#JÀRRÐh4i6›X–…mÛq]ÐS×8-¯…eفwRï;4[gçx@il!©4|®XÕÃ`1ÅæƒeJ™Ž©Ž<öO×¹òŒÆæšl>0Gš4«r¬ìOc[‚‰²ÇŠý³+‚¡R’õ#’ŽhŠk-6ï¯0ט¿ÏތËêÁ<ýy—PivŽWÙ5^#T ז Ӝ?cûx[JV dq-Áþé:[VPÀ¥£VôŠž`žÀ@>ÅCÛ§Öå.ŠÈ¥ü d¶îóè®i€€=iúsIÖ åè˧xdÇ$™„M_.AÝ •Èÿ'¥ 7ã²f(G!å <°ÌX¹‰×(íͺ\:Zb²ÒdŠîsþ`Ž”+/7Ùz°J¥éœøÅ@ ‚ÀéVš®Åûåäðl“m‡Ë€@JÈ'l†KiÛ"áH^Àho†UýYª-Ÿ'vOt,®\Ջ„l:0GÝ ±-ÁÅËKôç$I­phŠÎ–ÃU”ŠŒ#ÅŽC:á26×|Öå.Š™,7(7}Ö äÈ¥öNÕÙ;Y¥Ò :%ª†‹IÎ̑IXT>›V˜ª6Ñ:ñلÆåzs.šŽ¶,s0¶R !Xޓfe†RÚ%ԚjÓ癜³Ì5ü—­4Ց×|)ŸÆqËBpÒæƒñ¹[•ñƒHìñŠ5œŒô€*&84Ó$ԚBÚeÃHžbÖÅ’JÓãéœsÌÔ=s .É#… ˜v¹f]??Þ>I¥á‘Mž\¶¢@.íbËȳñìþ2csc†}ŽçεÃ9ŽÖš®S̹,ïMÑ B¶®tŸ¡ÖײX7œcyo ­‡fœm0Yiv®Ù“M°ª/Ã`!IÓ™¬ŽØ9^£îEýGÃÅ4 çI%$µŠbÛX™C3õN›3ç)€[Rol;\eÿL£ÓòI.ɓK:ӏíã&*­“nSiYMØ"7“", D%m¢D×@h¥ADu¡¥¶Ða'¬HÐq Â÷Ñ2 ?ÒZGe¥@¢ížF-ÒŠ6£K܌¶Ðõ¬ç]ÏŸïãûŸ1#že‚1 ‚ ƒNêœÒg>".Vm6„Š(ŠtŽëJ:’¡b’RàЗMГMPiJsÅy%–•Ò€] dͶ± ÓUÞœËÆÕœ€v§;f“hÁÃ;ŠPZ“NØ\º²D.‰cG.•LÂÁµ›T¢àmW2XLbّžÈ%l4‚„cÑô»&«ô䀓Q€>íp,4šRÆeÝpŽŽkÇ;‹lÒÁ Ï,“O;8±é±˜vI96HA6é0PH2UmÒ¶¿ ä\Ÿ²D>-f ž2YbÇá*ϘCI[0XH‘Mڌ*M!㠀Žk“vmîß4†-—VR‰%®uœ”cqÞ@?ԔëÑŠ!åZ $êóßۖ’|/±K„¹h€ÀšÁ,Žh¡É$l —ƒ³MÊ ¿³ çS;Ç£vË¥ I6¬KæI',€€\ [ žÞ7 @ÎåŠózÈ$-,!É¥\ —ÿ؉c ”Òd–”ÌÔ<ÊME)íðŠÕ=ä“.RFón&i#-A¹1E+PçôZ©Û–W=ßéq]ÄN À"Ah4r>§¥cŠë=ñÅ¡#>υ߅åq”îø×ÛŸvSTûìRŠž øÀ°ã˜Š³ÁÄݗKÄ."A>å°z(Ú¡WQ‡‘;1!%~(ÙŽo†ñŠG)㲪?‡”ððö)ŠkX=˜¥å+fj«²€Oïfûá*ù”͆åEz².I׊鬈¬AåºÇÛŠHº×®íãÂeöM5ñÂ[A )‡§÷Îph¶Åe+ ¬èË2XL°oºÎ³{g¹hy¡bЇ+˜©“u-–•R€]‹Í‡fÙr ÂÃy.É3\L²s¢Êö±*£œÒ ›cÌ6СBÊHµÝJ Ûâºu$ìȝºg¢F)í²n$φÑŠ#kVäj‹ºg÷ϲgKõ#yÖå)¥Éž6­0\J]›+Î+qÅy¥ØJMáS•&ì˜"Ôª]KŠ.fØRtāËyýYü0ä‡['9<çqÕªƒ¹$Ë{R<0ˆú€Ø]î`!®-,ŠyfÏ4{§ê¬̲~€ÀH1Ésû£v|Åê^Ò®ÅáéÏìŸeÍ`ŽóslÉóøžŠ™£œY&«M~Žu?PÜp᎔,ïI±g¢A1 ”M°íðÏì#áØl\]"eKz2‡çÂ%œG±o0­VØÙüÙVŽA(&©·~°eNJÆro>É`Þåàl‹GwMrõùýÌÖ¿\Êå’Ñ"íšfž`ž”bŠæñȎY¥žbe…k‡6(³f0OOÖeËÁ9vWY֛åâåyìå‚Ý“5†ò)zsIfj-Ý1*Ö fY3˜#—²©µÖ æ(€"kø·M …àšµ}ä’6Ù€C³Ò<·s ºK5Yb8ñÑ}í£Wt,ø:œRÎØnÞn×^B¢¥œ·€wÜ^êØGšà‚0èd>›¢gmKo[ÈÛñQBgš•ýYVôe;‹>Æf웪G±‰1MO±íp™m‡«àâå€$J~™ªcÉÈCŒ°eÜ B6,£4žm±fPáØóÖâBÚ¥ÒðÙ7U§Ò ›m²¬'Íp)Mbÿ\{Hä>]7”c¢Òâ‘SxŠoXڃvšÆV˜Žq3Pø:gf]­aü,+Šó<0Ýà_?@Òµi)4AØ~€éLÆÃ¹(Æf›ø¡f¢ÒâŸ;€ëHZ"›ˆª8RõLµŽÂZ†KјÜ5^A£©¶Bü@‘Mؑ0óКáž4BZšª²g²†ÒðäžY’Žd¶æ“p,‹)@³s¬ÂŸ©:BžbÇÌÔ<Š)‡Žk*ÅîÉU/dÇX…uÃYR®M1í ŽŠŒi—õË ì›¬±g¢ÎŽÃÕšÿêØE, 7çrÁpÉJƒGwL„šÖRµF¿X‹µè:Œ¢Ýî¢]l[!ޜ·Z2¶-ê®: íÂãtâÑ;GÿÅEaÉùpVíX#úsI~j}_Ô¹m‰@“MZwAt¯>AšÐZqP; ]ǓF{!iNJYRЗs.€é/D®®¶UK ì*#¡pl«Yo>ŠclùӕŽ#ixŠJÝ'íZ”2Îã /.µÓ.¹ÍMbI‰D <»o–ã5,Ž =™WŸßú‘{&ël>8GÓ™­{ÌÖ=òI‡ £%6ŒB­á³ùP™]5Ô9²ØKI'd£á©Na.e3RL±Œ7MÒ±p,Ù٘uÑöÚ¥ã…=“ŽXٗa $“t°:ƒO³µ{2 Ò®Ó±­ÈàX/ É$† I&+-‚2‰èÕfg“ûŠkd“RÚ%—ŽñEӏÐšœ]¯íÉ`[Ñ|ñŠU=qLàü<âÚå3Õ}¹«²¬ˆ¬ã»Æª<·¿LC)vOT*$É¥\.-* ]cU¶ŽUð‚sÔØíng!ŠÈ¬9F’X»!çåb,Z p#÷µè.ñÖöâ‰È)Ϋ¢œð™-Ì~Ï×V·¥Ó”çÁ|ÏöΓXМÉÞºéÀ;Ç«Gã%YhðTZãwMbQÖgTmÏdmAVš¯4¡Öžkñœg³¬'Mڍ’CŠ—W¬é£Ò ™¬FÅBA¥éshŠ_£-ü­…¥~ô}þx¢¢ŠuÃ9ÎÈqp¶ÁÓ{g ”fãêÞ^ãHZ±µRJ‰ãXÑR±ˆ(6M1&qßKÒZjZ~,â<˜©UX7”¥”KЛM,xݧ€Ž³=»ûÔã{f9<Û€q(¥]úóIFzÒ$‹ï??Yc_€°kƒ¬»- ] ‚*&暑µ кŠR‘Ȭµ~ŒmšábÞ\‚lÒf°bý²<Ù€Í[¢x¶7OЛw)Š]z³.ŌËå+KH`ÓÁ2’¥úԞדŽÕ‰œ©5ñÅêÁ,W¬,„šMf©·BÖ/+ГuQÇËJi®[ÛG­•æš­yôå“\ެpÌlTK Fz¢Zš.+uÍUYvŒW)7‚Î…–5Üm!åNØ4œD”©lÇމöšUHÚ€6õV0Ÿ¯£Jí~ØÎ’®¶ª­€ŸŸ`𘢐v(e3ëF 4|ÍÎñ SUûŸcž”¢”qÉ&¢XèKÏëÁW°õðÜ˖µ8VÊ®˜Bdœž‰Œ¶[‹–ÇvŒO;Y%ú;žaÚB³ûžçxqÓbékû…ñ©,¹ròÖÝ1ë !N zèЋˇˆŽþï^,ÚG3jݵw8• š£ ìöâŒt=_~ál²úY∵@|ußq­Æß ¶ª¢c—]1ãPm„Z3\H’IØLTšT›!¹ëFò Sôd\Š«-j̀|Ê¡Ö Øz8 @_ї&Tšéº÷ð8êp~ãH6aӗMà+ÅŸ©ÛƪŒ–ÒGLJ ß'Žñ)˜‹ï%aIús ŠªG’M:H ÓUïž‹áRƉ“YÚF€k‘LD?‡G”œq,Ñ)”NØqòB$ÂÓI›ÞŒ‹%%»'jެ C–õd(ŠÝÎ"~â}tCD™«Ñ}L×Zì¯RH¹ôd]šAH£PL;ôfŽâD§Ž¹·FJiJ×€ƒù$S5Ã3Múó ÎȰŒ'C6ÙNÚ:¹Ò3‹Â‚h ˊb–¥dY1E!åâйF;ºŒ”Æ’‚éj‹çVp-É#ùN«Ð5‡tr€þ|ˊ>žÛ?‡kKJ÷˜c å:S.BÏ6ÔÒtm'¹DBŸÚ š6‹Q8D–4ŊÞ4œ¹$sõÛW©6†KQœv–( £}Yz³ãsMÆË-üPcKÁŸ©:3uǒ,ïIÓòCš^@)íRʺbË¡ Åtƒ¡BŠ‹W”(€ìH\§lÒ /yvß…T”ݗOPʺñyÅçp~èZÿã?퓜õ‘º ãšÏ}igNwØ²àŒ¿.qxN%³K¬¡­& ©Aœe¯ÂŸ ádÐÊ'œÛƒ·ç{„“O£¥ƒÝsÉ ßŠjÎÑxü/Bc/$u鄳{h>÷y”_=5‚Në(ŸÁJ#3ËQµœèÀ;b±ËršçOÕY<;œîõ7Šå¹p$G>åðšK™« $‹çöÍ1]õÈ¥l6®éc¶æ1Yi⇊ŒuÝنG ¢žÇW®éeÕ@;+û³”ëß{vìEß_*Â8ê‚á<ù${'ë(­q,‹œi²I;*­Ç Z–ˆÄ{üŸó‡òôå“<ºsúšŠ;4×äðLƒ‘ž4¯Z×OµàØ’LÒŠ\÷Ø|ž²À¢uîXà‚‘<ç d;“¯kIÒ ›–²{"ªïVmFB-—ržá‚~|}yw¡+RÁùƒQrÓø\ƒ±r“B:ZžË Pœô{œ­{˜®±Œ7Ãåçõ2PHQÊ8ôæ’<¹kŠéª‡cYlX^ tØ5^¥d6BÊÍèóKrÕê^Èþ©Z ²n”õ\ó–®Ûyu–e=éx}dÑ8ÞvžL¥á£!J\‚\**u“Mºôæ§Ž&ˆœÅŽËÕç÷ñ£íSi±”IpùŠ"ùŽK_>zŸc˅^ 9—¡R’Z3ੜ3L–[µ`[’Õý6žßǺ¡ãå&»'ª —RŒ”ÒÜpá Rôç“ØRrx®Aà Ù=QãüÁë†óô瓠¡”Êuퟮ3[÷(×}‹I®¿ Ÿ©r‹tÊf0Ÿdl®É¡Ù®-¹|e ײ88Sc¶îSŠ-êՖOÓ)f\}~/¡Òì¯Ò R®…0WkqN§ ÆÂ°ªÐiðΙÍ]Û0!»Üíµ©]N‡®Ä•8»PF™Ó²“à"@.}«í1“YÎt#ËôéWþVn!ìø” »° wh#õÇÿš`üaD"‹Õw!¢6ÑÉ v«g-Z… ¬S&^µÈÌJR—ý:š€Æc†Æ;폧£ϒöRzŸ?îëB¥!Ö:²Ðü`Ëë‡ó ’2.žòäîÌ4Íî‰ ÇbŽ'Íòž4¶%iù!Ïì›áð\“PÁŸ©:®m±f ÃòÞtœˆPçùýeš~@±:5ÂÚ%{ºŸg»Ä&r ­èːN8H!xrï,Ïí›å²•%zsIz²IvŒU(e]z³ rI l¯p•‹ß•îP±õ©ý™ZkÞ9͚Z‹59zr ŽÖì/³ýpÏãÚ]q!i}d–Šî†^*(¥ •"aKŽŒ Q+T»'ªìŸ¬3^ŽÆÚD¹Å¶±2+zÒ £ìÒÝcU–Å¥hš~È{fÂÈ:œ~Yވ3Q§¢˜OÑþÜ®:²ñÏJÍwfݶbÆí燊GvÎÐôËK)ÎëÏÐðBvŽUØ1^#TšÙZ‹GwMsáHže=©8–U°s¬Â3ûgQfj-žÜ=Íòž +ú3âùí8M±ÄÜYí"Õ®#q‰R?ԝSYÎ6P±ï‰Ý3èP3PL²f(Ïl­e÷€é‰­e^šÙ7Å.3.™„Åö± iW2XL±z0ÇD¹Éî±*+û³”².–øaÔÞI×¢'çâڒcs4Œp>|A@ 3uŸZ3 ‰Æù¡¹&?Þ:Éå«J”2 €€†°u"»JkŠª-žØ=Åê<¥L! é<µ{–ýÓuB¥ydç$k2¬̱Œ?CšB¶UØ1VE“ÕOìžae_†Þ\’ÁbÐ왬²c¬FÓØ;©p­i–÷ŠíM#… КçF1®ç¬Û¹Kž ¬(Ž02eGvhau\>BZ+b[0JKħ¬h€-æ…d\ÿ2®°Mw lÝç‚EQÏ/FgÎ7áXósØ¥UšêajOލ®@V“ºì¿b¥Š$Öý,áÌæyuÒ)®g6Sùþ€_GûÕyWŽò#SƒÖq…d|®ÉtÕ#áH¶Eµåãªs²A ¢ pûXGJŽE˓gšýÛÇ*잚’IÚ¡Šé‡ñYÓÑœn«²g²Ž Vb Ñ?=º0ԝךkðÝg‘t¢{izŠF+`jÓ)ÇÆ M?ÄQaè¶+içX•ƒ3 2®EµÐðCžÛ?˖ƒe¥:ãªál>PfÇX•€c*š{~ǒ©Ãs-þéÑýQLgšM­ðG÷ÐòÃ%ã™üÏ­ N7螌BÇ ¶~ӊçöͱõP…LŠÜð •fëáJ§æê>í˜Ä’’LÂÆóCŒ0ʒCÖyàùq€xqâÈsfÙršÜ9ù`ºÚâߞ>±HÔ:ZøŸØ=ͳû%)Ç¢„ŽEšHX"+7™ªz€ ǎ2u[¡Š³w5J ¶UÙ9Q#åFõ[~ÐÉÊ^Jxbûá »'jGy­ŽŠDYô£žÚ xhç®%±-IÃQZóÔÞÙx EÂýáSdDUæQÈÆ#;§IØ×±©4¢`6œCiÄ¥zâ霳lÚ_ÆÁÏ\U@ø·gƱÃÑø¬¶øþæq² K *-Ÿ ˆ6:QÿÔl«²gªNÆuâäš/;–ìJ3*Ÿåp…ŽëPó|‚0ÊìñÆißTƒ3 l+²º6ý0žÏÚ'L©hŸ›¬‘°ePš@…GYhÞÂûÒ* ŸJ3è(QVfÃkuÜ!º‡¢sºFµ5ÿŸh8ú{‡JSo4:ÉGÏłçÕ®¶àÿÄOÖ„A€eY ާ;݋Œ÷"Šw÷—@iüV@Ý ¢RqÁ‘ø¡Æ š~ï%>ãîÏ=²­ºÛ¡;ÛŒ»/ùGµŸè:Å#ºŸ†]ÇЉ£ú@jŒà…_sº Ã)å)ûü㍜cœ®Ý©Ûm·àGŽMË£¶ócÝ 4~ [ó}ã((æ?Á„Íö<° íãíKËç Z1ÇÌÏ! _µ#â:}¯ýý¢þ£š·¢Mà‘í®ttκhê^Øùœ£ûfô Ê]sÕRDkMÔj5 …Âñ¿§%ºZKCçèÇvÜ¡˜·$""+cœ-,—Äé*±cYñà”±q Ñë$œ:Ï墊gÄÅ©‘Ùå)Qõq‚éç£Jéqùƒ`ì‚ñDžV!ÖQ+eäz¶ Ë ¬ƒ°–Kâ‚_%±òP!: p/ÅʍP›Û†ª•Ä.®"¿€Lõ €ì[‹LßAå{!¬4Vª0-+ۏ°‹ª±ÇÇÆ Оž‰–ee. }Ü$¡N]+Ž÷šùŒÄŸä{µ¯Ó} ‚Ž+ûŒè÷ÿ38…qº<4Ñ}îÚµ‹žž²Ù,®ë.š…ŠýìNt»/ï3>þµÛýåø÷7ÿš3ùèÛ}vjj €Si’©$–ŽÎ`Ÿ'nÛžêCwbÁËý<»ç˜ºÇù3ÛÅqúlj犜FÄ59ÏXråidÛ¶müÓ?ýïxÇ;Èår$‰ÜÔD‡²ˆÎé,ZŽ këNNŠè² ¶ pGzPvd$Ýõ7ÛŸç8”€óç@Dš<ÛnÈÊ-‹&® †nMÑ$:ƒêr ëžyۓžòqF_‹»üjt«JíÑOQþÎ;iíŸ+7‚=ü*„›ŸïRâ|„Êw‹Ú£w¢ýVf™%œx‚úSŸvݳ{šþ࣓O-ª.òÁ~ÑÑQ®¹æ>ñ‰Oðï|‡‰‰‰³&Þ­{gþr¿æd¬!Gv¯#N^ügœ9pðÐAnºé&–-[Æûßÿ~îœ÷^ž|òIšÍæ"‹göw%Tž’לyá­ùÌg>ÃàÀ W_}5w~òNî»ï>ÛBèèŒæšŠbœœ² ¿ÄŸã²no¢Xp„ŸóâRH[%ÏѬç3žµÃ:Ê€{҂F‡ØœëvUŸF8IìÁ«¢Œ(¥°û6Œ=ܙ]t~ݚ"œÙ†öàfÁN£Ãº1 ð…ªîFÓnš÷Ȋcº©Ž7a8ŽC.—ã™gžáw÷wÉf³Œímoã’K.aýúõ\}õÕæ$žsˆÀ(•Ju—yë”åëºvç` ­Ù·ožçñÃþýèG¬^œš×ŸöµlÜž‘›oŸ¹«sËž†]÷¢Éü9Ííßϛ cƒT».btùÌf9ÿš®×v &#O'ª>ßY ™è!ôf‰œ Èd/öÀ•„³ÛQµý/JtÊD€…HH®ÿ%@#,'Ê®NÁr»>ǛÞô&Œ2Xz(­ùØÇ>ÆÀàà¡øÔSOÍo$‚€ýû÷s×]wq×]wqíµ×òõ¯Ý<Œ%Jš÷Þ{/<òè±ceű-žm_»–®ïûÔëu~øa’É$ét×uq.¶eG!OñúübB&&&ŽÚØìرƒOúÓìÞœ›nžaáúÜ]&§Ëå Ä%n¢R7 ãcãÆØœÜ>ÃOtªm‹ù毵Ô9˄¢ ˜~­ìÂ*œe×nÞÒA H®Î赚Ú8õ'>» o~S~ ”",ï£ñħÐ~m~s¡BtPFÖ/—í¿ÓmYp"øiê(ApÛm·±nÝZ …©TªgèyFƒ‰‰ ž|â >òяâ{óå{,Ëâø{÷îÅ÷}„d³Y6lØÀ;ßùN^ýêWã:ÎY[€õHk²9¥ç$ŸŸR ú„‚œ{÷òðÃ333oD2™ oûÛ¹õÖ[¹öÚk±,ë¬=ƜÚôґBðë¿þë\ré¥óâQ)îºë.~ô£uþ/•J±jÕ*>ò‘på•W244tֆÛhœp7oúÄÉaIɯŸí—¹ìòË_plWØÅ‰b­f‹¿ýìgù¹Ÿû9òù<¥R‰T*E*•ŠcW,ô‘BtþŸG·ïû|ûÛ߯qlÛæšk®á­o}+¯{ÝëÈf³‘DD.g-¢27²ã&¶c« ¬. (:Q†RÆ'²tîIÏØ%Eû?RD%x8—Žð;+vºÕýøÃYþJœÑëf·£k‡±z.ÂyÒNúuTõ ²·p"3 áÜôÀ¬t?ÂÍ£*{qVü îÊiíøáÄcG®šÇ™ˆâ ;iƒp£Ý…>}­¡X,Ò××G±X$NG 9ÐjµšÕj(¥°l›Þžž£Û¶I¥R!žõÖ[yӛÞÄ5×\C©T"ŸÏÁÙm;ò>³œGö‰V«…RŠt:Íàà ï{ßûžîºë%ŸÏ“J¥ð}ÿ¬‰Ýýá\>®ì¥Ò×ßÇÐÐЂg˜ÍfÉårÜ~ûíüÂ/ü—\r €Óé³w#Ô.kÒÙÀ›>ñRÈòÂp׉NEJ§Ód2ҙ4éTºcYl{ÂNvŒ÷ööâº.¿üË¿Ìë_ÿz®ŸújJ¥…BÏóhµZ]2St‰Pó§ƒÏàŽeû‡®læ¶RŠÈ[­ù]îëvöŽ "C‘°ä’îg•PB@P¥ñìg°zVceGÈ]÷ „Zè7h<ù7h¿B÷q:Ç։þ®oc÷]„3p1Ùþˆ`vvnŽ¢Q݃ö+GŒýØ;ŽB{e=¬žóÉ¿înê} ÿ÷NûÙv5+¥:®çsìâwÜÁÍ7ßÌí·ßN>Ÿ_4 ¬ÖÛ’ÜžŸŸR&Á“{fÙ>V6ñ”?!£££ÜqÇ\wýuÜtãM‹Jt W÷0ڛf¶îóݧa[Š?œìž:’k®¹†/}éK\uÕUŒŒŒ,"®IÙ6·^9B­°å`™ãUÓÈ/EpŸÂuêT,„àï|oŒí  Ÿø í¢Ø„cwʰu\Ç¢muœ¢sÔ_»Ö²Œ’U¬#r%D'ñ}ށcŸ}ÃhNSä/qWü4öÐeË­ Š·àí¹Ÿ°²;j%壛sèfyþý¡‡jÕP­Jއð+4žž.û d~™ÈÌìÆ?ô0ªv(ÞqšÆ, íºZ Õ,#ìT\¬[£êãŽö?Œ3|9„þ¢3i]{íµ\}ÍÕØ–}l+ÝÙ, ˆŽÕrmy³z_hRZXւ£,RÇ{m÷D%8ôñ7<‹D$|à8ªLÒâè+>Ú±Ô)éÝßýdûÉ>g1ô!×_}ä•èZOÉ$p- ÏR'ÌÞ}¡¶ìZ…ŽÛ'^šŸœèw‹í™žMH!<ñB»#˟ÆÜ7>jÐøÿtý0µÿü=„tÉT#Š g7Sþç·v®#„Dy³Tïÿ­øŒHèæÍÇþ”ŠS„ (Í ·m{wU±0ƒí8 €eÉèT‡v,‰††*…cKœ8V¥îÍ»Um+:&ˆ‹v‡JaII–X2 1haçÈ7!I;Šu Cm $¢sŠÄÙ¿šFÏŠåºøLóóµ8ABt¬ø(œè­ž¯ð°ó;€V|z†@#eÔŸíËJkdÜl):G3¶‚ ³Ø€]øaˆ-%¶%â~§Ïz«\ûÞ,ËZ ]—×ÓÐnÇúÿÙ;ï0+Êëß)·no,,,°À²,(Š?[¢b‰€±1jŒF£ˆ5±k¢QPPFQ±)*EŠ(eélaÛÝÛï̜ßsgöÞ-ˆaËù<wo™÷Ìû~ßóžs^ E¶µƒnáx[š÷œ ݈ïäo`‡"C‘tƒÕÍ睊 E6#tƒâ˜Ë^$Dt=nO„PTïþÃbñ`mô@JÙ÷œDæ®*V6,šîÊ"â5aä6WšMQHB2Ká@J(Ø ;ŠÑ\…¶²§}íÛšrvM$:ŒPy\שI^¡0'ßìmÉ+"K÷È@A–©.æ@¿¥Â²J?Œ. 2áQñÞê=Åt}»€`P l­ðcsE4CBiA:ºgyàVeD åu!l.÷£Ò†* œÐ' ©Ÿ` Y)N ,ÛŽUŸ7F›±Ù^]˜ C†$™Û±Uû#XYV‹pLÃIŹðº,ߎŸ]R]Ú/ Á–m©FLÓqTaºgyàuªÐtõa k¶Õb_CÍÀ‰}sâVPé‹ Ëë@Š[ÅçßVbo}ˆ£ áPd 镁®™îžxE5”U°~W²<œ< õÁ(–m®†?l®×;yin”UùñÍÎ:€{TÛ+™^ÜþPÌÞ§9Րê’1Œ8E¶÷÷£øbÓŸøw2?SA˜ÛëšÓ>ÙZRVˆ¡]~âËËæ†,¢ù¶|‚lAiMH€Ä™ 5;*mÛ_ÏHjœIˆ÷]BüèbÌ"á˜X$¶=Rœ2 ²ŠŽ{$IÂÚí5øv™'F”ä¢WŽe•~4„4;‹®ÊƚíuÐ ã€ö-fþwh†ïö6@Ûm 6…n#úç G¶^4PQBVŠœrœØžÇ€Ð3Û M'”׆¡Èœr=PvÔbÝ®z€8 *HCQ—Tìkˆ 6µëœ†c:Vl®A0ª!ªé<lc4„5,ÙT…@XCUC]Ó]Ú7©n©NÕþªÂè–éAnšµ(2œxœ üá¶WP”›‚Âbš/·VcO]…ÙœÔ/=sœšÆJ l¯ `s¥_Îf~J¡˜ ó]EãN,¶è“³ í02K0JÂ,“ôBB2c“¶öã:Š Ó®zˆˆfÀ‰"'Չþ]s‘î5=C‚Ì‚ Ÿ0úD5䥻âRærÀëT°§6XƒÇ¡@‰o$ß%ͅt·²lÆ5)²¯SECØ,%€„š@õ¡hcöµtÃ@m0‚Y^å¥ 'Õ C‰Çª™y¹/‚n™ºdžâV`è@º×XÃ..Õì*óR]Z€@–Œ.3›ÒZÒÌjµjƒQ»ž9ÛCÛÁ Ó † 2Ý8º0é5_j:’4Ã@µ/‚LÝ2<ØŸ/„Yn膁ªúBQin‡ƒ€Ÿ]RÑ3Û §*ÃÐ )N.UF$¡ÜØîÚ‚͎‘d›ø U¢•¹,ˍ"N’’\D|ÛœÑ(%xã}¿Y–³É:4µðsèø«‹,™Y÷œæV1¬o.Ò<*4MGuC1]AºÛ™¡Zˆ"֐•êD×47<.ºAš DÕt€žT;o&+ÕÕžCјÄœ ƒšö¿ß¥‡90œªŒÿ땅®™nTúBˆêrS]öv^uþ(êC1tÉp¡kºÇìò‰Gá jHÉtÀªŒ“áu Í£Ú^Š˜f˜9p ãH4Š7Ûu‚iH›ê°ŸÙpš¢1{ëÂ(ÈrÛËÌPˆ Ëï@~Š.E Kº Ñao]B²"A’Ìþ$7Íi'4VœŸ&A]јÎ}ÄÿH'Z‚Ð,Ÿ-²ÔXC1)û-yÚ^•¶åì…çxV3 3ÖÑúŒ$ìmþxé™aÚZ_ß~)©ä¥IFAŠÙ©Nì® â󍕐„À°ŸÙHw[»ÎDر/€ì4zæz¡Êêƒ1Tø¢f–«Š™5Z ŠÍUØYŠÇÉ̀C‘le`pLâ¬A;ñIIäŠ8Q˜›‚­• ؞LJZ 'ô͊ E3É B¥/ˆž9ôÎó˜ûÕjvU‡„cšÉºj[5¶T §b.UÅtzBÜÛCÛì#·*a@A*ŒNvÕaÕöZx*²SÍxD«é*ê#ð8Td{1šGR=Ô"Ø]„$ÂQ1ÍÌpþâû*Tû£Pd .EBL'h†Ìø„t¶‰ÿ‘ÇMŠ’­üâQ‹qo¢i@²³ü…¹4„]Çý’™=-$™›A›»žH€ÆzŒ,™¶ÚvFŒ.9i®€{S7œŽx©“˜E‘áV$d¥:ìàr«ï(÷… H÷šB Š&ˆº€™­ŒˆDux] sŒšðEéQq\Q6"šŽ¯·ÖpœQdI 7ÍÕØŸ Á°·³Ñ "žUÙ)æþîBö–°uÁÂ1ó5XG…/ IÂftËô`OM^—‚=ÒàRd¬ÛUÕAûxØ2Ž,²d&µ5í#B ¢Ã¥*f<±n@’òӝpÄ+eX5ZuÃ@C$†˜f ?Ó E’°Ïn˜µöê1øS5äŠ9‘“ê‚?¬¡G¶ƒ{ŠcsE[*üh*W˜ÿÕÀ(%Ԅ•ìÄ»Œ/cÎ0ÍØâød³qèøû­>eqì"”·ðcÚŽHlœpÇÃ*¢Û¿k:úwMÞŸQÓ ,ý~*ëÂè™ãE¯Œd¥šp( "šIÀãT sA¢Æ߆0rÓ\ÐtBe]šE’`ŸÞVƒÁ=3Ð;/=²œ0âÅYwUŒê%ÓcaVMàå€#cfçæVqúQÍwkX±yª¢„cèß5=sR ŽšË€‡‡"!Šðcšš !­k:„ÊëüšÅ Í l© 'Յž9^æxí%ç{|š Fmû”ïtÄúÄøÿ.‡‚Ý30 {ó÷Œµ|;vבæNÇ é蛟jÖȌï֑âr€‚€)ëƒQ䀹@ ”Uìúy;j RÝÙ8ŸO6ŽêžU•Šš¬#ÑàRÕÆÏÌÿ°Sˆ{øÓ;H„ßóÙòZc'ìÍý`×VLH„$âUt¬ØG˜âÑ^µV’¯3 ÅÄØMŽ©`Ú:¶Vøáq†[|=Šš EŽêXœ­éª,¡.èG­?Šž¹^4„ceM7†º`Ù©N„¢ª"I»9ì© BÓ ùNžT1ݬœW݁Š$l«ò£Œ^Am Ú!CTÚò„@f‚@ÔhU5Ôø#ð…4¬ØZ.én(²€/Ã>=sRŠjPeS( Ôb¶k`gM éëê‚Q|]Vü ܪÓÚŽbWM¡øÄaK•®z •õ‘é`hëEÃc†ow×·n1dö›ÊýˆDu€žUHB`wMNUAŠ×@$fùQݬb@ ø‚1øBQ;ÖÍ0;ªÍeè4·—CF ¢¡>ša_C„pÔÀw{|ædÄhÃ÷R‡2VËË'â‰( u—ãžÃx#6>Ïfn̐vY»3‰/9'¥T 5Æ>v¡h{^E¯`" ŒÍÞÈŠÍRBÏŸŠ1tM‡AF<9€x „€aøv/¡äDS] ìÙûÖJ¿-úÌv@¥/l.?Ç·}s«²Sœ„@}(_šq€°®m…/„òúÙ¬­§žM7°qoƒÝQHmôæ "Hñ؛ƒ¿îuuuˆF£mnÆ,„@Ye[àouŒâً{jB(¯ CÐâK‡U Õ¶Íš²¯SA^º ÕÍ¢éd9̎±ª!‚J_Šdz"íAÀ†Ýõ¶=ˆ6:Én* FüÙ[ÓV?D m¢ŸÂ,€þUYõ~=޲$!Õ°qoƒœSAf]£-ñ=8$ÉÜ­'Å©Àë4wÛÙ±/ÔóX+9[*ýEŽ—Bq‡–@0ªá›u Ñ6…6ٞ¶Ž1Ä7&™ÑèADÂV{V³=€„$˜äv¢$HñØD˜‰-ö2µè7nÁ'–žVŽÒ^R<υ ˜¬–#MŠoíg•:êàNŽ•€,ː$ó"èJvTÌN’3·ŽŒGH{ö^šª I’Ì6:ÌûLKBàž!C°gÛ÷ñ¶n¿íÝÒ.<BL'#»ªXYV‹úP¬Õs=»ùÙë ¡r×vôìÙý>Ÿ••=‚¡ë j¿ËT-·£) a þ°†}Ÿ0V•Õbo]žUԞíÁŒ§êjª¡ÈŽCÜç»wï"Ôí+‘ö:B ÑúÞÁºaÀŠÂÖ°œ*€µ;êŠê­Ÿ¿ñ»Úå"`ï¶ï“æEj;Š-Mjêž7®H[^„x‰,³Ž¢€âY̐ÌDXÏ'8gâ;œˆN”¶&5Sã ®WÇ£ËP̚·Á@4žyÎbñÛ±‘°†?Í^‡ÝÊ@äææB’$ÛEn>Æa‰“e×\s5ŸþdÖ¯\jÞšœEŒ4ÎڝuX°z7>ÝX‰-• œHDzÃ0P[S…7Ÿ{×ÿêÊCúŽ~ýúaÂ/ÎÇëù"áP|`é6aÝ.ëwÕáœ5{°h]9Êöùã¥pD‡ µÑbfM» 2ЧOŸƒjK뜿›z;ÞyþAÔ®ë«ᘁO¿«Â{köà¿ßW¢ª!ÜacN‰õµûð÷§ ÇD~~~‡ž±ÉÞ9¥±ð¶ «ov\"™‚Ðû’U'AY j\Ÿ&4æ>ËjR ŽLÒÒ³$I¶·J–ešªŠÇãS-†ß¿ô\<¢œz€@qÊàLϟ=Šc_Uÿüb/Rûÿ £N ‡ÃEQ È²œ }XœŠ’ŒÇºSn› _u%úõp¹SgTL» ôc_Å|0çEÌ|à 9î8{p8˜˜4Y–ñëk'Ÿ„Gn[‡I·L‡7%—«£EÁwøIguÅ”m\!ŠpþùÀëõވ€þÅÅxêé¿à¶Ûoš &£°_)Œ)éÃÞ® ˆECØŸé[|·ò¿xøÓpÞyçu˜“³JÙ$•ÇŠåJl|«¯rc]ë?IŽ{# ªùRce}s÷@\ uðŸ°YŒ¢58(ª UU‘“›ƒ±§†Å0cÁR|Wö=¡øöTݑf. Ã0 s0XIž………8ï²Ëðá‚ã⿜„¡Ý ñËá'›• I&ÈDNCY6³Ÿ‰ dÉ„–'Q$ìî"5š×ã›QlÝŽ ó‚þû_Ä$gõ3€¥¥ÅWûdȊܡ8JkBÅJ7 r|Ãt‡Ã—ËMÓ`4MëT{ ÿ¯°U,O®ªªp¹]Pµ1™E‘AqBÃ0 Ó©±t‹ªªÈËËÃI§ŒìñbSÙV\øìKÈMó`ܐ!8±žºåwAJZ–œt !%xÍ9"ŸC$ B0bQ¬Yÿ6lÛ†×æÿ¡X Ž”ääç#-- ðzœðx]×ö¢eæ§ÀêÛ{9†éÈ÷§"›¹©)©™Ï§Š¥Âét¢¡¡@~¿±X ÑhÔ¡³r-¬ÄP+€Î R²³ÌápØax©©©ðx<ÈÊÊBVv62ÒÓM¢ÓÕ¬Öq‡ŠM òZ£,Ì=…I¢€¥f«8>ñð‹ÄŠÿ7ýÇüžN%£Á߀ܜ\ŸžÌ B«V­Â±ÇË„±íbËÖ-èÛ§/O ÚÀ˜IDöŠ›Ûã¶ÛÃëõÂírÛ"1 "‰ØžE+œÎ*ñ·nÝ: 4È‹‰;Õ%Ö7öx?wî\¬[·Î,ãpÚ](²UI.Qg-q7ýmŠmMÓðâ‹/ÚG"<ÿüóŒƒL'ï4êêëq×]w5{퉾xä8P&QD"\wýõÍ^ûä“O°æ›oØ^:i?²µ¬ sæÌiöÚµ×^‹@0ÈcLŒMEcbFó[oœ¿ßßì³³fͲ=’–·Ð›Mw]éèýA‡Š3gÎÄöíۓž{衇àóùžsïÄÿôiÓ iñúë¯ÃívãÊ+¯ä‹Ä$uúÿyÿ}Tïۇ{Ƕ—>}ú`ì©§òEꀜsöÙÈËËK‹=öà…žC‚iû¢Ñ 7ވ3Ï<·ß~;ଳÎÂe—]†W^yµµµ|á:’P$"ìÛ·wÞy'Ün7233QZZŠôôtÀ7ÞÈ­ÝI1 ݺu᪫®²Ÿ¿øâ‹ qæ™gr‡À$±léRƒA̘1ªª.ºè"lÞŒ=öŸøâ ŸHŒM›6aʔ)šššÀøñãíçoŸùf†êêjŸHíŒ'Ÿ|ò Þ{ï=üñ€^œzáÕW_ņ ðÈ#ðE šùʧL™"Âm·Ý†nžïŸû.ŸüòK|ûí·øýï+V ??¿CÌú ðkAƒAøPYQk®¹Š™Wµ3ÓŽDAbüJkïaØ^,222P__h4j‹F†í‚û‘–‰D"())ÁË/¿ŒôôtddfÀãöÀëõÂápŽ™=›¶Õ[oœ…ñãÇã7¿ù þò—¿p›& t€“¹ûî»í”ö`0ÈÊÊ€I“pÙe—a×®],:ãlèڜí‚a[`žáöä6mN‡ZzÎÌÌŽgwápl€=zôà`c†a†a˜Î&›n—‰DL¡èpðì€a†aŠ3 ÅŠXÅ3SÄ0 Ã0 ÃB±%¡ÈÁç Ã0 Ã0,[ŠŠ Ã0 Ã0,[ŠÕÁ­Ì0 Ã0 ÃB±‘@ `ž $q+3 Ã0 ðPl$rë2 Ã0 ðPd†a†aX(\d›a†aÖ,[„‹l3 Ã0Lû`M_ßßû›î¿}8Q]×ADüÝí]\*lž Ã0 ÃI„Ð4 Ï?ÿ< Ã@×®]1|øpôîÝ»™ÃGÍ›7£k×®ðzœÍ^{íµ×0dÈ”––öc\Œx1N<ñD€€€ ‹áùçŸG0„a(,,Ę1c““ƒE~ˆ%%(,,Ž¿Ã0 ”mۆšêjwÜqí"á¶C{.Ã0 Ã0í]×ñþûŒÁ@«×¬ÆŠåËaF‹ï_œz5êëë[|mþüùزeËa9®D`yy9vïÞ ]×ícþàƒPQQ@ €+V`åʕB  AÓŽfß·{×.¬[·®Õßhkth¢Ëåâ;a†aÚ ………žcêÈËÍÎ;ð§?ý gŸsª««ñÚk¯!¢wïÞ:t(.\ˆ­[·âª«®Â¿þõ/”——£k×®øÅ/~I’°bÅ ¬]»yyyøÕ¯~…ï¿ûKŸX‚-[· OQLœ8ëׯǢE‹lá&„À;mÛ¶!55\7ju IDATx2Ò3ìeçE‹aذaI^ÌÞœ{ãŽ;î@nn.6mڄ3fàÌ3τËå‚~ø!V¬XÃ00ùªÉÌÒ}±X ¯Ÿú*Î9çtéҥͶI‡ô(Z ž=Š Ã0 Ó~ "Äb1[4ææå¢²²Û·oÇØ±c1vìXø|>(Š‚ž={bÌ©cPUU…nݺaòäɈD"XŽh -- W\qêëë±`ÁÔùꐓ“ƒ)7OÁâŋQ^Q޹sç¢_¿~=z4`Æ ˆÅb8묳гgO,\°Ð†a ²²ÙÙÙP%é˜-Ýѯ_?€ŠŠ¢ŒŒ«V­ÂΝ;±aÃbäȑ‡Â0 ë֭Ì3püñÇ#++«M·I‡ô(Z æt:ù®c†a˜vJ8†Ëí‚ËåÂìÙ³í1^Qž\.d€g@–e¬\¹+V¬ÀΝ;1jÔ([Ž €€›6mBn^.V­Z…5kÖ ¬¬ þ?Î<ë,Œ·p¡-.ËÊÊðñÇcåʕˆÅbI"Î×àC^^Þj‹P(Ç"‚ËåBqq1Þÿ}|ôÑGží¶Û $÷ß=zô@·nÝ ªªí±d¡ø?Š`"Ã0 ÃŽB¡vìØ=Šcé²¥ðx=ÈÎÊÆ÷?`z Ã|öùgˆÅbPÕÕÕøòË/‘ŸŸsÏ=/¿ü2¢Ñ(ˆ[·nŎ;°iÓ&Œ5 K–,AFF®žò |ýõ׈Åbس{7&Mš„ÞEœñÕW_¡°°£GÆ±Ç‹ÚÚZø|>ûØvíڅŸ}ûÂãõ4;æíÛ·#‹áÏ>Dߟ}‘––"B4…ÓéÄ€I“°qãF|òÉ'èÕ³nŒñFŒ3÷Ýwîœ÷^dff¶Ù6éÐEUUù®c†a˜v€Š¢à¹gŸƒ$IèÖ­Î>ûl8œvÚixûí·‘——!$IBŸ>}0oÞ<Œ7óæÍÜ9sÐÐЀ’’ôíہ@¯Œò ºvíŠÁƒcÏÞ=øìÓÏðüsÏ£OŸ>Ðu¹¹¹xýõ×±yóf@ÿþý±¯ºsæÌA À•W^i„œœšJ£¶’€Ï=÷ W¯^žä’K`ºt邮Ž4”••aÑ¢Eðûý˜! ÃhñFŽfrŒ¥ EæÐm……"Ãý~Pø±8d¡Øæ‰D"æÉu’Nݺ ›fCÈ ÍžNN` I’Ø^îG^bî@}_G<);FQí\³Ÿ)†aŠ?@gˆQd†a†a¡xXKϪÂñg Ã0 Ã0,‡ÃØ£È0 Ã0 ÃB± VŒ"3 Ã0 ðPLÂÚӘ…"Ã0 Ã0 EBãŽ$,†a†aX(&*EzãŸÇ Ã0 Ã0 Eké™wÝ`†a†a¡˜„µ/=3 Ã0 ðPLB×u!xé™a†a†…bs¡pŒ"Ã0 Ã0 Å„"/=3 Ã0 ðPl.ãåq$Iâf†a†a¡Øˆ¡£È0 Ã0 ÃB±9Œ3 Ã0 Ã0 ÅV…"Ç(2 Ã0 ðPlQ(ìQd†a†a¡˜ÙENfa†a†a¡˜{†a†aX(îW(²G‘a†a†…b3¡ÈÉ, Ã0 Ã0,[Š/=3 Ã0 ðPlA( ! ÉŒôÌ0 Ã0 ÃB±‰PYb"Ã0 Ã0 Å4Mãò8 Ã0 Ã0,›Ã1Š Ã0 Ã0,÷+Ù£È0 Ã0 ÃBцˆxé™a†a†…bËðÒ3Ã0 Ã0 ÅV…"Üf†a†a¡Ø MÓBna†a†aŠÍ…"{†a†aX(6ŠœÌÂ0 Ã0 ÃB±œÌÂ0 Ã0 ÃB±E¬¥gö(2 Ã0 ðPL"‹ñÒ3Ã0 Ã0 Åd¬‚Ûg=3 Ã0 ðPl‚åQd†a†aX(2 Ã0 Ã0,†a†aŠ ُyé™a†a†…b’8Ôt.Ã0 Ã0 ÃB±bÑÀårqë2 Ã0 ðPl$RRRžu†a†aX(6‹™EÇíË0 Ã0 ÃB±¹Pt»Ýܺ Ã0 Ã0,‰D#Ø£È0 Ã0 ÃB± ш£ÈÉ, Ã0 Ã0,“°–žY(2 Ã0 ðPLÂÊzv:Üº Ã0 Ã0,› ENfa†a†a¡Ø¢Pt8ܺ Ã0 Ã0,› Eö(2 Ã0 ðPlQ(²G‘a†a†…b‹B‘“Y†a†aX(²Pd†a†a¡øÃD"Š Ã0 Ã0,›ÃE†a†aŠ-â÷ûBn]†a†aŠL™2±X ×^{-·.Ã0 Ã0̏@éh'$„€¢˜§EDìYdæGQ__ρa:8VØZ(â‹ÑTWñe`: ‰“žH0c/ Ãýß÷,†a†a&ŽÄ—€a†a†a¡È0 Ã0 ðPd†a†aX(2 Ã0 Ã0,†a†aŠ Ã0 Ã0LûŠû«ªs€*î$þîø ‚Áà+T)„À_|Ë/¿B‘}¬SŠLÁ… ›Û… qÅW@h4Úìu!úôéƒÊÊÊÃ"L:òÍý׿þ¥¥¥ÈÎÎÆ±Ç‹yóæÑÂ¥B\{íµxûí·“Šãôïß~¿?騄žì²ËðüB†Ñ¬wî܉‹/Ÿø€ÎI]×m[dZŸFpë­·¢°°9998ûì³±|ùò#zÍB¡JJJ°f͚$ÛYœz5ºwï]כÇi§†]»vµÚ<øàƒxàØv¬þš³ÙŽu}n¹å–va«V­b›8Lãˆ_~ù%FŒ¬¬,`Ö¬YˆD"GtYŽhnžá†fºâ—¿ü%Ÿøâ‹fÇöúë¯ãšk®Ù¯®())ACCC»ÐÒ¡6æþð 2§vfϞY³fáÓO?ÅÒ¥Kø{ÕöÁÎÐZzLD8逓ðþû®B!ÐÐЀ'žx'œpB³ï ƒš¬¬D(Bߟ}á÷û›}ÿŽ;š‰†Äc6 Ãnü àÏþóuG¹Ù‰cǎœO>‰;n¿oŸù&®ŒòJÜ}÷ÝØ³gÏAµ§ÕÙ.{8wܹžêª«’lwɒ%(..FJJJ³ÏVTT  aÙ²ežîºëšµ£Šiö€¡µY¢µ”aøÅ/~ïŸûŽ«ü·ÂŸ}ûМ{w¬]»3gÎÄ믿Žc=ÓŠMC8>š¶×4íl·%[s»Ý8÷Üs1cƌ€áÑGÅo~óȲÜì8,[Ÿ9s&,XЬÍëêêP[[»_C$ø|>ôë×µµµ?h;ÍÓdÙĺuëڜMœsî9ÍlbÖ¬Y?Ê&êêêÎ&ê:žMX×òŽ;îÀšQ£pî¹çbΜ9x衇ðïÿ_}õÕAµ]â¿Ã1ŽŒ9¯œöšíB ŠŠoŒñŽ>úèfßé÷ûQUU…úúz”””  6ûþ;wîWWX¶+„ÀoŒçŸþȍ#t|ýõ×€| Ÿ€ç à MÓZýœa͞{î¹ç( î÷÷ZúœE,KzŸatà 7Ðøñãí篟új:çœsZüÞ·Þz‹Î<óÌýþŸ¢(ŽwïÞVëž{ïiñµ–Ž»µsÙß9¶u&L˜@ƒNj «mt]?às4 ƒ† ²ß÷·v]›~&ñ}éééŽpáBûïÂÂBúì³ÏZü±cÇÒ3Ï<Óâ1D£QÚ»w/rÊ)­þö—_~IÏ>÷ìµïKg K—.t÷=w7»±X,鹺N‘H„N8á„}œ›Ÿ'%%…‚Á ý\FF†mÓÖÿÖk¥¥¥TVVÖâ1„B!š>}:ÝvÛm­þö_ÿúWZŽhÑÛN"š®±MA›°¬ML›6n¿ýöýÛćÃ&>üðCBP Hz^×õƒÖúӟ~Ԙke‰m?qâDúå/i¿ç¿ø]~ùå-~ï³Ï>KçwÞ~Ï×ívS]]]«Çuß}÷µ]qHBñž{ÕÙºu+ p8Lº®Ó1ÇC‹-¢œ{÷RQQ|òÉtà 7В%KH–e*))¡óÏ?Ÿt]§… RQQ•––Rߟ}ié²eDDtÆgЈ#èüóϧîݻӓO>I—^z)ué҅nºéŠ€ãØµk œ{÷’ßï§ŽŽ4Ú²e ?žŠ‹‹©ÿþô·¿ÿˆÈŠõõõ€êëë)‰Ð駟NtÊ)§Pjj*UVVҳߠââb0`ýê꫉ˆhʔ)€ DoŒñýýï§[n¹…ˆˆŸúê+:á„hÀ€T\\LÿøÇ?ˆˆhîܹ”M_|1Ҕ)SÚm§ …𰰐–.]Úê{Þzë-[š744Ú·o-Xž€Ž>êh=z4œûî»ôøã8p =ôÐCDDt×]wQQQÓÏ~þsjhh ø¶“ôë_ÿš†J€gŸ}–Î<óLÊÊÊ¢%K–$ýþ‚ ìÉÀ|@©©©ŽsçN*--¥ÒÒR:t(UVVÚBñ…^ ÷ߟ~ö³Ÿъ+𰰐LC† ¡ÓO?Ýî(,{zíµ×ÈçóÑ1ÇC]ºt¡Þœ{S0€Aƒњ5kˆˆèÅ_€RÿþýièСôÍÚoìh„ töÙgSNN}ðÁB$nÙ²…О={ZíЮ¿þzš7ožýþ~ýú‘aô»ßýކJ£F¢•+WÒùçŸOB*..ŠyóæQ$¡‰'Rii)õêՋnºùf{WU•ŠNJÅÅÅtÊ)§Ð}÷ÝG'žx"åççӞ={’úµë¯¿žüq""úóŸÿL—^z)­^³šúõëGLš€–––Ò®]»èÖ[o¥×_ˆˆþö·¿QNN >œrsséöÛo§P(DƒŠА!ChóæÍŽvÝ:r:Ô«W/***"Àoß'DD·ÝvõïߟŠŠŠhÜyãš¶¶–ü~?¥§§ÓÕW_M£F¢ââbûýÙ&®»î:Û&6oÞ|@6ñÎ;ïŽM 6¬E›žîºëè‰'ž°mâ²Ë.ûÉlÂáp4ڄ¿u›8ïŒól›HKKk—6ñÛßþ–f͚ժ®Øžq# h4JšŠQ=è¿ÿý/mÛŸŠŠŠhäȑ4uêTúä“Oìqä’K.!"¢·ß~›zõêE  ’’Zœz5wÜqtê©§ÒÙgŸM=zô gž}†&NœH¹¹¹4}úô€ß/++#T]]MÕÕÕ€ª*mߟ~þóŸSÿþý©€€„þõ¯% ÅÊÊJ@~¿ŸhäȑԣG=z4åääÏç£çžŽŠ‹‹©€€„®¿á""ºæškHQ4hœÿþûôä“OÚâwɒ%tÜqÇÙçòÏþ“ˆˆþñPϞ=iâĉTЭ€~ÿûß¶¶9$¡ø«_ýŠ{ì±V_ß¶m[’P1b-^Œ˜}žˆ²²²(؊}ÔšQT^^Nº®“®ë$Ë2ùý~ÒuÊÊÊH–e"":çœsèÞ{ï%"¢>úˆŽ9æû÷2Ò3šy³.»ì2zê©§’ü;vÑŒyóhøðá€ëº-}>Ÿ}̏=þžm`–G±¢¢‚6lØ@Ñh”vîÜI(‰PMM ÷ÇÙï}ã7è®»î¢P(DùùùôᇒaŽmÛ6r8Ž~ýzš?>vÚi€i}ÿý÷$ ‰@»ìØý~?eggÓ·ß~Ûê{æÎK'NŽß/„ úúzšú»©tÇÔ;ÌÙ¯ŠÑöíÛÉrr†A/œôõìÙӞáÝxãv»§€€Ðúõ뉈hèС4uêT""zõµW›y5M£ŒŒ<ª©©¡Q£FÑã?N;wî€êêjÛãlyrƎKÏ?ÿ<}ôÑGtÑEÙ^ÎÙ³gÛӘ1c’ìiîܹ4räHÒuŠOŸN?ò°=6l­[·Ž–/_N^¯—***l;éÝ»7Åb1ºüòËéßÿþ·ùüì7hÒ€IB(~õÕW€jjjZ}Ï­·Þj_›­[·Ú熞@ .°¯óŒyó(77×þÜ©§žJ'NŽ…@aa!͘1ƒˆˆzõêeD‡ƒ>ùä""9r€=¶Xœzµ}¯Ë²LK—.¥õë×S  p8L………TUU•$ îºë.zë­·š¢¢‚dYŠU«V‘®ëtÇwÐm·ÝFûöí³'&Ó§O§_|Ñ<Æ…ôÞÞ#Ã0šŠŠ†$I"ŸÏG/Ÿø";Ö>—;~ýë_S4¥ŒŒ<ÚŽi]{íµ4þüNa ,hn'œ@ ß[تMŒ3ŠU›èÝ»w’M|úé§DDtòȓéž{î9l6QނMÜ~ûíÍl⥗^""¢=zÐþóŸC¶‰__ûkûþiëŒ?ž^yå•V_ÿî»ïHUU[(8–-[FóޙG………Ž„m0dÈ ƒ€ë:R…¢Ñ(éºNkÖ¬!§ÓIDD't͜9“ˆˆfϞM'žx¢¹z‹R—.]šÃùçŸOsæÌ¡9sæÐ„ H×uÚµk—ݧ7.I(VUU‘ªª€ÅbtßÿH¿ùÍoìïòx<äóùhãÆ‹ÅhóæÍ€b±íÚµËgˆˆžyæzôÑGÉçóQZZý÷¿ÿ%]×iãÆ$Imݺ•Þ|óM{œ]»v-¹\. …B‡¥m)™eìØ±x饗~0ÞÎZO·@Ǟ:SŠLAϞ=ñî»ï6JJ$IÂ7ß|ƒ¡Ã†ÂëõB‚‚`Ϟ=BÀårÒÓӑššjŸGaf¿ÿÀàÙgŸÅ­·ÞŠ[oœàp80}út|òÉ'€–O]Q|ýÕW8íŽÓ’ž×uÅÅÅxä‘GðꫯÚ1VŒBK1 õõõ8õÔS={öD—.]°lÙ2!àt:!Izô背fq*í—Ë…‚‚Œðâ ‡1í®iøv÷(--ÅÞœ{“ÚD¯¿þÓ§O·ÛeòäÉX»v­ýº¢(€¢¢"šª èÝ«7öîݛˆ+I˜4i.ŒðB|ÿý÷žéŠ›Ðœ{wlÜž3gÎÄæÍ›F[_Ù±c&L˜`—…·§O?ý4ÉÖ[²­Ï?ÿEEEÈËËLœ8»wïF(!-- pì1Ç¢ŒŒŒSÄ'–””–/_Þ,Ÿšµ~Ċý|áù0í®ižð ›%LE£Q¬_¿7Ýt“Ý÷ß?V¬Xa¶›ªÚï/..¶íhøðáØ¶m[Òo<¥¥¥;v,zõê…aÆ¡ŽŽoŸõž~úiø|>;†¬)UUUÐuÇs $I²3;;{öîÅC=„õë×7ÆÑ @–ä€sQUïŒóÎ8ã ûùoŒŸþ9TUÙ}aÿþýQVVÖ1lbÅþm¢©m†^xwýþ®$›°^F£Ø°aC«6¡(J’MXñ†#†8p›xóM<ýôÓš¯¯oÕ&ö MÄb±ÆþK–Zމ3Ï<óm¢€ ¶nÝÚ.Ú~ôèÑxæ™g*Žß0 Œ;w.œôRt/èŽE‹5Ó«W¯Ægœaß÷}ûö…×ëEMM=†@VVŒ^¯y999Í~ïŸûîßÿügÜsÏ=˜:u*$Ižûî»±dɒVSV¬Z¹gŸ}v3]QTT„xoŒñF²®šëŠêêjD£Q >BôïßiiiXµjUÒ¹!‹Ù9G$™åÜsÏE ÀUW]…h4jd~÷ÝwXŽh‘$P^^Ã0l£˜>}:6l؀+.¿ápn·>ŸD„ÒÒR|±ä hš"B]]vìØnݺµ˜º?cêÚµ+222PUU…O<ÑhGunºé&Œ?ÑhŽÅÏiš†“O>¹YRŽ¢(˜5kJJJpýõכB—Ë…` Øì{<Ün7–/_!***PUU…všŒ5Y–1gÎÌ|d&æÏŸog À;͛7#=={÷îÙÁèBhš†wß}wßs7ŠNjO¬ ÿþxøá‡í¿çΝÛâÍÛT ¶”aöÛßþ‹/ÆÕW_m'­Œ7·Þz+†ºßšwïÞøàƒšÙÚ qóÍ7㢋.²…ŠÃá@]m]³c2d¶mÛf'3|øá‡ÈÎΆÓé쎉,^¯óçÏDŽ °yóæ€ë;g΄Ãa€¥¥aýúõöä˺žEEEX¹r%4MÓO>‰ÔÔTÛîºuë†^xÁþ­‡~}úôùÁA§%‘ÿâ‹/âóÏ?ÇË/¿ Xºt)–/[†)SŠ K—.­~_~~>dYÆæÍ›íc³’Ž2·ß~;Fm¿&I’ÝRB@û)§œ‚O?ýÔþüìÙ³qôÑGÛ u j ¶MŒoÝ&RSS±aÆVm"ŠÅðä“O"%%ÅNŽs8èÚµ+^|ñѲ «jAS^xá…f6±bÅ L™2ùùùl”Ly<™óIDAT×’MȲ _}s›=zt«6Ñ퀈pÙe—¡¬¬ 7Ýtb± Àaøæ›oðñÇ#-- º®£ººº®ÛößÐЀx«×¬ÆW\]×át:Q__"ÂÀ±páBûwÊËËQSSƒ¬¬¬Nr±èÛ·/b±b±JKK‰DPܯn¹å\pÁI¿©®8逓ðÙgŸ5ÓÓŠMÈ#píµ×Ú¿ër¹ðš}Ozzº-~­„˜††ôë×ï'må`? „€ÛíÆºuëpÉ%— ;;]ºtÏçCVV^~ùedgg㗿ü%ƌƒ“N: kÖ¬®ëxûí·ñðÃÃëõâÜqçÂétb„ 8ãŒ3™™‰¥K—âÕW_EVVºvíŠêêjŒ÷Þ{v‡`‰ MӒÒÊëëë[ô ^~ù娳gÜn74MÃQG…«®º Çw–/_Že˖Á0 øýþ€ ³É“'ãã?Æ)§œ‚h4 MÓ`òóóq÷Ýwc˖-0 ³fÍÂŽiӐ››‹ã??ÿùÏQ\\Œ`0Çƒ7Þx\p233Q^^Žûï¿C‡Åܹsíã§&™Óí "BII Ö­[‡‰'bÒ€IÈÍÍEMM ŒÙ³gcøˆáhhhÀÉ'Ÿl e—Ë…›oŸÙž=ÿá@jj*Î9ç””” K—.øôÓO±fÍäææ"-- ÙÙÙXóÍ@CCƒ=;ÓXÓ4ø|ŸfÇXPP€+'OÆ\`Š¢àÎ;ïĆ ðÁ`äȑðûýˆF£ölL^xW_}5f̘@ `Ï֏>úh\uÕU2d–.]Še˖áôÓOÇĉ±`ÁLŸ>Á`Ðìïžã¡[·n…B˜={6€ÝÁèº~ØfíÁvÎ>ûl<óÌ39r$ˆ>ŸãƍÃy睇 /Œgœq>þøc ‰@’$œþù…Bš©©Ác=†ŒÌ tëÖ ƒƈ#°xñbŒ7EEE‡Â5zyä‘fý…Ïç³×`0ˆ@ Ðì‡ †‰'âä“O€€€àœ÷ÞÃÃ?ŒêêjL:¯œö|> Ã@(B4Evv6æŒ9—^z)4MÃÆ1yòdšªŠ®]»â·¿ý-ðÙgŸáÜsÏŔ)SpÛm·á¡‡ÂÃ? Ã0‡1eÊ,_ŸYYYHIIA÷îÝñ¯ý ‘HµµµI}×ÿ·sÿ.ƒǟô†¢Œ.E'—®¢NÙtr±H¯“à&8þ×E:JAž@p7ÝÜœ]K—€Œ6¹ÁKHcÓêÑ~?“Úö5íû4ï“’v¥dš2Q­Vµœœ­›››ÔL4~7Žøs±/···ÚÝÝÕêêª\וã8fÂu݁™ØÜÜìËÄ‚®®®¢Lœ©ÕjõeÂó–‰?ٙèt:º»»ËÌÄÉɉîïïf¢ÝnG™ð>–eYZ__WµZ•mÛò ]> Hibernate Validator JSR 303 Reference Implementation Reference Guide &versionNumber; &versionNumber; ©rightYear; ©rightHolder; libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/0000755000175000017500000000000011402110353030737 5ustar twernertwerner././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/defineconstraints.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/defineconstr0000644000175000017500000003674011262172500033365 0ustar twernertwerner Defining constraints
What is a constraint? A constraint is a rule that a given element (field, property or bean) has to comply to. The rule semantic is expressed by an annotation. A constraint usually has some attributes used to parameterize the constraints limits. The constraint applies to the annotated element.
Built in constraints Hibernate Validator comes with some built-in constraints, which covers most basic data checks. As we'll see later, you're not limited to them, you can literally in a minute write your own constraints. Built-in constraints Annotation Apply on Runtime checking Hibernate Metadata impact @Length(min=, max=) property (String) check if the string length match the range Column length will be set to max @Max(value=) property (numeric or string representation of a numeric) check if the value is less than or equals to max Add a check constraint on the column @Min(value=) property (numeric or string representation of a numeric) check if the value is more than or equals to min Add a check constraint on the column @NotNull property check if the value is not null Column(s) are not null @NotEmpty property check if the string is not null nor empty. Check if the connection is not null nor empty Column(s) are not null (for String) @Past property (date or calendar) check if the date is in the past Add a check constraint on the column @Future property (date or calendar) check if the date is in the future none @Pattern(regex="regexp", flag=) or @Patterns( {@Pattern(...)} ) property (string) check if the property match the regular expression given a match flag (see java.util.regex.Pattern ) none @Range(min=, max=) property (numeric or string representation of a numeric) check if the value is between min and max (included) Add a check constraint on the column @Size(min=, max=) property (array, collection, map) check if the element size is between min and max (included) none @AssertFalse property check that the method evaluates to false (useful for constraints expressed in code rather than annotations) none @AssertTrue property check that the method evaluates to true (useful for constraints expressed in code rather than annotations) none @Valid property (object) perform validation recursively on the associated object. If the object is a Collection or an array, the elements are validated recursively. If the object is a Map, the value elements are validated recursively. none @Email property (String) check whether the string is conform to the email address specification none @CreditCardNumber property (String) check whether the string is a well formated credit card number (derivative of the Luhn algorithm) none @Digits property (numeric or string representation of a numeric) check whether the property is a number having up to integerDigits integer digits and fractionalDigits fractonal digits define column precision and scale @EAN property (string) check whether the string is a properly formated EAN or UPC-A code none
Error messages Hibernate Validator comes with a default set of error messages translated in about ten languages (if yours is not part of it, please sent us a patch). You can override those messages by creating a ValidatorMessages.properties or ( ValidatorMessages_loc.properties ) and override the needed keys. You can even add your own additional set of messages while writing your validator annotations. If Hibernate Validator cannot resolve a key from your resourceBundle nor from ValidatorMessage, it falls back to the default built-in values. Alternatively you can provide a ResourceBundle while checking programmatically the validation rules on a bean or if you want a completly different interpolation mechanism, you can provide an implementation of org.hibernate.validator.MessageInterpolator (check the JavaDoc for more informations).
Writing your own constraints Extending the set of built-in constraints is extremely easy. Any constraint consists of two pieces: the constraint descriptor (the annotation) and the constraint validator (the implementation class). Here is a simple user-defined descriptor: @ValidatorClass(CapitalizedValidator.class) @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Capitalized { CapitalizeType type() default Capitalize.FIRST; String message() default "has incorrect capitalization" } type is a parameter describing how the property should to be capitalized. This is a user parameter fully dependant on the annotation business. message is the default string used to describe the constraint violation and is mandatory. You can hard code the string or you can externalize part/all of it through the Java ResourceBundle mechanism. Parameters values are going to be injected inside the message when the {parameter} string is found (in our example Capitalization is not {type} would generate Capitalization is not FIRST ), externalizing the whole string in ValidatorMessages.properties is considered good practice. See . @ValidatorClass(CapitalizedValidator.class) @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Capitalized { CapitalizeType type() default Capitalize.FIRST; String message() default "{validator.capitalized}"; } #in ValidatorMessages.properties validator.capitalized = Capitalization is not {type} As you can see the {} notation is recursive. To link a descriptor to its validator implementation, we use the @ValidatorClass meta-annotation. The validator class parameter must name a class which implements Validator<ConstraintAnnotation> . We now have to implement the validator (ie. the rule checking implementation). A validation implementation can check the value of the a property (by implementing PropertyConstraint ) and/or can modify the hibernate mapping metadata to express the constraint at the database level (by implementing PersistentClassConstraint ) public class CapitalizedValidator implements Validator<Capitalized>, PropertyConstraint { private CapitalizeType type; //part of the Validator<Annotation> contract, //allows to get and use the annotation values public void initialize(Capitalized parameters) { type = parameters.type(); } //part of the property constraint contract public boolean isValid(Object value) { if (value==null) return true; if ( !(value instanceof String) ) return false; String string = (String) value; if (type == CapitalizeType.ALL) { return string.equals( string.toUpperCase() ); } else { String first = string.substring(0,1); return first.equals( first.toUpperCase(); } } } The isValid() method should return false if the constraint has been violated. For more examples, refer to the built-in validator implementations. We only have seen property level validation, but you can write a Bean level validation annotation. Instead of receiving the return instance of a property, the bean itself will be passed to the validator. To activate the validation checking, just annotated the bean itself instead. A small sample can be found in the unit test suite. If your constraint can be applied multiple times (with different parameters) on the same property or type, you can use the following annotation form: @Target(METHOD) @Retention(RUNTIME) @Documented public @interface Patterns { Pattern[] value(); } @Target(METHOD) @Retention(RUNTIME) @Documented @ValidatorClass(PatternValidator.class) public @interface Pattern { String regexp(); } Basically an annotation containing the value attribute as an array of validator annotations.
Annotating your domain model Since you are already familiar with annotations now, the syntax should be very familiar public class Address { private String line1; private String line2; private String zip; private String state; private String country; private long id; // a not null string of 20 characters maximum @Length(max=20) @NotNull public String getCountry() { return country; } // a non null string @NotNull public String getLine1() { return line1; } //no constraint public String getLine2() { return line2; } // a not null string of 3 characters maximum @Length(max=3) @NotNull public String getState() { return state; } // a not null numeric string of 5 characters maximum // if the string is longer, the message will //be searched in the resource bundle at key 'long' @Length(max=5, message="{long}") @Pattern(regex="[0-9]+") @NotNull public String getZip() { return zip; } // should always be true @AssertTrue public boolean isValid() { return true; } // a numeric between 1 and 2000 @Id @Min(1) @Range(max=2000) public long getId() { return id; } } While the example only shows public property validation, you can also annotate fields of any kind of visibility @MyBeanConstraint(max=45 public class Dog { @AssertTrue private boolean isMale; @NotNull protected String getName() { ... }; ... } You can also annotate interfaces. Hibernate Validator will check all superclasses and interfaces extended or implemented by a given bean to read the appropriate validator annotations. public interface Named { @NotNull String getName(); ... } public class Dog implements Named { @AssertTrue private boolean isMale; public String getName() { ... }; } The name property will be checked for nullity when the Dog bean is validated.
././@LongLink0000000000000000000000000000015200000000000011563 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/bootstrapping.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/bootstrappin0000644000175000017500000003721711262172500033426 0ustar twernertwerner Bootstrapping We already seen in the easiest way to create a Validator instance - Validation.buildDefaultValidatorFactory. In this chapter we have a look at the other methods in javax.validation.Validation and how they allow to configure several aspects of Bean Validation at bootstrapping time. The different bootstrapping options allwow, amongst other things, to bootstrap any Bean Validation implementation on the classpath. Generally, an available provider is discovered by the Java Service Provider mechanism. A Bean Validation implementation includes the file javax.validation.spi.ValidationProvider in META-INF/services. This file contains the fully qualified classname of the ValidationProvider of the implementation. In the case of Hibernate Validator this is org.hibernate.validator.HibernateValidator. If there are more than one Bean Validation implementation providers in the classpath and Validation.buildDefaultValidatorFactory() is used, there is no guarantee which provider will be chosen. To enforce the provider Validation.byProvider() should be used.
<classname>Configuration</classname> and <classname>ValidatorFactory</classname> There are three different methods in the Validation class to create a Validator instance. The easiest in shown in . Validation.buildDefaultValidatorFactory() ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); You can also use the method Validation.byDefaultProvider() which will allow you to configure several aspects of the created Validator instance: Validation.byDefaultProvider() Configuration<?> config = Validation.byDefaultProvider().configure(); config.messageInterpolator(new MyMessageInterpolator()) .traversableResolver( new MyTraversableResolver()) .constraintValidatorFactory(new MyConstraintValidatorFactory()); ValidatorFactory factory = config.buildValidatorFactory(); Validator validator = factory.getValidator(); We will learn more about MessageInterpolator, TraversableResolver and ConstraintValidatorFactory in the following sections. Last but not least you can ask for a Configuration object of a specific Bean Validation provider. This is useful if you have more than one Bean Validation provider in your classpath. In this situation you can make an explicit choice about which implementation to use. In the case of Hibernate Validator the Validator creation looks like: Validation.byProvider( HibernateValidator.class ) ValidatorConfiguration config = Validation.byProvider( HibernateValidator.class ).configure(); config.messageInterpolator(new MyMessageInterpolator()) .traversableResolver( new MyTraversableResolver()) .constraintValidatorFactory(new MyConstraintValidatorFactory()); ValidatorFactory factory = config.buildValidatorFactory(); Validator validator = factory.getValidator(); The generated Validator instance is thread safe and can be cached.
<classname>ValidationProviderResolver</classname> In the case that the Java Service Provider mechanism does not work in your environment or you have a special classloader setup, you are able to provide a custom ValidationProviderResolver. An example in an OSGi environment you could plug your custom provider resolver like seen in . Providing a custom ValidationProviderResolver Configuration<?> config = Validation.byDefaultProvider() .providerResolver( new OSGiServiceDiscoverer() ) .configure(); ValidatorFactory factory = config.buildValidatorFactory(); Validator validator = factory.getValidator(); Your OSGiServiceDiscoverer must in this case implement the interface ValidationProviderResolver: ValidationProviderResolver interface public interface ValidationProviderResolver { /** * Returns a list of ValidationProviders available in the runtime environment. * * @return list of validation providers. */ List<ValidationProvider<?>> getValidationProviders(); }
<classname>MessageInterpolator</classname> already discussed the default message interpolation algorithm. If you have special requirements for your message interpolation you can provide a custom interpolator using Configuration.messageInterpolator(). This message interpolator will be shared by all validators generated by the ValidatorFactory created from this Configuration(see ). Providing a custom MessageInterpolator Configuration<?> configuration = Validation.byDefaultProvider().configure(); ValidatorFactory factory = configuration .messageInterpolator(new ContextualMessageInterpolator(configuration.getDefaultMessageInterpolator())) .buildValidatorFactory(); Validator validator = factory.getValidator(); It is recommended that MessageInterpolator implementations delegate final interpolation to the Bean Validation default MessageInterpolator to ensure standard Bean Validation interpolation rules are followed. The default implementation is accessible through Configuration.getDefaultMessageInterpolator().
<classname>TraversableResolver</classname> The usage of the TraversableResolver has so far not been discussed. The idea is that in some cases, the state of a property should not be accessed. The most obvious example for that is a lazy loaded property or association of a Java Persistence provider. Validating this lazy property or association would mean that its state would have to be accessed triggering a load from the database. Bean Validation controls which property can and cannot be accessed via the TraversableResolver interface (see ). TraversableResolver interface /** * Contract determining if a property can be accessed by the Bean Validation provider * This contract is called for each property that is being either validated or cascaded. * * A traversable resolver implementation must be thread-safe. * */ public interface TraversableResolver { /** * Determine if the Bean Validation provider is allowed to reach the property state * * @param traversableObject object hosting <code>traversableProperty</code> or null * if validateValue is called * @param traversableProperty the traversable property. * @param rootBeanType type of the root object passed to the Validator. * @param pathToTraversableObject path from the root object to * <code>traversableObject</code> * (using the path specification defined by Bean Validator). * @param elementType either <code>FIELD</code> or <code>METHOD</code>. * * @return <code>true</code> if the Bean Validation provider is allowed to * reach the property state, <code>false</code> otherwise. */ boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType); /** * Determine if the Bean Validation provider is allowed to cascade validation on * the bean instance returned by the property value * marked as <code>@Valid</code>. * Note that this method is called only if isReachable returns true for the same set of * arguments and if the property is marked as <code>@Valid</code> * * @param traversableObject object hosting <code>traversableProperty</code> or null * if validateValue is called * @param traversableProperty the traversable property. * @param rootBeanType type of the root object passed to the Validator. * @param pathToTraversableObject path from the root object to * <code>traversableObject</code> * (using the path specification defined by Bean Validator). * @param elementType either <code>FIELD</code> or <code>METHOD</code>. * * @return <code>true</code> if the Bean Validation provider is allowed to * cascade validation, <code>false</code> otherwise. */ boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType); } Hibernate Validator provides two TraversableResolvers out of the box which will be enabled automatically depending on your environment. The first is the DefaultTraversableResolver which will always return true for isReachable() and isTraversable(). The second is the JPATraversableResolver which gets enabled when Hibernate Validator gets used in combination with JPA 2. In case you have to provide your own resolver you can do so again using the Configuration object as seen in . Providing a custom TraversableResolver Configuration<?> configuration = Validation.byDefaultProvider().configure(); ValidatorFactory factory = configuration .traversableResolver(new MyTraversableResolver()) .buildValidatorFactory(); Validator validator = factory.getValidator();
<classname>ConstraintValidatorFactory</classname> Last but not least, there is one more configuration option to discuss, the ConstraintValidatorFactory. The default ConstraintValidatorFactory provided by Hibernate Validator requires a public no-arg constructor to instantiate ConstraintValidator instances (see ). Using a custom ConstraintValidatorFactory offers for example the possibility to use dependency injection in constraint implementations. The configuration of the custom factory is once more via the Configuration (). Providing a custom ConstraintValidatorFactory Configuration<?> configuration = Validation.byDefaultProvider().configure(); ValidatorFactory factory = configuration .constraintValidatorFactory(new IOCConstraintValidatorFactory()) .buildValidatorFactory(); Validator validator = factory.getValidator(); The interface you have to implement is: ConstraintValidatorFactory interface public interface ConstraintValidatorFactory { /** * @param key The class of the constraint validator to instantiate. * * @return A constraint validator instance of the specified class. */ <T extends ConstraintValidator<?,?>> T getInstance(Class<T> key); } Any constraint implementation relying on ConstraintValidatorFactory behaviors specific to an implementation (dependency injection, no no-arg constructor and so on) are not considered portable. ConstraintValidatorFactory should not cache instances as the state of each instance can be altered in the initialize method.
././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/gettingstarted.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/gettingstart0000644000175000017500000002473111262172500033416 0ustar twernertwerner Getting started This chapter will show you how to get started with Hibernate Validator, the reference implementation (RI) of Bean Validation. For the following quickstart you need: A JDK >= 5 Apache Maven An Internet connection (Maven has to download all required libraries) A properly configured remote repository. Add the following to your settings.xml: Configuring the JBoss Maven repository in <filename>settings.xml</filename> <repositories> <repository> <id>jboss</id> <url>http://repository.jboss.com/maven2</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> More information about settings.xml can be found in the Maven Local Settings Model.
Setting up a new Maven project Start by creating new Maven project using the Maven archetype plugin as follows: Using Maven's archetype plugin to create a sample project using Hibernate Validator mvn archetype:generate \ -DarchetypeCatalog=http://repository.jboss.com/maven2/archetype-catalog.xml \ -DgroupId=com.mycompany \ -DartifactId=beanvalidation-gettingstarted \ -Dversion=1.0-SNAPSHOT \ -Dpackage=com.mycompany When presented with the list of available archetypes in the JBoss Maven Repository select the hibernate-validator-quickstart-archetype. After Maven has downloaded all dependencies confirm the settings by just pressing enter. Maven will create your project in the directory beanvalidation-gettingstarted. Change into this directory and run: mvn testMaven will compile the example code and run the implemented unit tests. Let's have a look at the actual code.
Applying constraints Open the project in the IDE of your choice and have a look at the class Car: Class Car annotated with constraints package com.mycompany; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } //getters and setters ... } @NotNull, @Size and @Min are so-called constraint annotations, that we use to declare constraints, which shall be applied to the fields of a Car instance: manufacturer shall never be null licensePlate shall never be null and must be between 2 and 14 characters long seatCount shall be at least 2.
Validating constraints To perform a validation of these constraints, we use a Validator instance. Let's have a look at the CarTest class: Class CarTest showing validation examples package com.mycompany; import static org.junit.Assert.*; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.junit.BeforeClass; import org.junit.Test; public class CarTest { private static Validator validator; @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Test public void manufacturerIsNull() { Car car = new Car(null, "DD-AB-123", 4); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); } @Test public void licensePlateTooShort() { Car car = new Car("Morris", "D", 4); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals("size must be between 2 and 14", constraintViolations.iterator().next().getMessage()); } @Test public void seatCountTooLow() { Car car = new Car("Morris", "DD-AB-123", 1); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals("must be greater than or equal to 2", constraintViolations.iterator().next().getMessage()); } @Test public void carIsValid() { Car car = new Car("Morris", "DD-AB-123", 2); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(0, constraintViolations.size()); } } In the setUp() method we get a Validator instance from the ValidatorFactory. A Validator instance is thread-safe and may be reused multiple times. For this reason we store it as field of our test class. We can use the Validator now to validate the different car instances in the test methods. The validate() method returns a set of ConstraintViolation instances, which we can iterate in order to see which validation errors occurred. The first three test methods show some expected constraint violations: The @NotNull constraint on manufacturer is violated in manufacturerIsNull() The @Size constraint on licensePlate is violated in licensePlateTooShort() The @Min constraint on seatCount is violated in seatCountTooLow() If the object validates successfully, validate() returns an empty set. Note that we only use classes from the package javax.validation from the Bean Validation API. As we don't reference any classes of the RI directly, it would be no problem to switch to another implementation of the API, should that need arise.
Where to go next? That concludes our 5 minute tour through the world of Hibernate Validator. Continue exploring the code or look at further examples referenced in . To get a deeper understanding of the Bean Validation just continue reading.. In case your application has specific validation requirements have a look at .
././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/integration.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/integration.0000644000175000017500000002145511262172500033300 0ustar twernertwerner Integration with other frameworks Hibernate Validator is intended to be used to implement multi-layered data validation, where constraints are expressed in a single place (the annotated domain model) and checked in various different layers of the application.
Database schema-level validation Out of the box, Hibernate Annotations (as of Hibernate 3.5.x) will translate the constraints you have defined for your entities into mapping metadata. For example, if a property of your entity is annotated @NotNull, its columns will be declared as not null in the DDL schema generated by Hibernate. If, for some reason, the feature needs to be disabled, set hibernate.validator.apply_to_ddl to false. See also . You can also limit the DDL constraint generation to a subset of the defined constraints by setting the property org.hibernate.validator.group.ddl. The property specifies the comma seperated, fully specified classnames of the groups a constraint has to be part of in order to be considered for DDL schema generation.
ORM integration Hibernate Validator integrates with both Hibernate and all pure Java Persistence providers.
Hibernate event-based validation Hibernate Validator has a built-in Hibernate event listener - org.hibernate.cfg.beanvalidation.BeanValidationEventListener - which is part of Hibernate Annotations (as of Hibernate 3.5.x). Whenever a PreInsertEvent, PreUpdateEvent or PreDeleteEvent occurs, the listener will verify all constraints of the entity instance and throw an exception if any constraint is violated. Per default objects will be checked before any inserts or updates are made by Hibernate. Pre deletion events will per default not trigger a validation. You can configure the groups to be validated per event type using the properties javax.persistence.validation.group.pre-persist, javax.persistence.validation.group.pre-update and javax.persistence.validation.group.pre-remove. The values of these properties are the comma seperated, fully specified class names of the groups to validate. shows the default values for these properties. In this case they could also be omitted. On constraint violation, the event will raise a runtime ConstraintViolationException which contains a set of ConstraintViolations describing each failure. If Hibernate Validator is present in the classpath, Hibernate Annotations (or Hibernate EntityManager) will use it transparently. To avoid validation even though Hibernate Validator is in the classpath set javax.persistence.validation.mode to none. If the beans are not annotated with validation annotations, there is no runtime performance cost. In case you need to manually set the event listeners for Hibernate Core, use the following configuration in hibernate.cfg.xml: Manual configuration of <classname>BeanValidationEvenListener</classname> <hibernate-configuration> <session-factory> ... <property name="javax.persistence.validation.group.pre-persist">javax.validation.Default</property> <property name="javax.persistence.validation.group.pre-update">javax.validation.Default</property> <property name="javax.persistence.validation.group.pre-remove"></property> </session-factory> <event type="pre-update"> <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/> </event> <event type="pre-insert"> <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/> </event> <event type="pre-delete"> <listener class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"/> </event> </hibernate-configuration>
JPA If you are using JPA 2 and Hibernate Validator is in the classpath the JPA2 specification requires that Bean Validation gets enabled. The properties javax.persistence.validation.group.pre-persist, javax.persistence.validation.group.pre-update and javax.persistence.validation.group.pre-remove as described in can in this case be configured in persistence.xml. persistence.xml also defines a node validation-mode while can be set to AUTO, CALLBACK, NONE. The default is AUTO. In a JPA 1 you will have to create and register Hibernate Validator yourself. In case you are using Hibernate EntityManager you can add a customized version of the BeanValidationEventListener described in to your project and register it manually.
Presentation layer validation When working with JSF2 or JBoss Seam and Hibernate Validator (Bean Validation) is present in the runtime environment validation is triggered for every field in the application. shows an example of the f:validateBean tag in a JSF page. For more information refer to the Seam documentation or the JSF 2 specification. Usage of Bean Validation within JSF2 <h:form> <f:validateBean> <h:inputText value=”#{model.property}” /> <h:selectOneRadio value=”#{model.radioProperty}” > ... </h:selectOneRadio> <!-- other input components here --> </f:validateBean> </h:form>
libhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/preface.xml0000644000175000017500000000626611262172500033106 0ustar twernertwerner Preface Validating data is a common task that occurs throughout any application, from the presentation layer to the persistence layer. Often the same validation logic is implemented in each layer, proving time consuming and error-prone. To avoid duplication of these validations in each layer, developers often bundle validation logic directly into the domain model, cluttering domain classes with validation code which is really metadata about the class itself. JSR 303 - Bean Validation - defines a metadata model and API for entity validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML. The API is not tied to a specific application tier or programming model. It is specifically not tied to either the web tier or the persistence tier, and is available for both server-side application programming, as well as rich client Swing application developers. Hibernate Validator is the reference implementation of this JSR. ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/introduction.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/introduction0000644000175000017500000000413011262172500033407 0ustar twernertwerner Introduction
What is it about?
Installation
Prerequisites
Running Bean Validation RI with downloaded JARs
Running Bean Validation RI using Maven
Building Bean Validation RI from the sources
././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/customconstraints.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/customconstr0000644000175000017500000004435411271353571033456 0ustar twernertwerner Creating custom constraints Though the Bean Validation API defines a whole set of standard constraint annotations one can easily think of situations in which these standard annotations won't suffice. For these cases you are able to create custom constraints tailored to your specific validation requirements in a simple manner.
Creating a simple constraint To create a custom constraint, the following three steps are required: Create a constraint annotation Implement a validator Define a default error message
The constraint annotation Let's write a constraint annotation, that can be used to express that a given string shall either be upper case or lower case. We'll apply it later on to the licensePlate field of the Car class from to ensure, that the field is always an upper-case string. First we need a way to express the two case modes. We might use String constants, but a better way to go is to use a Java 5 enum for that purpose: Enum <classname>CaseMode</classname> to express upper vs. lower case package com.mycompany; public enum CaseMode { UPPER, LOWER; } Now we can define the actual constraint annotation. If you've never designed an annotation before, this may look a bit scary, but actually it's not that hard: Defining CheckCase constraint annotation package com.mycompany; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.ConstraintPayload; @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = CheckCaseValidator.class) @Documented public @interface CheckCase { String message() default "{com.mycompany.constraints.checkcase}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; CaseMode value(); } An annotation type is defined using the @interface keyword. All attributes of an annotation type are declared in a method-like manner. The specification of the Bean Validation API demands, that any constraint annotation defines an attribute message that returns the default key for creating error messages in case the constraint is violated an attribute groups that allows the specification of validation groups, to which this constraint belongs (see ). This must default to an empty array of type Class<?>. an attribute payload that can be used by clients of the Bean Validation API to asign custom payload objects to a constraint. This attribute is not used by the API itself. An examle for a custom payload could be the definition of a severity. public class Severity { public static class Info extends ConstraintPayload {}; public static class Error extends ConstraintPayload {}; } public class ContactDetails { @NotNull(message="Name is mandatory", payload=Severity.Error.class) private String name; @NotNull(message="Phone number not specified, but not mandatory", payload=Severity.Info.class) private String phoneNumber; // ... }Now a client can after the validation of a ContactDetails instance access the severity of a constraint using ConstraintViolation.getConstraintDescriptor().getPayload() and adjust its behaviour depending on the severity. Besides those three mandatory attributes (messge, groups and payload) we add another one allowing for the required case mode to be specified. The name value is a special one, which can be omitted upon using the annotation, if it is the only attribute specified, as e.g. in @CheckCase(CaseMode.UPPER). In addition we annotate the annotation type with a couple of so-called meta annotations: @Target({ METHOD, FIELD, ANNOTATION_TYPE }): Says, that methods, fields and annotation declarations may be annotated with @CheckCase (but not type declarations e.g.) @Retention(RUNTIME): Specifies, that annotations of this type will be available at runtime by the means of reflection @Constraint(validatedBy = CheckCaseValidator.class): Specifies the validator to be used to validate elements annotated with @CheckCase @Documented: Says, that the use of @CheckCase will be contained in the JavaDoc of elements annotated with it
The constraint validator Next, we need to implement a constraint validator, that's able to validate elements with a @CheckCase annotation. To do so, we implement the interface ConstraintValidator as shown below: Implementing a constraint validator for the constraint <classname>CheckCase</classname> package com.mycompany; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; public class CheckCaseValidator implements ConstraintValidator<CheckCase, String> { private CaseMode caseMode; public void initialize(CheckCase constraintAnnotation) { this.caseMode = constraintAnnotation.value(); } public boolean isValid(String object, ConstraintValidatorContext constraintContext) { if (object == null) return true; if (caseMode == CaseMode.UPPER) return object.equals(object.toUpperCase()); else return object.equals(object.toLowerCase()); } } The ConstraintValidator interface defines two type parameters, which we set in our implementation. The first one specifies the annotation type to be validated (in our example CheckCase), the second one the type of elements, which the validator can handle (here String). In case a constraint annotation is allowed at elements of different types, a ConstraintValidator for each allowed type has to be implemented and registered at the constraint annotation as shown above. The implementation of the validator is straightforward. The initialize() method gives us access to the attribute values of the annotation to be validated. In the example we store the CaseMode in a field of the validator for further usage. In the isValid() method we implement the logic, that determines, whether a String is valid according to a given @CheckCase annotation or not. This decision depends on the case mode retrieved in initialize(). As the Bean Validation specification recommends, we consider null values as being valid. If null is not a valid value for an element, it should be annotated with @NotNull explicitely. The passed-in ConstraintValidatorContext could be used to raise any custom validation errors, but as we are fine with the default behavior, we can ignore that parameter for now.
The error message Finally we need to specify the error message, that shall be used, in case a @CheckCase constraint is violated. To do so, we add the following to our custom ValidationMessages.properties (see also ) Defining a custom error message for the <classname>CheckCase</classname> constraint com.mycompany.constraints.CheckCase.message=Case mode must be {value}. If a validation error occurs, the validation runtime will use the default value, that we specified for the message attribute of the @CheckCase annotation to look up the error message in this file.
Using the constraint Now that our first custom constraint is completed, we can use it in the Car class from the chapter to specify that the licensePlate field shall only contain upper-case strings: Applying the <classname>CheckCase</classname> constraint package com.mycompany; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) private String licensePlate; @Min(2) private int seatCount; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } //getters and setters ... } Finally let's demonstrate in a little test that the @CheckCase constraint is properly validated: Testcase demonstrating the <classname>CheckCase</classname> validation package com.mycompany; import static org.junit.Assert.*; import java.util.Set; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import javax.validation.ValidatorFactory; import org.junit.BeforeClass; import org.junit.Test; public class CarTest { private static Validator validator; @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Test public void testLicensePlateNotUpperCase() { Car car = new Car("Morris", "dd-ab-123", 4); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals( "Case mode must be UPPER.", constraintViolations.iterator().next().getMessage()); } @Test public void carIsValid() { Car car = new Car("Morris", "DD-AB-123", 4); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(0, constraintViolations.size()); } }
Constraint composition Looking at the licensePlate field of the Car class in , we see three constraint annotations already. In complexer scenarios, where even more constraints could be applied to one element, this might become a bit confusing easily. Furthermore, if we had a licensePlate field in another class, we would have to copy all constraint declarations to the other class as well, violating the DRY principle. This problem can be tackled using compound constraints. In the following we create a new constraint annotation @ValidLicensePlate, that comprises the constraints @NotNull, @Size and @CheckCase: Creating a composing constraint <classname>ValidLicensePlate</classname> package com.mycompany; import static java.lang.annotation.ElementType.*; import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.Documented; import java.lang.annotation.Retention; import java.lang.annotation.Target; import javax.validation.Constraint; import javax.validation.ConstraintPayload; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @NotNull @Size(min = 2, max = 14) @CheckCase(CaseMode.UPPER) @Target( { METHOD, FIELD, ANNOTATION_TYPE }) @Retention(RUNTIME) @Constraint(validatedBy = {}) @Documented public @interface ValidLicensePlate { String message() default "{com.mycompany.constraints.validlicenseplate}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; } To do so, we just have to annotate the constraint declaration with its comprising constraints (btw. that's exactly why we allowed annotation types as target for the @CheckCase annotation). As no additional validation is required for the @ValidLicensePlate annotation itself, we don't declare a validator within the @Constraint meta annotation. Using the new compound constraint at the licensePlate field now is fully equivalent to the previous version, where we declared the three constraints directly at the field itself: Application of composing constraint <classname>ValidLicensePlate</classname> package com.mycompany; public class Car { @ValidLicensePlate private String licensePlate; //... } The set of ConstraintViolations retrieved when validating a Car instance will contain an entry for each violated composing constraint of the @ValidLicensePlate constraint. If you rather prefer a single ConstraintViolation in case any of the composing constraints is violated, the @ReportAsSingleViolation meta constraint can be used as follows: Usage of <classname>@ReportAsSingleViolation</classname> //... @ReportAsSingleViolation public @interface ValidLicensePlate { String message() default "{com.mycompany.constraints.validlicenseplate}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/furtherreading.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/furtherreadi0000644000175000017500000000512411262172500033356 0ustar twernertwerner Further reading Last but not least, a few pointers to further information. A great source for examples is the Bean Validation TCK which can is available for anonymous access in the Hibernate SVN repository. Alternatively you can view the tests using Hibernate's fisheye installation. The JSR 303 specification itself is also a great way to deepen your understanding of Bean Validation resp. Hibernate Validator. If you have any furhter questions to Hibernate Validator or want to share some of your use cases have a look at the Hibernate Validator Wiki and the Hibernate Validator Forum. In case you would like to report a bug use Hibernate's Jira instance. Feedback is always welcome! ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/xmlconfiguration.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/xmlconfigura0000644000175000017500000002712511262172500033375 0ustar twernertwerner XML configuration
<filename>validation.xml</filename> The key to enable XML configuration for Hibernate Validator is the file validation.xml. If this file exists in the classpath its configuration will be applied when the ValidationFactory gets created. shows a model view of the xsd valiation.xml has to adhere to. validation-configuration-1.0.xsd shows the several configuration options of validation.xml. validation.xml <validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration"> <default-provider>org.hibernate.validator.HibernateValidator</default-provider> <message-interpolator>org.hibernate.validator.engine.ResourceBundleMessageInterpolator</message-interpolator> <traversable-resolver>org.hibernate.validator.engine.resolver.DefaultTraversableResolver</traversable-resolver> <constraint-validator-factory>org.hibernate.validator.engine.ConstraintValidatorFactoryImpl</constraint-validator-factory> <constraint-mapping>/constraints-car.xml</constraint-mapping> <property name="prop1">value1</property> <property name="prop2">value2</property> </validation-config> There can only be one validation.xml in the classpath. If more than one is found an exception is thrown. All settings shown in the validation.xml are optional and in the case of show the defaults used within Hibernate Validator. The node default-provider allows to choose the Bean Validation provider. This is useful if there is more than one provider in the classpath. message-interpolator, traversable-resolver and constraint-validator-factory allow to customize the javax.validation.MessageInterpolator, javax.validation.TraversableResolver resp. javax.validation.ConstraintValidatorFactory. The same configuration options are also available programmatically through the javax.validation.Configuration. In fact XML configuration will be overriden by values explicitly specified via the API. It is even possible to ignore the XML configuration completely via Configuration.ignoreXmlConfiguration(). See also . Via the constraint-mapping you can list an arbitrary number of additional XML files containing the actual constraint configuration. See . Last but not least, you can specify provider specific properties via the property nodes. Hibernate Validator does currently not make use of any custom properties.
Mapping constraints Expressing constraints in XML is possible via files adhering to the xsd seen in . Note that these mapping files are only processed if listed via constraint-mapping in your validation.xml. validation-mapping-1.0.xsd shows how our classes Car and RentalCar from resp. could be mapped in XML. constraints-car.xml <constraint-mappings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/mapping validation-mapping-1.0.xsd" xmlns="http://jboss.org/xml/ns/javax/validation/mapping"> <default-package>org.hibernate.validator.quickstart</default-package> <bean class="Car" ignore-annotations="true"> <field name="manufacturer"> <constraint annotation="javax.validation.constraints.NotNull"/> </field> <field name="licensePlate"> <constraint annotation="javax.validation.constraints.NotNull"/> </field> <field name="seatCount"> <constraint annotation="javax.validation.constraints.Min"> <element name="value">2</element> </constraint> </field> <field name="driver"> <valid/> </field> <getter name="passedVehicleInspection" ignore-annotations="true"> <constraint annotation="javax.validation.constraints.AssertTrue"> <message>The car has to pass the vehicle inspection first</message> <groups> <value>CarChecks</value> </groups> <element name="max">10</element> </constraint> </getter> </bean> <bean class="RentalCar" ignore-annotations="true"> <class ignore-annotations="true"> <group-sequence> <value>RentalCar</value> <value>CarChecks</value> </group-sequence> </class> </bean> <constraint-definition annotation="org.mycompany.CheckCase" include-existing-validator="false"> <validated-by include-existing-validators="false"> <value>org.mycompany.CheckCaseValidator</value> </validated-by> </constraint-definition> </constraint-mappings> The XML configuration is closely mirroring the programmatic API. For this reason it should suffice to just add some comments. default-package is used for all fields where a classname is expected. If the specified class is not fully qualified the configured default package will be used. Every mapping file can then have several bean nodes, each describing the constraints on the entity with the specified class name. A given entity can only be configured once across all configuration files. If the same class is configured more than once an exception is thrown. Settings ignore-annotations to true means that constraint annotations placed on the configured bean are ignored. The default for this value is true. ignore-annotations is also available for the nodes class, fields and getter. If not explicitly specified on these levels the configured bean value applies. Otherwise do the nodes class, fields and getter determine on which level the constraints are placed (see ). The constraint node is then used to add a constraint on the corresponding level. Each constraint definition must define the class via the annotation attribute. The constraint attributes required by the Bean Validation specification (message, groups and payload) have dedicated nodes. All other constraint specific attributes are configured using the the element node. The class node also allows to reconfigure the default group sequence (see ) via the group-sequence node. Last but not least, the list of ConstraintValidators associated to a given constraint can be altered via the constraint-definition node. The annotation attribute represents the constraint annotation being altered. The validated-by elements represent the (ordered) list of ConstraintValidator implementations associated to the constraint. If include-existing-validator is set to false, validators defined on the constraint annotation are ignored. If set to true, the list of ConstraintValidators described in XML are concatenated to the list of validators described on the annotation.
././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootlibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/usingvalidator.xmllibhibernate-validator-java-4.0.2.GA/hibernate-validator/src/main/docbook/en-US/modules/usingvalidat0000644000175000017500000013523011271351071033370 0ustar twernertwerner Validation step by step In this chapter we will see in more detail how to use Hibernate Validator to validate constraints for a given entity model. We will also learn which default constraints the Bean Validation specification provides and which additional constraints are only provided by Hibernate Validator. Let's start with how to add constraints to an entity.
Defining constraints Constraints in Bean Validation are expressed via Java annotations. In this section we show how to annotate an object model with these annotations. We have to differentiate between three different type of constraint annotations - field-, property-, and class-level annotations. Not all constraints can be placed on all of these levels. In fact, none of the default constraints defined by Bean Validation can be placed at class level. The java.lang.annotation.Target annotation in the constraint annotation itself determines on which elements a constraint can be placed. See for more information.
Field-level constraints Constraints can be expressed by annotating a field of a class. shows a field level configuration example: Field level constraint package com.mycompany; import javax.validation.constraints.NotNull; public class Car { @NotNull private String manufacturer; @AssertTrue private boolean isRegistered; public Car(String manufacturer, boolean isRegistered) { super(); this.manufacturer = manufacturer; this.isRegistered = isRegistered; } } When using field level constraints field access strategy is used to access the value to be validated. This means the instance variable directly independed of the access type. The access type (private, protected or public) does not matter. Static fields and properties cannot be validated.
Property-level constraints If your model class adheres to the JavaBeans standard, it is also possible to annotate the properties of a bean class instead of its fields. uses the same entity as in , however, property level constraints are used. The property's getter method has to be annotated, not its setter. Property level constraint package com.mycompany; import javax.validation.constraints.AssertTrue; import javax.validation.constraints.NotNull; public class Car { private String manufacturer; private boolean isRegistered; public Car(String manufacturer, boolean isRegistered) { super(); this.manufacturer = manufacturer; this.isRegistered = isRegistered; } @NotNull public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } @AssertTrue public boolean isRegistered() { return isRegistered; } public void setRegistered(boolean isRegistered) { this.isRegistered = isRegistered; } } When using property level constraints property access strategy is used to access the value to be validated. This means the bean validation provider accesses the state via the property accessor method. It is recommended to stick either to field or property annotation within one class. It is not recommended to annotate a field and the accompanying getter method as this would cause the field to be validated twice.
Class-level constraints Last but not least, a constraint can also be placed on class level. When a constraint annotation is placed on this level the class instance itself passed to the ConstraintValidator. Class level constraints are useful if it is necessary to inspect more than a single property of the class to validate it or if a correlation between different state variables has to be evaluated. In we add the property passengers to the class Car. We also add the constraint PassengerCount on the class level. We will later see how we can actually create this custom constraint (see ). For now we it is enough to know that PassengerCount will ensure that there cannot be more passengers in a car than there are seats. Class level constraint package com.mycompany; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; @PassengerCount public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; private List<Person> passengers; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } //getters and setters ... }
Constraint inheritance When validating an object that implements an interface or extends another class, all constraint annotations on the implemented interface and parent class apply in the same manner as the constraints specified on the validated object itself. To make things clearer let's have a look at the following example: Constraint inheritance using RentalCar package com.mycompany; import javax.validation.constraints.NotNull; public class RentalCar extends Car { private String rentalStation; public RentalCar(String manufacturer, String rentalStation) { super(manufacturer); this.rentalStation = rentalStation; } @NotNull public String getRentalStation() { return rentalStation; } public void setRentalStation(String rentalStation) { this.rentalStation = rentalStation; } } Our well-known class Car from is now extended by RentalCar with the additional property rentalStation. If an instance of RentalCar is validated, not only the @NotNull constraint on rentalStation is validated, but also the constraint on manufacturer from the parent class. The same would hold true, if Car were an interface implemented by RentalCar. Constraint annotations are aggregated if methods are overridden. If RentalCar would override the getManufacturer() method from Car any constraints annotated at the overriding method would be evaluated in addition to the @NotNull constraint from the super-class.
Object graphs The Bean Validation API does not only allow to validate single class instances but also complete object graphs. To do so, just annotate a field or property representing a reference to another object with @Valid. If the parent object is validated, all referenced objects annotated with @Valid will be validated as well (as will be their children etc.). See . Class Person package com.mycompany; import javax.validation.constraints.NotNull; public class Person { @NotNull private String name; public Person(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } Adding a driver to the car package com.mycompany; import javax.validation.Valid; import javax.validation.constraints.NotNull; public class Car { @NotNull @Valid private Person driver; public Car(Person driver) { this.driver = driver; } //getters and setters ... } If an instance of Car is validated, the referenced Person object will be validated as well, as the driver field is annotated with @Valid. Therefore the validation of a Car will fail if the name field of the referenced Person instance is null. Object graph validation also works for collection-typed fields. That means any attributes that are arrays implement java.lang.Iterable (especially Collection, List and Set) implement java.util.Map can be annotated with @Valid, which will cause each contained element to be validated, when the parent object is validated. Car with a list of passengers package com.mycompany; import java.util.ArrayList; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotNull; public class Car { @NotNull @Valid private List<Person> passengers = new ArrayList<Person>(); public Car(List<Person> passengers) { this.passengers = passengers; } //getters and setters ... } If a Car instance is validated, a ConstraintValidation will be created, if any of the Person objects contained in the passengers list has a null name. null values are getting ignored when validating object graphs.
Validating constraints The Validator interface is the main entry point to Bean Validation. In we will first show how to obtain an Validator instance. Afterwards we will learn how to use the different methods of the Validator interface.
Obtaining a <classname>Validator</classname> instance The first step towards validating an entity instance is to get hold of a Validator instance. The road to this instance leads via the Validation class and a ValidatorFactory. The easiest way is to use the static Validation.buildDefaultValidatorFactory() method: Validation.buildDefaultValidatorFactory() ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); For other ways of obtaining a Validator instance see . For now we just want to see how we can use the Validator instance to validate entity instances.
Validator methods The Validator interface contains three methods that can be used to either validate entire entities or just a single properties of the entity. All three methods return a Set<ConstraintViolation>. The set is empty, if the validation succeeds. Otherwise a ConstraintViolation instance is added for each violated constraint. All the validation methods have a var-args parameter which can be used to specify, which validation groups shall be considered when performing the validation. If the parameter is not specified the default validation group (javax.validation.Default) will be used. We will go into more detail on the topic of validation groups in
<methodname>validate</methodname> Use the validate() method to perform validation of all constraints of a given entity instance (see ). Usage of <methodname>Validator.validate()</methodname> ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); Validator validator = factory.getValidator(); Car car = new Car(null); Set<ConstraintViolation<Car>> constraintViolations = validator.validate(car); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
<methodname>validateProperty</methodname> With help of the validateProperty() a single named property of a given object can be validated. The property name is the JavaBeans property name. Usage of <methodname>Validator.validateProperty()</methodname> Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Car car = new Car(null); Set<ConstraintViolation<Car>> constraintViolations = validator.validateProperty(car, "manufacturer"); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); Validator.validateProperty is for example used in the integration of Bean Validation into JSF 2 (see ).
<methodname>validateValue</methodname> Using the validateValue() method you can check, whether a single property of a given class can be validated successfully, if the property had the specified value: Usage of <methodname>Validator.validateValue()</methodname> Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); Set<ConstraintViolation<Car>> constraintViolations = validator.validateValue(Car.class, "manufacturer", null); assertEquals(1, constraintViolations.size()); assertEquals("may not be null", constraintViolations.iterator().next().getMessage()); @Valid is not honored by validateProperty() or validateValue().
<classname>ConstraintViolation</classname> methods Now it is time to have a closer look at what a ConstraintViolation. Using the different methods of ConstraintViolation a lot of useful information about the cause of the validation failure can be determined. gives an overview of these methods: The various <classname>ConstraintViolation</classname> methods Method Usage Example (refering to ) getMessage() The interpolated error message. may not be null getMessageTemplate() The non-interpolated error message. {javax.validation.constraints.NotNull.message} getRootBean() The root bean being validated. car getRootBeanClass() The class of the root bean being validated. Car.class getLeafBean() If a bean constraint, the bean instance the constraint is applied on. If a property constraint, the bean instance hosting the property the constraint is applied on. car getPropertyPath() The property path to the value from root bean. getInvalidValue() The value failing to pass the constraint. passengers getConstraintDescriptor() Constraint metadata reported to fail.
Message interpolation As we will see in each constraint definition must define a default message descriptor. This message can be overridden at declaration time using the message attribute of the constraint. You can see this in . This message descriptors get interpolated when a constraint validation fails using the configured MessageInterpolator. The interpolator will try to resolve any message parameters, meaning string literals enclosed in braces. In order to resolve these parameters Hibernate Validator's default MessageInterpolator first recursively resolves parameters against a custom ResourceBundle called ValidationMessages.properties at the root of the classpath (It is up to you to create this file). If no further replacements are possible against the custom bundle the default ResourceBundle under /org/hibernate/validator/ValidationMessages.properties gets evaluated. If a replacement occurs against the default bundle the algorithm looks again at the custom bundle (and so on). Once no further replacements against these two resource bundles are possible remaining parameters are getting resolved against the attributes of the constraint to be validated. Since the braces { and } have special meaning in the messages they need to be escaped if they are used literally. The following The following rules apply: \{ is considered as the literal { \} is considered as the literal } \\ is considered as the literal \ If the default message interpolator does not fit your requirements it is possible to plug a custom MessageInterpolator when the ValidatorFactory gets created. This can be seen in .
Validating groups Groups allow you to restrict the set of constraints applied during validation. This makes for example wizard like validation possible where in each step only a specified subset of constraints get validated. The groups targeted are passed as var-args parameters to validate, validateProperty and validateValue. Let's have a look at an extended Car with Driver example. First we have the class Person () which has a @NotNull constraint on name. Since no group is specified for this annotation its default group is javax.validation.Default. When more than one group is requested, the order in which the groups are evaluated is not deterministic. If no group is specified the default group javax.validation.Default is assumed. Person public class Person { @NotNull private String name; public Person(String name) { this.name = name; } // getters and setters ... } Next we have the class Driver () extending Person. Here we are adding the properties age and hasDrivingLicense. In order to drive you must be at least 18 (@Min(18)) and you must have a driving license (@AssertTrue). Both constraints defined on these properties belong to the group DriverChecks. As you can see in the group DriverChecks is just a simple tagging interface. Using interfaces makes the usage of groups type safe and allows for easy refactoring. It also means that groups can inherit from each other via class inheritance. The Bean Validation specification does not enforce that groups have to be interfaces. Non interface classes could be used as well, but we recommend to stick to interfaces. Driver public class Driver extends Person { @Min(value = 18, message = "You have to be 18 to drive a car", groups = DriverChecks.class) public int age; @AssertTrue(message = "You first have to pass the driving test", groups = DriverChecks.class) public boolean hasDrivingLicense; public Driver(String name) { super( name ); } public void passedDrivingTest(boolean b) { hasDrivingLicense = b; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } Group interfaces public interface DriverChecks { } public interface CarChecks { } Last but not least we add the property passedVehicleInspection to the Car class () indicating whether a car passed the road worthy tests. Car public class Car { @NotNull private String manufacturer; @NotNull @Size(min = 2, max = 14) private String licensePlate; @Min(2) private int seatCount; @AssertTrue(message = "The car has to pass the vehicle inspection first", groups = CarChecks.class) private boolean passedVehicleInspection; @Valid private Driver driver; public Car(String manufacturer, String licencePlate, int seatCount) { this.manufacturer = manufacturer; this.licensePlate = licencePlate; this.seatCount = seatCount; } } Overall three different groups are used in our example. Person.name, Car.manufacturer, Car.licensePlate and Car.seatCount all belong to the Default group. Driver.age and Driver.hasDrivingLicense belong to DriverChecks and last but not least Car.passedVehicleInspection belongs to the group CarChecks. shows how passing different group combinations to the Validator.validate method result in different validation results. Drive away public class GroupTest { private static Validator validator; @BeforeClass public static void setUp() { ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); validator = factory.getValidator(); } @Test public void driveAway() { // create a car and check that everything is ok with it. Car car = new Car( "Morris", "DD-AB-123", 2 ); Set<ConstraintViolation<Car>> constraintViolations = validator.validate( car ); assertEquals( 0, constraintViolations.size() ); // but has it passed the vehicle inspection? constraintViolations = validator.validate( car, CarChecks.class ); assertEquals( 1, constraintViolations.size() ); assertEquals("The car has to pass the vehicle inspection first", constraintViolations.iterator().next().getMessage()); // let's go to the vehicle inspection car.setPassedVehicleInspection( true ); assertEquals( 0, validator.validate( car ).size() ); // now let's add a driver. He is 18, but has not passed the driving test yet Driver john = new Driver( "John Doe" ); john.setAge( 18 ); car.setDriver( john ); constraintViolations = validator.validate( car, DriverChecks.class ); assertEquals( 1, constraintViolations.size() ); assertEquals( "You first have to pass the driving test", constraintViolations.iterator().next().getMessage() ); // ok, John passes the test john.passedDrivingTest( true ); assertEquals( 0, validator.validate( car, DriverChecks.class ).size() ); // just checking that everything is in order now assertEquals( 0, validator.validate( car, Default.class, CarChecks.class, DriverChecks.class ).size() ); } } First we create a car and validate it using no explicit group. There are no validation errors, even though the property passedVehicleInspection is per default false. However, the constraint defined on this property does not belong to the default group. Next we just validate the CarChecks group which will fail until we make sure that the car passes the vehicle inspection. When we then add a driver to the car and validate against DriverChecks we get again a constraint violation due to the fact that the driver has not yet passed the driving test. Only after setting passedDrivingTest to true the validation against DriverChecks will pass. Last but not least, we show that all constraints are passing by validating against all defined groups.
Group sequences By default, constraints are evaluated in no particular order and this regardless of which groups they belong to. In some situations, however, it is useful to control the order of the constraints evaluation. In our example from we could for example require that first all default car constraints are passing before we check the road worthiness of the car. Finally before we drive away we check the actual driver constraints. In order to implement such an order one would define a new interface and annotate it with @GroupSequence defining the order in which the groups have to be validated. If at least one constraints fails in a sequenced group none of the constraints of the follwoing groups in the sequence get validated. Interface with @GroupSequence @GroupSequence({Default.class, CarChecks.class, DriverChecks.class}) public interface OrderedChecks { } Groups defining a sequence and groups composing a sequence must not be involved in a cyclic dependency either directly or indirectly, either through cascaded sequence definition or group inheritance. If a group containing such a circularity is evaluated, a GroupDefinitionException is raised. The usage of the new sequence could then look like in . Usage of a group sequence @Test public void testOrderedChecks() { Car car = new Car( "Morris", "DD-AB-123", 2 ); car.setPassedVehicleInspection( true ); Driver john = new Driver( "John Doe" ); john.setAge( 18 ); john.passedDrivingTest( true ); car.setDriver( john ); assertEquals( 0, validator.validate( car, OrderedChecks.class ).size() ); }
Redefining the default group sequence of a class The @GroupSequence annotation also fulfills a second purpose. It allows you to redefine what the Default group means for a given class. To redefine Default for a class, place a @GroupSequence annotation on the class. The defined groups in the annotation express the sequence of groups that substitute Default for this class. introduces a new class RentalCar with a redfined default group. With this definition the check for all three groups can be rewritten as seen in . RentalCar @GroupSequence({ RentalCar.class, CarChecks.class }) public class RentalCar extends Car { public RentalCar(String manufacturer, String licencePlate, int seatCount) { super( manufacturer, licencePlate, seatCount ); } } testOrderedChecksWithRedefinedDefault @Test public void testOrderedChecksWithRedefinedDefault() { RentalCar rentalCar = new RentalCar( "Morris", "DD-AB-123", 2 ); rentalCar.setPassedVehicleInspection( true ); Driver john = new Driver( "John Doe" ); john.setAge( 18 ); john.passedDrivingTest( true ); rentalCar.setDriver( john ); assertEquals( 0, validator.validate( rentalCar, Default.class, DriverChecks.class ).size() ); } Due to the fact that there cannot be a cyclic dependency in the group and group sequence definitions one cannot just add Default to the sequence redefining Default for a class. Instead the class itself should be added!
Built-in constraints Hibernate Validator implements all of the default constraints specified in Bean Validation as well as some custom ones. list all constraints available in Hibernate Validator. Built-in constraints Annotation Part of Bean Validation Specification Apply on Use Hibernate Metadata impact @AssertFalse yes field/property check that the annotated element is false. none @AssertTrue yes field/property check that the annotated element is true. none @DecimalMax yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. The annotated element must be a number whose value must be lower or equal to the specified maximum. The parameter value is the string representation of the max value according to the BigDecimal string representation. none @DecimalMin yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. The annotated element must be a number whose value must be higher or equal to the specified minimum. The parameter value is the string representation of the min value according to the BigDecimal string representation. none @Digits(integer=, fraction=) yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Check whether the property is a number having up to integer digits and fraction fractional digits. Define column precision and scale. @Email no field/property. Needs to be a string. Check whether the specified string is a valid email address. none @Future yes field/property. Supported types are java.util.Date and java.util.Calendar. Checks whether the annotated date is in the future. none @Length(min=, max=) no field/property. Needs to be a string. Validate that the annotated string is between min and max included. none @Max yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Checks whether the annotated value is less than or equal to the specified maximum. Add a check constraint on the column. @Min yes field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Check whether the annotated value is higher than or equal to the specified minimum. Add a check constraint on the column. @NotNull yes field/property Check that the annotated value is not null. Column(s) are not null. @NotEmpty no field/property. Needs to be a string. Check if the string is not null nor empty. none @Null yes field/property Check that the annotated value is null. none @Past yes field/property. Supported types are java.util.Date and java.util.Calendar. Checks whether the annotated date is in the past. none @Pattern(regex=, flag=) yes field/property. Needs to be a string. Check if the annotated string match the regular expression regex. none @Range(min=, max=) no field/property. Supported types are BigDecimal, BigInteger, String, byte, short, int, long and the respective wrappers of the primitive types. Check whether the annotated value lies between (inclusive) the specified minimum and maximum. none @Size(min=, max=) yes field/property. Supported types are String, Collection, Map and arrays. Check if the annotated element size is between min and max (inclusive). Column length will be set to max. @Valid yes field/property Perform validation recursively on the associated object. none
On top of the parameters indicated in each constraint supports the parameters message, groups and payload. This is a requirement of the Bean Validation specification. In some cases these built-in constraints will not fulfill your requirements. In this case you can literally in a minute write your own constraints. We will discuss this in
libhibernate-validator-java-4.0.2.GA/hibernate-validator/pom.xml0000644000175000017500000002576111275002113024537 0ustar twernertwerner hibernate-validator-parent org.hibernate 4.0.2.GA ../pom.xml 4.0.0 org.hibernate hibernate-validator Hibernate Validator site http://validator.hibernate.org javax.validation validation-api org.slf4j slf4j-api com.googlecode.jtype jtype 0.1.0 org.slf4j slf4j-log4j12 runtime true org.hibernate.java-persistence jpa-api 2.0.Beta-20090815 true org.testng testng test jdk15 test src/main/resources true src/main/xsd META-INF true org.apache.maven.plugins maven-source-plugin attach-sources jar org.codehaus.mojo jaxb2-maven-plugin xjc org.hibernate.validator.xml ${basedir}/target/generated-sources true org.apache.maven.plugins maven-surefire-plugin ${basedir}/src/test/suite/unit-tests.xml org.apache.maven.plugins maven-surefire-report-plugin generate-test-report test report-only ${project.build.directory}/surefire-reports test-report org.apache.maven.plugins maven-shade-plugin package shade com.googlecode.jtype:jtype com.googlecode.jtype org.hibernate.validator.jtype org.jboss.maven.plugins maven-jdocbook-plugin 2.2.0 true org.hibernate hibernate-jdocbook-style 2.0.0 jdocbook-style master.xml ${basedir}/src/main/docbook en-US ${basedir}/src/main/docbook/en-US/images pdf classpath:/xslt/org/hibernate/jdocbook/xslt/pdf.xsl hibernate_reference.pdf html_single classpath:/xslt/org/hibernate/jdocbook/xslt/xhtml-single.xsl index.html html classpath:/xslt/org/hibernate/jdocbook/xslt/xhtml.xsl index.html true saxon 1.72.0 - make-doc site resources generate org.jboss.maven.plugins maven-jdocbook-style-plugin 2.0.0 maven-assembly-plugin src/main/assembly/dist.xml make-assembly site assembly org.twdata.maven maven-cli-plugin 0.6.3.CR3 org.apache.maven.plugins maven-project-info-reports-plugin 2.0.1 jaxb 1.5 javax.xml.bind jaxb-api 2.1 com.sun.xml.bind jaxb-impl 2.1.3 libhibernate-validator-java-4.0.2.GA/pom.xml0000644000175000017500000002333411275002113020605 0ustar twernertwerner 4.0.0 org.hibernate hibernate-validator-parent pom 4.0.2.GA Hibernate Validator Parent http://validator.hibernate.org Hibernate's Bean Validation (JSR-303) reference implementation. epbernard Emmanuel Bernard emmanuel@hibernate.org JBoss, a division of Red Hat http://in.relation.to/Bloggers/Emmanuel hardy.ferentschik Hardy Ferentschik hferents@redhat.com JBoss, a division of Red Hat http://in.relation.to/Bloggers/Hardy hibernate-dev hibernate-dev@lists.jboss.org hibernate-validator hibernate-validator-archetype hibernate-validator-legacy hibernate-validator-tck-runner javax.validation validation-api 1.0.0.GA org.slf4j slf4j-api 1.5.6 org.slf4j slf4j-log4j12 1.5.6 org.testng testng 5.8 jdk15 org.apache.maven.wagon wagon-webdav 1.0-beta-2 org.apache.maven.plugins maven-jar-plugin 2.2 ${pom.artifactId} ${pom.version} ${pom.groupId} ${pom.groupId} ${pom.url} Bean Validation org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.5 1.5 org.apache.maven.plugins maven-surefire-plugin always true **/*Test.java maven-source-plugin attach-sources jar maven-assembly-plugin project org.apache.maven.plugins maven-release-plugin 2.0-beta-9 clean install true true true package site assembly:assembly deploy Hudson http://hudson.qa.jboss.com/hudson/job/beanvalidation JIRA http://opensource.atlassian.com/projects/hibernate/browse/HV 2007 Apache License, Version 2.0 license.txt scm:svn:https://svn.jboss.org/repos/hibernate/validator/tags/v4_0_2_GA http://fisheye.jboss.org/browse/Hibernate/validator/tags/v4_0_2_GA repository.jboss.org file://${maven.repository.root} snapshots.jboss.org JBoss Snapshot Repository dav:https://snapshots.jboss.org/maven2 org.apache.maven.plugins maven-project-info-reports-plugin 2.0.1 maven-javadoc-plugin html todo a ToDo: javadoc org.codehaus.mojo jxr-maven-plugin maven-surefire-plugin maven-clover-plugin org.apache.maven.plugins maven-pmd-plugin 1.5 org.codehaus.mojo taglist-maven-plugin org.codehaus.mojo changelog-maven-plugin org.codehaus.mojo changes-maven-plugin