![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ![]() | ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ![]() | ![]() | ![]() | ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]()
|
Release notesReleases ReleasesFor all releases prior to 0.9.6, the release notes can be found here. Release CVS
Release 0.9.9.1
New featuresAdded support for JOTM as transaction managerAdded support for JOTM as transaction co-ordinator. As a result, the following transaction managers are supported.
Improved Database.getIdentity(Object)The new implementation of the Database.getIdentity(Object) does not rely on the object being loaded in the same transaction anymore. It is even not required to have an active transaction. The identity will now be determined by calling the getters of the fields defined as identities in the mapping. If a mapping for the objects class could not be found a ClassNotPersistenceCapableException will be thrown. Null is only returned if the objects identity is null. Note:Care should be take if you previously used the null return of Database.getIdentity(Object) to determine if the object has been loaded in the current transaction before. Added helper method to close databaseAdded org.castor.jdo.util.JDOUtils.closeDatabase() method to close an open database instance without throwing exceptions. Any active transaction will be silently rolled back. BugsImproved 'caching' of Castor DTDs/XML SchemasAdded code to DTDResolver so that any URL/URIs against http://castor.org/... will be resolved against (local) files from within the Castor JAR(s). Problem obtaining underlying JDBC connectionsFixed a problem with obtaining the underlying JDBC connection used by Castor internally when there was no valud transaction. The code has been changed so that a PersistenceException will be thrown to indicate the lack of a valid transaction.
Release 0.9.9
Download & installation instructionsThis is the final 0.9.9 release, a feature release for Castor JDO and XML. Please note that we are providing the usual suspects (binaries, docs and sources) for this release at the Codehaus. We are currently planning for a Castor 1.0 release in about 8+ weeks, which we mainly see as a bug fix release and a one-time opportunity to get the HTML documentation into a better shape .. ;-). Please note that we have - in addition to the features added and bugs fixed as documented with 0.9.9M1 and 0.9.9M2 - started to makes substantial changes to the project documentation as follows: As mentioned above, these pages are work in progress and shall be expanded for the upcoming 1.0 release.
Release 0.9.9M2
Download & installation instructionsPlease note that we are providing the usual suspects (binaries, docs and sources) for this release at the Codehaus. We recommend, though, to download the complete package, as the HTML docs at the main Castor site has not been updated, and to build the documentation yourself. Preparations for the final release have started. Since the last release candidate, the following problem areas have been addressed.
Release 0.9.9M1
Download & installation instructionsPlease note that we are providing the usual suspects (binaries, docs and sources) for this release at the Codehaus. We recommend, though, to download the complete package, as the HTML docs at the main Castor site has not been updated, and to build the documentation yourself. ChangesSupport for polymorphismSupport for polymorphism has been completely rewritten, allowing you to load objects that are part of an extend relationship by their base types, with Castor JDO returning the actual (leaf) classes. With the following class hierarchy ...
it will be possible to execute OQL queries as follows: SELECT product FROM Product product and Castor JDO will return the actual Laptop and Server instances. For a complete set of code examples, please review src/tests/ctf/jdo/tc9x/TestPolymorphism.java. Updated MANIFEST filesBoth castor-0.x.y.jar and castor-0.x.y-xml.jar now carry an updated and up-to-date MANIFEST file. New featuresSupport for DerbySupport for Apache Derby (starting with release 10.1.1.0) has been added. For initial information about configuration of Castor JDO for the use with Apache Derby, please see src/tests/jdo/derby.xml. Known issues: Added support for distributed cachesAs of this release, four new cache types have been added: As some of these cache implementations allow you to use it in a distributed mode, this allows Castor JDO to be used in a clustered (multi-JVM) environment. In such an environment, Castor JDO wil make use of the underlying cache provider to replicate/distribute the cache content between the various JDOManager instances. Support for transient attribute for <sql> mappingsSupport for the transient attribute has been added to the <sql> element has been added. This allows you to define a field mapping as follows: <field name="prop1" type="string"> <sql name="prop_1" transient="true" /> <bind-xml name="property1" /> </field> allowing you to include a field for XML un-/marshalling, but exclude it from persistence. Support for typesafe enumerationsEnumerations are a common method for ensuring data integrity, both in software and in relational databases. As a platform for linking the two, we added support for persisting class fields whose type is a Java typesafe enumeration to Castor JDO. To use this new feature your typesafe enumeration should follow the enum pattern commonly used and provide a static valueOf(String) method. An enum of different kinds of computer equipment may look like: public class KindEnum { private static final Map KINDS = new HashMap(); public static final KindEnum MOUSE = new KindEnum("Mouse"); public static final KindEnum KEYBOARD = new KindEnum("Keyboard"); public static final KindEnum COMPUTER = new KindEnum("Computer"); public static final KindEnum PRINTER = new KindEnum("Printer"); public static final KindEnum MONITOR = new KindEnum("Monitor"); private final String _kind; private KindEnum(final String kind) { _kind = kind; KINDS.put(kind, this); } public static KindEnum valueOf(final String kind) { return (KindEnum) KINDS.get(kind); } public String toString() { return _kind; } } At your Product class you may want to have a property that tells you what kind of computer equipment a product is of. public class Product { private int _id; private String _name; private KindEnum _kind; public Product() { } public int getId() { return _id; } public void setId(int id) { _id = id; } public String getName() { return _name; } public void setName(String name) { _name = name; } public KindEnum getKind() { return _kind; } public void setKind(KindEnum kind) { _kind = kind; } } Your mapping for the Product class should be: <class name="Product" identity="id"> <description>Product with kind enum</description> <map-to table="enum_prod"/> <field name="id" type="integer"> <sql name="id" type="integer"/> </field> <field name="name" type="string"> <sql name="name" type="char"/> </field> <field name="kind" type="KindEnum"> <sql name="kind" type="char"/> </field> </class> To add this new feature we added an additional check when searching for field types. Like before Castor first searches for know types and thereafter for a mapping for the class you specified as type. If both of them do not match it now checks if the class specified as type is available at classpath and has a static valueOf(String) method. Only if all of this conditions are met it will be viewed as a valid mapping. Parametrized boolean->char type converterPre patch we always returned a boolean value even if the database contained a value which does not conform to the rules defined. This behaviour caused that we could load records with wrong values without problems but got a ObjectModifiedException when we tried to update these values as our update statment includes checking of all old values in the where clause of SQL statement. With the patch this behavier changes to strict checking if the loaded char/string value matches one of the boolean characters defined by conversion rule. If the value does not match a ClassCastException explaing the fail reason will be thrown. Performance improvementsSeveral code areas of Castor JDO have been severly refactored or rewritten from scratch, leading to some significantly improved runtime performance. This includes amongst others a reduced execution time when dealing with a large number of entities loaded as part of a single transaction, etc.
Release 0.9.7
Download & installation instructionsThis is the final 0.9.7. release, mainly a maintenance release. We are currently planning the next release which will be Castor 0.9.9, a feature release. ChangesMoved key generators to jdo.keygen packageWhilst this change is non-intrusive per se, please note that you might have to change a local castor.properties file if you happened to re-specify key generators in there. Fixed problem with multiple <database> configurationsSupport for multiple database configurations has been re-enabled.
Release 0.9.7M1
Download & installation instructionsPlease note that we are providing the usual suspect (binaries, docs and sources) for this release at the Codehaus. We recommend, though, to download the complete package, as the HTML docs at the main Castor site has not been updated, and to build the documentation yourself. ChangesSupport for JDBC proxy classesProxy classes for java.sql.Connection and java.sql.PreparedStatement instances have been added, to allow for complete and better JDBC statements to be output to the log files. As this might impose a performance penalty at run-time, we have added a new property to the Castor property file (castor.properties) to allow configuration of this feature. # True if JDBC proxy classes should be used to enable more detailed logging output of SQL # statements; false otherwise (logging will be turned off completely). # org.exolab.castor.persist.useProxy=true When disabled, no logging of SQL statements will occur al all. Castor and Java 5Several bugs have been fixed to allow use of Castor with a JDK 1.5. This mainly involved preventing compilation problems due to variable names et al. that were in conflict with new Java 5 naming conventions (e.g. use of enum as a variable name). Renamed JDO2 to JDOManagerJDO2 has been renamed to JDOManager. Please change your source code accordingly. Please note that - going forward - any bug fixes/enhancements will be committed against JDOManager only. Type of access mode constants changedThe type of the access mode constants (Shared / ReadOnly / Exclusive / DbLocked) defined in Database interface has changed from Default field typesIt is possible again - after disabling this feature in 0.9.6 - to not specify a type in a field mapping. By default, a field defined as such will have a type of 'java.lang.String'. AdditionsAddition of RSS feed for announcementsAn RSS feed has been added to the project documentation to allow users to be informed about additions/changes to Castor. This feed basically mirrors the news items posted to Specifying a binding file with the Source generator Ant taskSupport for specifying a binding file with the Castor Source Generator Ant Task has been added. Below is the example as provided with the 0.9.6 release notes extended to cover the specification of a binding file: <target name="castor:gen:src" depends="init" description="Generate Java source files from XSD."> <taskdef name="castor-srcgen" classname="org.exolab.castor.tools.ant.taskdefs.CastorSourceGenTask" classpathref="castor.class.path" /> <mkdir dir="${gen.src.d}" /> <castor-srcgen file="${schema.d}/books2.xsd" todir="${gen.src.d}" package="com.sourcebeat.castorlive.xmodel" types="j2" bindingfile="custom-binding.xml" warnings="false" /> </target> Problems fixedSince release 0.9.6, the following problem areas have been addressed.
Release 0.9.6
StatusThis is the final 0.9.6. release. We are currently planning the next milestone release which will be Castor 1.0. New Documentation- Creating Custom FieldHandlers SummaryFinal release. Since the third release candidate, the following problem areas have been addressed.
Release 0.9.6 RC3
Preparations for the final release have started. Since the second release candidate, the following problem areas have been addressed.
Release 0.9.6 RC2
Open issues:There's an issue with Castor finding mapping files within JARs when the path to the mapping file is specified relatively to the JDO configuration file. We are working on this, but as there's a workaround (using InputSources as mentioned on the mailing lists recently), we have decided to go ahead and not hold back this second release candidate. Details on this bug can be found here. Since the first release candidate, the following problem areas have been addressed.
Release 0.9.6 RC1
Download & installation instructionsPlease note that we are providing the usual suspect (binaries, docs and sources) for this release at the Exolab FTP server. We recommend, though, to download the complete package, as the HTML docs at the main Castor site have not been updated, and build the documentation yourself. ChangesFormat of the JDO configuration fileDue to various internal refactorings, we decide to change the syntax of the JDO configuration file, adding a new root element named <jdo-conf> and elements to declare transaction demarcation semantics. Here's a sample of Castor JDO running against mySQL (with local transactions). <?xml version="1.0"?> <!DOCTYPE jdo-conf PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version 1.0//EN" "http://castor.org/jdo-conf.dtd"> <jdo-conf> <database name="test" engine="mysql" > <driver url="jdbc:mysql://localhost/test" class-name="org.gjt.mm.mysql.Driver"> <param name="user" value="test" /> <param name="password" value="test" /> </driver> <mapping href="mapping.xml" /> </database> <transaction-demarcation mode="local" /> </jdo-conf> Configuration of JDBC DatasourcesWhen setting up JDBC DataSources to be used with Castor JDO, configuration of parameters now needs to occur as a sequence of <param> elements rather than one <params> element. This is to stream-line the way these JDBC resources are configured. What used to be <data-source class-name="com.sybase.jdbc2.jdbc.SybDataSource"> <params user="thomas" password="thomas" port-number="2048" server-name="Dual1" database-name="thomas" /> </data-source> before this release, now needs to be specifed as follows: <data-source class-name="com.sybase.jdbc2.jdbc.SybDataSource"> <param name="user" value="thomas" /> <param name="password" value="thomas" /> <param name="port-number" value="2048" /> <param name="server-name" value="Dual1" /> <param name="database-name" value="thomas" /> </data-source> Please note the use of hyphens in the naming of properties. In other words, in order for Castor to set the value of the portNumber property of the SybDataSource to '2048', please use the following <param> element <param name="port-number" value="2048" /> rather than <param name="portNumber" value="2048" /> as shown in the pooling documentation for previous releases. Transaction demarcationA new way of configuring transaction demarcation has been added. This configuration is now part of the main JDO configuration file (jdo-conf) and mandates the specification of the transaction demarcation used within your application. As part of this configuration file, the user has to specify which transaction demarcation to use. This can either be 'local' or 'global', and is supplied by the use of a <transaction-demarcation> element. Local ModeWhen using Castor JDO stand-alone and you want Castor to control transaction demarcation ('local' mode), please use this element as follows: <transaction-demarcation mode="local" /> Global ModeWhen running inside a J2EE application server, and you want to use container managed transactions ('global' transactions), please make sure you use this element as follows: <transaction-demarcation mode="global"> <transaction-manager name="jndi" /> </transaction-demarcation> In this mode, the XML element <transaction-manager> specifies the transaction manager that is used by your application server/web container to control these transactions. The following transaction managers are supported in Castor at the time of the release of Castor 0.9.6:
In addition to specifying the transaction manager name, it is possible to pass arbitrary name/value pairs to the transaction manager instance. Note:It should also be noted that "database pooling" must be enabled for the JDO instance when using the WAS v4 and v5 transaction managers, or the JDO "database" instance will fall outside the current transaction/thread, resulting in the error message "No transaction in progress for the current thread". For example: JDO myJdo = new JDO(); myJdo.setDatabasePooling( true ); Note: At the moment, only the JNDI transaction manager factory supports such an attribute. In this context, the jndiEnc attribute can be used to specify what JNDI ENC to use to lookup the transaction manager as shown below: <transaction-demarcation mode="global"> <transaction-manager name="jndi"> <param name="jndiEnc" value="java:comp/env/TransactionManager" /> </transaction-manager> </transaction-demarcation> Using timezone information when accessing date/time/timestamp dataCastor will use the JDBC ResultSet.getDate(int, Calendar) and related methods which take a Calendar object to specify the timezone of the data retrieved from the database when the timezone information is not already specified in the data; this ensures that the 'current' timezone is applied. The default time zone can be configured in the castor.properties file; see the configuration section for details on how to configure Castor with information about your default time zone. To change the timezone to a different timezone than the default, please set a (different) value on the org.exolab.castor.jdo.defaultTimeZone property: # Default time zone to apply to dates/times fetched from database fields, # if not already part of the data. Specify same format as in # java.util.TimeZone.getTimeZone, or an empty string to use the computer's # local time zone. # org.exolab.castor.jdo.defaultTimeZone= org.exolab.castor.jdo.defaultTimeZone=GMT+8:00 New featuresJDO configuration without a file and JDoConfFactoryAs part of this release, we have added a way to configure Castor JDO without the need to provide an XML configuration file. As such, JDO.setConfiguration(JdoConf) has been provided to pass in an instance of JdoConf. Too assist users of this new approach in creating JdoConf instances, please have a look at org.exolab.castor.jdo.util.JdoConfFactory. Resetting database configurationsIn order to clear all previously registered Castor Database configurations you can now call the new function org.exolab.castor.jdo.engine.DatabaseRegistry.clear(). This is for example usefull, if you want to log on using a user supplied login name and database connection. It is especially needed if it's possible to change the login password of the database login account in interactive applications. CacheManagerWith this release, we have decided to remove several methods related to clearing caches (partially) from Database(impl).java. Instead, we have created a new CacheManager class in the util package that can be obtained from a Database instance as follows: Database db = jdo.getDatabase(); CacheManager manager = db.getCacheManager(); Once such an instance has been obtained, cache content can be cleared (partially) using one of several CacheManager?.clearCache() methods. In addition, users might inquire about whether an object is currently cached (or not) by using CacheManager.isCached (Class, Object). Details about the functionality provided by this new class can be found in the HTML docs and/or Javadocs. OQL - Support for LIMIT/OFFSET clausesOn a selected number of RDBMS, Castor JDO now supports the use of LIMIT (and OFFSET clauses) as follows: OQLQuery query = db.getOQLQuery ("select a from Account order by id limit $1 offset $2"); query.bind (10); query.bind (5); OQLResults results = query.execute(); This will select accounts 6 to 15, given that numbers for account ids start at 1. As per this release, the following RDBMS have full/partial support for this new feature.
1) Oracle has full support for LIMIT/OFFSET clauses for release 8.1.6 and later. OQL - bind variables in combination with "IN" operatorsPreviously it was only possible to use OQL WHERE statements with "IN" operators of the following form: "... WHERE DNAME in list(1, 2, 3)" "... WHERE DNAME in list(\"SALES\", \"TEST\", \"ABC\")" "... WHERE DNAME in list(\"ABC\", nil)" To make it easier executing dynamic queries, it's now also allowed to use bind variables, for example: "... WHERE DNAME in list($1, $2)" Add your own cache implementationIf you are not satisfied with Castor's set of performance caches, we've added a way for you to provide you own cache implementationa and register it with Castor. To provide a custom cache implementation, you need to
Detailed instructions can be found in the package.html file of the org.exolab.castor.persist.cache package. Castor Source Generator Ant TaskThe Castor Source Generator Ant Task has been added to the CVS tree. Below is an example of how to use it from within an Ant build descriptor: <target name="castor:gen:src" depends="init" description="Generate Java source files from XSD."> <taskdef name="castor-srcgen" classname="org.exolab.castor.tools.ant.taskdefs.CastorSourceGenTask" classpathref="castor.class.path" /> <mkdir dir="${gen.src.d}" /> <castor-srcgen file="${schema.d}/books2.xsd" todir="${gen.src.d}" package="com.sourcebeat.castorlive.xmodel" types="j2" warnings="false" /> </target> The only requirement is that the castor-srcgen-ant-task.jar must be on the CLASSPATH. New features - experimentalJDO2 - a new approachDue to a couple of inconsistencies in the interface of the JDO class, we have decided to refactor this class and provide users with a much improved way of configuring and instantiating JDO instances (as explained below). To provide backwards-compatibility, we have created a new JDO2 class and left the old untouched. To create a Castor JDO instance (based upon a XML configuration file), users need to execute code similar to the following lines: JDO2.loadConfiguration ("jdo-conf.xml"); JDO2 jdo = JDO2.createInstance ("test"); Similar to what the old interface used to be, a couple of overloaded loadConfiguration() methods are provided, to allow specification of class loaders and XML entity resolvers.
For all the previous releases, the release notes can be found here. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() ![]() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() | ![]() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |