Author: tchemit Date: 2009-01-15 17:43:15 +0000 (Thu, 15 Jan 2009) New Revision: 1303 Added: topia/tags/2.1.2/ topia/tags/2.1.2/changelog.txt topia/tags/2.1.2/pom.xml topia/tags/2.1.2/topia-persistence/changelog.txt topia/tags/2.1.2/topia-persistence/pom.xml topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst topia/tags/2.1.2/topia-soa/changelog.txt topia/tags/2.1.2/topia-soa/pom.xml topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java topia/tags/2.1.2/topia-ui/changelog.txt topia/tags/2.1.2/topia-ui/pom.xml Removed: topia/tags/2.1.2/changelog.txt topia/tags/2.1.2/pom.xml topia/tags/2.1.2/topia-persistence/changelog.txt topia/tags/2.1.2/topia-persistence/pom.xml topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst topia/tags/2.1.2/topia-soa/changelog.txt topia/tags/2.1.2/topia-soa/pom.xml topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java topia/tags/2.1.2/topia-ui/changelog.txt topia/tags/2.1.2/topia-ui/pom.xml Log: [maven-release-plugin] copy for tag 2.1.2 Copied: topia/tags/2.1.2 (from rev 1296, topia/trunk) Deleted: topia/tags/2.1.2/changelog.txt =================================================================== --- topia/trunk/changelog.txt 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,159 +0,0 @@ -2.1.1 chemit 20081215 - * 20081215 [chemit] - new release for isis-fish :) - -2.1.0 chemit 20081210 - * 20081205 [chemit] - improve poms, use lutinproject 3.2 - - use JUnit4 for test, fix some tests (but not all). - - add some usefull method to build regex on topiaIds - * 20081118 Switch to multi module project - -ver-2-0-29 chatellier 20081117 - * 20081117 [chemit] improve EntityEnum - * 20081117 [chemit] add method findAllWithOrder in DAO to make have sorted lists - -ver-2-0-28 chatellier 20081114 - * 20081113 [chorlet] add support for lazy loading on attribute with 0..* multiplicity - * 20081113 [chorlet] fix bug on bidirectional association by adding inverse attribute in the one side of two hibernate mapping files - * 20081107 [chatellier] fix "result" named attribute generation in model - * 20081107 [chatellier] fix ant:ant, org.apache.ant:ant conflict - * 20081107 [chatellier] set lutingenerator provided scope - * 20081101 [chemit] bump lutingenerator to 0.61 - * 20081101 [chemit] add a EntityEnum to have a generic way to access Entities. - * 20081101 [chemit] improve generators : - - can exclude some generators on TopiaMetaGenerator - - refactor TopiaMetaGenerator to use a simple List of Generator to launch - - refactor Generators to have a default public constructor - - * 20081029 [chemit] fix infinitive recursion on method findByPrimaryKey and findByProperty in TopiaDAODeleagtor class - * 20081026 [chemit] add dbName of table if explicit in javadoc - * 20081024 [chemit] fix bug when no entity defined in model - -ver-2-0-27 chemit 20081021 - * 20081021 [chemit] clean pom, use lutingenerator 0.60 - * 20080922 [thimel] Switched to lutinproject 3.0 - * 20080922 [thimel] Sources are correctly maven2 structuted (src/main/xxx) - * 20080922 [thimel] Fixed maven-processor-plugin usage - * 20080922 [thimel] License switched to LGPL - -ver-2-0-26 thimel 20080922 - * 20080922 [thimel] Last version with lutinproject 2.2 - * 20082608 [chemit] permettre de recuperer uniquement une fenetre de resultat en hql (TopiaContext#find(String hql,int startIndex,int endIndex, Object ... args) - * 20082907 [chemit] Suppression des dependances en dur sur les implantations d'entites - * 20072012 [thimel] Support des index sur les attibuts - * 20072012 [ruchaud] Récupération des classes persistées - * 20072012 [ruchaud] Création d'un vetoable sur les finds - -ver-2-0-25 poussin 20071214 - - * 20071120 [chatellier] modify service init methods, return boolean to stay - activated - * 20071116 [chatellier] add support for topia context listeners - * 20071114 [chatellier] add support for service without persitent classes - * 20071109 [chatellier] add type="string" on topiaId in templates - - update hibernate version to 3.2.5.ga (event patch) - - jetty version 5.1.10 (better pom.xml) - * 20071001 [chatellier] move tapestry version to 5.0.5 - * 20070528 [chatellier] add stateModel generation support - - tapestry generation templates - - tapestry 5.0.4 dependency - - * 20071106 [poussin] add removeContext on TopiaContextFactory and call it - in TopiaContextImpl.closeContext(). - - * 20071107 [thimel] add db schema support - * 20071107 [thimel] several .hbm.xml refactoring - * 20071108 [thimel] add DTO generator - * 20071108 [thimel] add copyright support in generators - * 20071108 [thimel] add serialVersionUID support in EntityAbstractGenerator - -ver-2-0-24 poussin 20070425 - - * 20070420 [chatellier] add services interfaces generation (stereotype=service) - * 20070420 [chatellier] add topia services support - * 20070330 [poussin] TopiaContextFactory return new TopiaContext if context is closed - * 20070331 [poussin] change many string argument to class argument - * 20070331 [poussin] add getService(Class) method on TopiaContext - * 20070331 [poussin] remove helper in service that only return service instant - * 20070331 [poussin] add Devel.rst documentation - * 20070402 [poussin] replace init to preInit and postInit in TopiaService - -ver-2-0-22 ruchaud 20061023 - - * 20061023 [ruchaud][improve] manage events - * 20061023 [ruchaud][bug fix] in generator of DAO Abstract on delete - -ver-2-0-21 poussin 20061019 - - * add support for auto-import entities for hql - * add getComposite and getAggregate on TopiaEntity - * bug fix for association hibernate mapping wit have attributeh - cascade="delete" for not navigable link to prevent constraint exception - * bug fix in delete, remove link before do delete - -ver-2-0-20 poussin 20061017 - - * add support for TopiaService mechanisme - -ver-2-0-16 poussin 20060907 - - * Implantation des méthodes update et delete sur les TopiaUserImpl et TopiaEntityPermissionImpl - * add backup/restore method on TopiaContext (backup only works for h2) - * TopiaContext is set in Entity during preload - * add updateSchema in TopiaContext interface - * add methods update et delete on TopiaUserImpl and TopiaEntityPermissionImpl - -ver-2-0-13 thimel 20060822 - - * [Secu] ajout d'un champ notes sur les TopiaUser - * [Secu] ajout d'un champ linkApplication sur les TopiaUser (permettant de faire le lien avec une application externe) - * [Secu] ajout de commits et rollbacks sur les Manager - * [Secu] ajout d'un setPassword (sans verification ancien mdp) sur les TopiaUser - -ver-2-0-12 thimel 20060721 - - * ajout des projections sur les DAO - * positionnement unique des userManager et permissionManager au niveau du contexte racine - * ajout de la possibilite de tester des permissions sur le permissionManager - -ver-2-0-11 thimel 20060703 - - * support de la fermeture d'un contexte - * support de la recherche sur tous les attributs d'une entite / annotation sur les interfaces - -ver-2-0-8 thimel 20060606 - - * amelioration detection des classes abstraites - * correction du polymorphisme avec les proxies d'Hibernate - * Hibernate 3.2 - -ver-2-0-7 thimel 20060523 - - * import/export XML "experimental" - * one-to-one transformes en many-to-one + unique="true" - * bug au niveau de la detection des parents abstract - -ver-2-0-6 thimel 20060504 - - * support des annotations sur les attributs des XXXAbstract - * re-correction du support des relations unidirectionnelles 1-n avec classes d'heritage du cote n - * ajout de la validation pour les attributs sans inverses (pour les objectmodel faits a la main) - -ver-2-0-5 thimel 20060427 - - * isIndexed remplace isOrdered dans le mapping hibernate - * add postCreate and postLoad on AbstractTopiaEntity - * findContains sur les DAO (implante hors Hibernate pour l'instant) - * support plus coherent des classes abstraites - * projet compatible maven2 - * correction du support des relations unidirectionnelles 1-n avec classes d'heritage du cote n - -ver-2-0-4 thimel 20060303 - - * Correction du support des interfaces et classes abstraites (conjointement a LutinGenerator 0.30) - * Ajout des exceptions sur le operations (conjointement a LutinGenerator 0.30) - -ver-2-0-3 thimel 20060228 - - * Correction du support des classes d'associations (mauvais mapping Hibernate) - * Support de super classes pour les classes d'association (LutinGenerator 0.29) - Copied: topia/tags/2.1.2/changelog.txt (from rev 1301, topia/trunk/changelog.txt) =================================================================== --- topia/tags/2.1.2/changelog.txt (rev 0) +++ topia/tags/2.1.2/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,162 @@ +2.1.2 chemit 20090115 + * 20090114 [chemit] - using lutinproject 3.3 + +2.1.1 chemit 20081215 + * 20081215 [chemit] - new release for isis-fish :) + +2.1.0 chemit 20081210 + * 20081205 [chemit] - improve poms, use lutinproject 3.2 + - use JUnit4 for test, fix some tests (but not all). + - add some usefull method to build regex on topiaIds + * 20081118 Switch to multi module project + +ver-2-0-29 chatellier 20081117 + * 20081117 [chemit] improve EntityEnum + * 20081117 [chemit] add method findAllWithOrder in DAO to make have sorted lists + +ver-2-0-28 chatellier 20081114 + * 20081113 [chorlet] add support for lazy loading on attribute with 0..* multiplicity + * 20081113 [chorlet] fix bug on bidirectional association by adding inverse attribute in the one side of two hibernate mapping files + * 20081107 [chatellier] fix "result" named attribute generation in model + * 20081107 [chatellier] fix ant:ant, org.apache.ant:ant conflict + * 20081107 [chatellier] set lutingenerator provided scope + * 20081101 [chemit] bump lutingenerator to 0.61 + * 20081101 [chemit] add a EntityEnum to have a generic way to access Entities. + * 20081101 [chemit] improve generators : + - can exclude some generators on TopiaMetaGenerator + - refactor TopiaMetaGenerator to use a simple List of Generator to launch + - refactor Generators to have a default public constructor + + * 20081029 [chemit] fix infinitive recursion on method findByPrimaryKey and findByProperty in TopiaDAODeleagtor class + * 20081026 [chemit] add dbName of table if explicit in javadoc + * 20081024 [chemit] fix bug when no entity defined in model + +ver-2-0-27 chemit 20081021 + * 20081021 [chemit] clean pom, use lutingenerator 0.60 + * 20080922 [thimel] Switched to lutinproject 3.0 + * 20080922 [thimel] Sources are correctly maven2 structuted (src/main/xxx) + * 20080922 [thimel] Fixed maven-processor-plugin usage + * 20080922 [thimel] License switched to LGPL + +ver-2-0-26 thimel 20080922 + * 20080922 [thimel] Last version with lutinproject 2.2 + * 20082608 [chemit] permettre de recuperer uniquement une fenetre de resultat en hql (TopiaContext#find(String hql,int startIndex,int endIndex, Object ... args) + * 20082907 [chemit] Suppression des dependances en dur sur les implantations d'entites + * 20072012 [thimel] Support des index sur les attibuts + * 20072012 [ruchaud] Récupération des classes persistées + * 20072012 [ruchaud] Création d'un vetoable sur les finds + +ver-2-0-25 poussin 20071214 + + * 20071120 [chatellier] modify service init methods, return boolean to stay + activated + * 20071116 [chatellier] add support for topia context listeners + * 20071114 [chatellier] add support for service without persitent classes + * 20071109 [chatellier] add type="string" on topiaId in templates + - update hibernate version to 3.2.5.ga (event patch) + - jetty version 5.1.10 (better pom.xml) + * 20071001 [chatellier] move tapestry version to 5.0.5 + * 20070528 [chatellier] add stateModel generation support + - tapestry generation templates + - tapestry 5.0.4 dependency + + * 20071106 [poussin] add removeContext on TopiaContextFactory and call it + in TopiaContextImpl.closeContext(). + + * 20071107 [thimel] add db schema support + * 20071107 [thimel] several .hbm.xml refactoring + * 20071108 [thimel] add DTO generator + * 20071108 [thimel] add copyright support in generators + * 20071108 [thimel] add serialVersionUID support in EntityAbstractGenerator + +ver-2-0-24 poussin 20070425 + + * 20070420 [chatellier] add services interfaces generation (stereotype=service) + * 20070420 [chatellier] add topia services support + * 20070330 [poussin] TopiaContextFactory return new TopiaContext if context is closed + * 20070331 [poussin] change many string argument to class argument + * 20070331 [poussin] add getService(Class) method on TopiaContext + * 20070331 [poussin] remove helper in service that only return service instant + * 20070331 [poussin] add Devel.rst documentation + * 20070402 [poussin] replace init to preInit and postInit in TopiaService + +ver-2-0-22 ruchaud 20061023 + + * 20061023 [ruchaud][improve] manage events + * 20061023 [ruchaud][bug fix] in generator of DAO Abstract on delete + +ver-2-0-21 poussin 20061019 + + * add support for auto-import entities for hql + * add getComposite and getAggregate on TopiaEntity + * bug fix for association hibernate mapping wit have attributeh + cascade="delete" for not navigable link to prevent constraint exception + * bug fix in delete, remove link before do delete + +ver-2-0-20 poussin 20061017 + + * add support for TopiaService mechanisme + +ver-2-0-16 poussin 20060907 + + * Implantation des méthodes update et delete sur les TopiaUserImpl et TopiaEntityPermissionImpl + * add backup/restore method on TopiaContext (backup only works for h2) + * TopiaContext is set in Entity during preload + * add updateSchema in TopiaContext interface + * add methods update et delete on TopiaUserImpl and TopiaEntityPermissionImpl + +ver-2-0-13 thimel 20060822 + + * [Secu] ajout d'un champ notes sur les TopiaUser + * [Secu] ajout d'un champ linkApplication sur les TopiaUser (permettant de faire le lien avec une application externe) + * [Secu] ajout de commits et rollbacks sur les Manager + * [Secu] ajout d'un setPassword (sans verification ancien mdp) sur les TopiaUser + +ver-2-0-12 thimel 20060721 + + * ajout des projections sur les DAO + * positionnement unique des userManager et permissionManager au niveau du contexte racine + * ajout de la possibilite de tester des permissions sur le permissionManager + +ver-2-0-11 thimel 20060703 + + * support de la fermeture d'un contexte + * support de la recherche sur tous les attributs d'une entite / annotation sur les interfaces + +ver-2-0-8 thimel 20060606 + + * amelioration detection des classes abstraites + * correction du polymorphisme avec les proxies d'Hibernate + * Hibernate 3.2 + +ver-2-0-7 thimel 20060523 + + * import/export XML "experimental" + * one-to-one transformes en many-to-one + unique="true" + * bug au niveau de la detection des parents abstract + +ver-2-0-6 thimel 20060504 + + * support des annotations sur les attributs des XXXAbstract + * re-correction du support des relations unidirectionnelles 1-n avec classes d'heritage du cote n + * ajout de la validation pour les attributs sans inverses (pour les objectmodel faits a la main) + +ver-2-0-5 thimel 20060427 + + * isIndexed remplace isOrdered dans le mapping hibernate + * add postCreate and postLoad on AbstractTopiaEntity + * findContains sur les DAO (implante hors Hibernate pour l'instant) + * support plus coherent des classes abstraites + * projet compatible maven2 + * correction du support des relations unidirectionnelles 1-n avec classes d'heritage du cote n + +ver-2-0-4 thimel 20060303 + + * Correction du support des interfaces et classes abstraites (conjointement a LutinGenerator 0.30) + * Ajout des exceptions sur le operations (conjointement a LutinGenerator 0.30) + +ver-2-0-3 thimel 20060228 + + * Correction du support des classes d'associations (mauvais mapping Hibernate) + * Support de super classes pour les classes d'association (LutinGenerator 0.29) + Deleted: topia/tags/2.1.2/pom.xml =================================================================== --- topia/trunk/pom.xml 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,127 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - <parent> - <groupId>org.codelutin</groupId> - <artifactId>lutinproject</artifactId> - <version>3.2</version> - </parent> - - <artifactId>topia</artifactId> - <version>2.1.3-SNAPSHOT</version> - - <modules> - <module>topia-persistence</module> - <module>topia-soa</module> - <module>topia-ui</module> - </modules> - - <dependencyManagement> - <dependencies> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutingenerator</artifactId> - <version>${generator.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - <version>${lutinutil.version}</version> - <scope>compile</scope> - </dependency> - </dependencies> - </dependencyManagement> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - <name>ToPIA - Tools for Portable and Independent Architecture</name> - <description>Framework de persistance et de distribution d'application.</description> - <inceptionYear>2004</inceptionYear> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>pom</packaging> - - <properties> - <!-- id du projet du labs --> - <labs.id>21</labs.id> - - <!-- nom du projet sur le labs --> - <labs.project>topia</labs.project> - - <!-- Ignore failure test for now --> - <maven.test.testFailureIgnore>true</maven.test.testFailureIgnore> - - <!-- generator version --> - <generator.version>0.63</generator.version> - - <!-- processor version --> - <processor.version>0.16</processor.version> - - <!-- lutinutil version --> - <lutinutil.version>1.0</lutinutil.version> - - </properties> - - <build> - <defaultGoal>install</defaultGoal> - <pluginManagement> - <plugins> - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-processor-plugin</artifactId> - <version>${processor.version}</version> - <executions> - <execution> - <phase>generate-sources</phase> - <goals> - <goal>process</goal> - </goals> - </execution> - </executions> - <configuration> - <!-- You might change defaut directories --> - <!-- srcDir>${basedir}/src/main/java</srcDir> - <destDir>${basedir}/target/processed-sources/java</destDir--> - <addCompileDirectory>true</addCompileDirectory> - <includes> - <include>**/*.java</include> - </includes> - <filters> - org.codelutin.processor.filters.GeneratorTemplatesFilter, - org.codelutin.processor.filters.ActiveLogsCodeFilter - </filters> - <verbose>${maven.verbose}</verbose> - </configuration> - </plugin> - </plugins> - </pluginManagement> - - <plugins> - - <plugin> - <artifactId>maven-javadoc-plugin</artifactId> - </plugin> - - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${maven.scm.connection}</connection> - <developerConnection>${maven.scm.developerConnection}</developerConnection> - <url>${maven.scm.url}</url> - </scm> - -</project> Copied: topia/tags/2.1.2/pom.xml (from rev 1302, topia/trunk/pom.xml) =================================================================== --- topia/tags/2.1.2/pom.xml (rev 0) +++ topia/tags/2.1.2/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,120 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + <parent> + <groupId>org.codelutin</groupId> + <artifactId>lutinproject</artifactId> + <version>3.3</version> + </parent> + + <artifactId>topia</artifactId> + <version>2.1.2</version> + + <modules> + <module>topia-persistence</module> + <module>topia-soa</module> + <module>topia-ui</module> + </modules> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutingenerator</artifactId> + <version>${generator.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + <version>${lutinutil.version}</version> + <scope>compile</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + <name>ToPIA - Tools for Portable and Independent Architecture</name> + <description>Framework de persistance et de distribution d'application.</description> + <inceptionYear>2004</inceptionYear> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>pom</packaging> + + <properties> + <!-- id du projet du labs --> + <labs.id>21</labs.id> + + <!-- nom du projet sur le labs --> + <labs.project>topia</labs.project> + + <!-- Ignore failure test for now --> + <maven.test.testFailureIgnore>true</maven.test.testFailureIgnore> + + <!-- generator version --> + <generator.version>0.63</generator.version> + + <!-- processor version --> + <processor.version>0.16</processor.version> + + <!-- lutinutil version --> + <lutinutil.version>1.0</lutinutil.version> + + </properties> + + <build> + <defaultGoal>install</defaultGoal> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-processor-plugin</artifactId> + <version>${processor.version}</version> + <executions> + <execution> + <phase>generate-sources</phase> + <goals> + <goal>process</goal> + </goals> + </execution> + </executions> + <configuration> + <!-- You might change defaut directories --> + <!-- srcDir>${basedir}/src/main/java</srcDir> + <destDir>${basedir}/target/processed-sources/java</destDir--> + <addCompileDirectory>true</addCompileDirectory> + <includes> + <include>**/*.java</include> + </includes> + <filters> + org.codelutin.processor.filters.GeneratorTemplatesFilter, + org.codelutin.processor.filters.ActiveLogsCodeFilter + </filters> + <verbose>${maven.verbose}</verbose> + </configuration> + </plugin> + </plugins> + </pluginManagement> + + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/topia/tags/2.1.2?root=topia</url> + </scm> + +</project> Deleted: topia/tags/2.1.2/topia-persistence/changelog.txt =================================================================== --- topia/trunk/topia-persistence/changelog.txt 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,21 +0,0 @@ -2.1.2 ??? 200901?? -* 20090106 [chemit] - amélioration du générateur de mapping hibernate : - - génération des clefs metier dans le mapping hibernate via la tag value naturalId - - mise en constantes des tagValues utiliser dans le génératuer du mapping hibernate - - ajout du tagValue notNull pour le mapping hibernate - - changement du tagValue order-by en orderBy car sinon on récupère order au lieu de order-by - - ajout de la méthode obtainProgperties sur la classe Loador pour recuperer la map des propriétés à binder - (car pour les clef métiers on doit les ajouter à la création sinon hibernate pleure...) -* 20090104 [chemit] - utilisation foreach dans les générateurs - - ajout de méthode getXXXByTopiaId pour les attributs à multiplicité dans les entités (interface et abstract) - - fix generic dans les méthodes générées - - ajout d'un tagValue i18n pour générer dans les entités abstraites les chaines i18n - - ajout d'un paquetage org.codelutin.topia.persistence.util avec du code utile :) (javadoc a faire...) - -2.1.1 chemit 20081215 -* 20081215 [chemit] - new release for isis-fish :) -* 20081212 [chemit] - add a InterfaceGenerator to generate simple with no stereotype interfaces. - -2.1.0 chemit 20081210 -* 20081205 [chemit] - improve poms, use lutinproject 3.2 - - add some usefull methods in TopiaUtil to help with regex on topiaId expression \ No newline at end of file Copied: topia/tags/2.1.2/topia-persistence/changelog.txt (from rev 1301, topia/trunk/topia-persistence/changelog.txt) =================================================================== --- topia/tags/2.1.2/topia-persistence/changelog.txt (rev 0) +++ topia/tags/2.1.2/topia-persistence/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,23 @@ +2.1.2 chemit 20090115 +* 20090115 [chemit] - pour le moment pas d'embed-xml sur les association multiples +* 20090114 [chemit] - improve exportXML (prepare queries then executes then when parameters are known to be fine) +* 20090106 [chemit] - amélioration du générateur de mapping hibernate : + - génération des clefs metier dans le mapping hibernate via la tag value naturalId + - mise en constantes des tagValues utiliser dans le génératuer du mapping hibernate + - ajout du tagValue notNull pour le mapping hibernate + - changement du tagValue order-by en orderBy car sinon on récupère order au lieu de order-by + - ajout de la méthode obtainProgperties sur la classe Loador pour recuperer la map des propriétés à binder + (car pour les clef métiers on doit les ajouter à la création sinon hibernate pleure...) +* 20090104 [chemit] - utilisation foreach dans les générateurs + - ajout de méthode getXXXByTopiaId pour les attributs à multiplicité dans les entités (interface et abstract) + - fix generic dans les méthodes générées + - ajout d'un tagValue i18n pour générer dans les entités abstraites les chaines i18n + - ajout d'un paquetage org.codelutin.topia.persistence.util avec du code utile :) (javadoc a faire...) + +2.1.1 chemit 20081215 +* 20081215 [chemit] - new release for isis-fish :) +* 20081212 [chemit] - add a InterfaceGenerator to generate simple with no stereotype interfaces. + +2.1.0 chemit 20081210 +* 20081205 [chemit] - improve poms, use lutinproject 3.2 + - add some usefull methods in TopiaUtil to help with regex on topiaId expression \ No newline at end of file Deleted: topia/tags/2.1.2/topia-persistence/pom.xml =================================================================== --- topia/trunk/topia-persistence/pom.xml 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,108 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>topia</artifactId> - <version>2.1.3-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-persistence</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutingenerator</artifactId> - </dependency> - - <dependency> - <groupId>commons-collections</groupId> - <artifactId>commons-collections</artifactId> - <version>3.2.1</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-core</artifactId> - <version>3.3.1.GA</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.hibernate</groupId> - <artifactId>hibernate-ehcache</artifactId> - <version>3.3.1.GA</version> - <scope>runtime</scope> - </dependency> - <dependency> - <groupId>javassist</groupId> - <artifactId>javassist</artifactId> - <version>3.4.GA</version> - <scope>runtime</scope> - </dependency> - <!-- hibernate-core only include api, need core --> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - <version>1.5.2</version> - <scope>runtime</scope> - </dependency> - - <!-- BD H2 for testing --> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <version>1.1.104</version> - <scope>test</scope> - </dependency> - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - - <name>ToPIA - Persistence</name> - <description>Hibernate based persistence module</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <defaultGoal>install</defaultGoal> - <plugins> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-processor-plugin</artifactId> - </plugin> - - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${maven.scm.connection.child}</connection> - <developerConnection>${maven.scm.developerConnection.child}</developerConnection> - <url>${maven.scm.url.child}</url> - </scm> - - -</project> Copied: topia/tags/2.1.2/topia-persistence/pom.xml (from rev 1302, topia/trunk/topia-persistence/pom.xml) =================================================================== --- topia/tags/2.1.2/topia-persistence/pom.xml (rev 0) +++ topia/tags/2.1.2/topia-persistence/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,108 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>topia</artifactId> + <version>2.1.2</version> + </parent> + + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-persistence</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutingenerator</artifactId> + </dependency> + + <dependency> + <groupId>commons-collections</groupId> + <artifactId>commons-collections</artifactId> + <version>3.2.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-core</artifactId> + <version>3.3.1.GA</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.hibernate</groupId> + <artifactId>hibernate-ehcache</artifactId> + <version>3.3.1.GA</version> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>javassist</groupId> + <artifactId>javassist</artifactId> + <version>3.4.GA</version> + <scope>runtime</scope> + </dependency> + <!-- hibernate-core only include api, need core --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.5.2</version> + <scope>runtime</scope> + </dependency> + + <!-- BD H2 for testing --> + <dependency> + <groupId>com.h2database</groupId> + <artifactId>h2</artifactId> + <version>1.1.104</version> + <scope>test</scope> + </dependency> + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>ToPIA - Persistence</name> + <description>Hibernate based persistence module</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <build> + <defaultGoal>install</defaultGoal> + <plugins> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-processor-plugin</artifactId> + </plugin> + + </plugins> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-persistence</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-persistence</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/topia/tags/2.1.2/topia-persistence?root=topia</url> + </scm> + + +</project> Deleted: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java =================================================================== --- topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,1298 +0,0 @@ -/* *##% ToPIA - Tools for Portable and Independent Architecture - * Copyright (C) 2004 - 2008 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - -/******************************************************************************* - * TopiaContextImpl.java - * - * Created: 23 déc. 2005 16:58:50 - * - * @author poussin - * - * @version $Revision$ - * - * Last update: $Date$ by : $Author$ - */ - -package org.codelutin.topia.framework; - -import java.beans.PropertyChangeListener; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.Reader; -import java.io.Writer; -import java.lang.reflect.Field; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.zip.GZIPInputStream; - -import org.apache.commons.collections.set.MapBackedSet; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codelutin.topia.TopiaContext; -import org.codelutin.topia.TopiaContextFactory; -import org.codelutin.topia.TopiaException; -import org.codelutin.topia.TopiaNotFoundException; -import org.codelutin.topia.event.TopiaContextListener; -import org.codelutin.topia.event.TopiaEntitiesVetoable; -import org.codelutin.topia.event.TopiaEntityListener; -import org.codelutin.topia.event.TopiaEntityVetoable; -import org.codelutin.topia.event.TopiaTransactionListener; -import org.codelutin.topia.event.TopiaTransactionVetoable; -import org.codelutin.topia.persistence.TopiaDAO; -import org.codelutin.topia.persistence.TopiaDAODelegator; -import org.codelutin.topia.persistence.TopiaEntity; -import org.codelutin.topia.persistence.TopiaId; -import org.codelutin.util.ArrayUtil; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.DocumentFactory; -import org.dom4j.Element; -import org.dom4j.io.OutputFormat; -import org.dom4j.io.SAXReader; -import org.dom4j.io.XMLWriter; -import org.hibernate.EntityMode; -import org.hibernate.FlushMode; -import org.hibernate.HibernateException; -import org.hibernate.Query; -import org.hibernate.ReplicationMode; -import org.hibernate.SQLQuery; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.Transaction; -import org.hibernate.cfg.Configuration; -import org.hibernate.event.PostDeleteEventListener; -import org.hibernate.event.PostInsertEventListener; -import org.hibernate.event.PostLoadEventListener; -import org.hibernate.event.PostUpdateEventListener; -import org.hibernate.event.PreDeleteEventListener; -import org.hibernate.event.PreInsertEventListener; -import org.hibernate.event.PreLoadEventListener; -import org.hibernate.event.PreUpdateEventListener; -import org.hibernate.tool.hbm2ddl.SchemaExport; -import org.hibernate.tool.hbm2ddl.SchemaUpdate; - -/** - * Le TopiaContextImpl est le point d'entre pour acceder aux donnees. Il est - * configurer par un fichier de propriete - * <p> - * List des proprietes disponible - * <dl> - * <dt> topia.persistence.properties.file - * <dd> le fichier de propriété a utiliser pour configurer hibernate - * - * <dt> topia.persistence.directories - * <dd> la liste des repertoires contenant les mappings hibernates (.hbm.xml) la - * liste de repertoire est separer par des virgules ',' - * - * <dt> topia.persistence.classes - * <dd> la liste des classes que doit géré hibernate. On peut tres bien utiliser - * topia.persistence.directories pour un ensemble d'entié du meme repertoire et - * topia.persistence.classes pour d'autres classes - * </dl> - * - * @see TopiaSecurityManager - * @see TopiaIndexService - * @see TopiaHistoryService - * - * @author poussin - */ -public class TopiaContextImpl implements TopiaContext, TopiaContextImplementor { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - static private Log log = LogFactory.getLog(TopiaContextImpl.class); - - static final private String TOPIA_PERSISTENCE_DIRECTORIES = "topia.persistence.directories"; - - static final private String TOPIA_PERSISTENCE_CLASSES = "topia.persistence.classes"; - - static final private String TOPIA_PERSISTENCE_PROPERTIES_FILE = "topia.persistence.properties.file"; - - /** - * Le pere de ce context, les contexts initaux n'ont pas de context pere - */ - protected TopiaContextImplementor parentContext = null; - - /** - * L'objet configuration utilisé pour la creation de la factory hibernate - */ - protected Configuration hibernateConfiguration = null; - - /** - * la factory permettant de recuperer la session hibernate. Seul les - * TopiaContextImpl initiaux contiennent un hibernateFactory - */ - protected SessionFactory hibernateFactory = null; - - /** - * La session utilisé par le TopiaContextImpl - */ - protected Session hibernate = null; - - /** - * Indique si le contexte a ete ferme - */ - protected boolean closed = false; - - /** - * Propriete de configuration - */ - protected Properties config = null; - - /** - * cache des DAO deja chargé pour ce context - */ - protected Map<Class, TopiaDAO> daoCache = new HashMap<Class, TopiaDAO>(); - - /** - * Set des sous context creer avec un beginTransaction et donc sur lequel - * nous sommes listener - */ - protected Set<TopiaContextImplementor> childContext = MapBackedSet - .decorate(new WeakHashMap<TopiaContextImplementor, Object>()); - - /** key: service name; value: service instance */ - protected Map<String, TopiaService> services = null; - - /** */ - protected TopiaFiresSupport firesSupport = new TopiaFiresSupport(); - - /** Liste des classes perssitance */ - protected List<Class> persistenceClasses = new ArrayList<Class>(); - - /** - * constructeur utilisé par la factory pour creer les contexts initiaux - * - * @param config - * @throws TopiaNotFoundException - */ - public TopiaContextImpl(Properties config) throws TopiaNotFoundException { - this.config = config; - services = loadServices(config); - preInitServices(services); - getHibernateConfiguration(); // force mapping loading - postInitServices(services); - } - - protected Map<String, TopiaService> loadServices(Properties config) { - Map<String, TopiaService> result = new HashMap<String, TopiaService>(); - // recherche des services present dans la config - for (Enumeration<String> e = (Enumeration<String>) config - .propertyNames(); e.hasMoreElements();) { - String key = e.nextElement(); - if (key.matches("^topia\\.service\\.\\w+$")) { - String classService = config.getProperty(key); - try { - Class forName = Class.forName(classService); - Object newInstance = forName.newInstance(); - TopiaService service = (TopiaService) newInstance; - if (key.equals("topia.service." + service.getServiceName())) { - result.put(service.getServiceName(), service); - log.info("Service " + key + " loaded by " - + classService); - } else { - log - .warn("Service config key doesn't match service name, disable it: " - + key - + " != " - + service.getServiceName()); - } - } catch (Throwable eee) { - if (log.isErrorEnabled()) { - log.error("Service class unknow for " + key + ": " - + classService); - } - if (log.isDebugEnabled()) { - log.debug(eee); - } - } - } - } - return result; - } - - protected void preInitServices(Map<String, TopiaService> services) { - for (TopiaService service : services.values()) { - if (!service.preInit(this)) { - log.warn("Can't preInit service disable it: " - + service.getServiceName()); - } - } - } - - protected void postInitServices(Map<String, TopiaService> services) { - for (TopiaService service : services.values()) { - if (!service.postInit(this)) { - log.warn("Can't postInit service disable it: " - + service.getServiceName()); - } - } - } - - public Map<String, TopiaService> getServices() { - TopiaContextImplementor parent = getParentContext(); - - Map<String, TopiaService> result = null; - if (parent != null) { - result = parent.getServices(); - } else { - result = services; - } - return result; - } - - protected boolean serviceEnabled(String name) { - boolean result = getServices().containsKey(name); - return result; - } - - protected TopiaService getService(String name) { - TopiaService result = getServices().get(name); - return result; - } - - public <E extends TopiaService> boolean serviceEnabled( - Class<E> interfaceService) { - boolean result = false; - try { - Field f = interfaceService.getField("SERVICE_NAME"); - String name = (String) f.get(null); - result = serviceEnabled(name); - } catch (Exception eee) { - if (log.isWarnEnabled()) { - log - .warn( - "Can't get service name for: " - + interfaceService, eee); - } - } - return result; - } - - /** - * Take one service, this service must be valid service interface with - * public static final SERVICE_NAME declaration. - * @param <E> - * @throws TopiaNotFoundException - */ - public <E extends TopiaService> E getService(Class<E> interfaceService) - throws TopiaNotFoundException { - try { - Field f = interfaceService.getField("SERVICE_NAME"); - String name = (String) f.get(null); - E result = (E) getService(name); - if (result == null) { - throw new TopiaNotFoundException("Service not available: " - + interfaceService); - } - return result; - } catch (Exception eee) { - throw new TopiaNotFoundException("Can't get service: " - + interfaceService, eee); - } - } - - /* (non-Javadoc) - * @see org.codelutin.topia.framework.TopiaContextImplementor#getAllServices() - */ - public Collection<TopiaService> getAllServices() { - Collection<TopiaService> result = getServices().values(); - return result; - } - - /** - * Constructeur utilisé par le beginTransaction pour créer le context fils. - * - * @param parentContext - * @throws HibernateException - * @throws TopiaNotFoundException - */ - protected TopiaContextImpl(TopiaContextImplementor parentContext) - throws HibernateException, TopiaNotFoundException { - this.parentContext = parentContext; - } - - public Set<TopiaContextImplementor> getChildContext() { - return this.childContext; - } - - protected void addChildContext(TopiaContextImplementor child) { - childContext.add(child); - } - - public void removeChildContext(TopiaContextImplementor child) { - //On ne retire les fils que si ce contexte n'est pas deja ferme. Permet d'eviter les acces concurrentiels - if (!closed) { - childContext.remove(child); - } - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getParentContext() - */ - public TopiaContextImplementor getParentContext() { - return parentContext; - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getRootContext() - */ - public TopiaContextImplementor getRootContext() { - TopiaContextImplementor result = this; - if (getParentContext() != null) { - result = getParentContext().getRootContext(); - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getConfig() - */ - public Properties getConfig() { - if (config == null && getParentContext() != null) { - config = getParentContext().getConfig(); - } - return config; - } - - /* (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#createSchema() - */ - public void createSchema() throws TopiaException { - try { - boolean showSchema = false; - if (log.isDebugEnabled()) { - showSchema = true; - } - getFiresSupport().firePreCreateSchema(this); - new SchemaExport(getHibernateConfiguration()).create(showSchema, - true); - getFiresSupport().firePostCreateSchema(this); - } catch (HibernateException eee) { - throw new TopiaException("Can't create database schema", eee); - } - } - - /* (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#createSchema() - */ - public void updateSchema() throws TopiaException { - try { - boolean showSchema = false; - if (log.isDebugEnabled()) { - showSchema = true; - } - getFiresSupport().firePreUpdateSchema(this); - new SchemaUpdate(getHibernateConfiguration()).execute(showSchema, - true); - getFiresSupport().firePostUpdateSchema(this); - } catch (HibernateException eee) { - throw new TopiaException("Can't create database schema", eee); - } - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getHibernate() - */ - public Session getHibernate() throws TopiaException { - if (hibernate == null) { - throw new TopiaException( - "No hibernate session available, you must start a transaction with beginTransaction"); - } - return hibernate; - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getHibernateFactory() - */ - public SessionFactory getHibernateFactory() throws TopiaNotFoundException { - if (hibernateFactory == null) { - if (getParentContext() != null) { - hibernateFactory = getParentContext().getHibernateFactory(); - } else { - hibernateFactory = getHibernateConfiguration() - .buildSessionFactory(); - } - } - return hibernateFactory; - } - - public Configuration getHibernateConfiguration() - throws TopiaNotFoundException { - if (hibernateConfiguration == null) { - if (getParentContext() != null) { - hibernateConfiguration = getParentContext() - .getHibernateConfiguration(); - } else { - hibernateConfiguration = new Configuration(); - - // Ajout du listeners pour les events - TopiaFiresSupport.TopiaHibernateEvent listener = new TopiaFiresSupport.TopiaHibernateEvent( - this); - - PreInsertEventListener[] preInsertEventListeners = hibernateConfiguration - .getEventListeners().getPreInsertEventListeners(); - preInsertEventListeners = ArrayUtil.concatElems( - preInsertEventListeners, listener); - PreLoadEventListener[] preLoadEventListeners = hibernateConfiguration - .getEventListeners().getPreLoadEventListeners(); - preLoadEventListeners = ArrayUtil.concatElems( - preLoadEventListeners, listener); - PreUpdateEventListener[] preUpdateEventListeners = hibernateConfiguration - .getEventListeners().getPreUpdateEventListeners(); - preUpdateEventListeners = ArrayUtil.concatElems( - preUpdateEventListeners, listener); - PreDeleteEventListener[] preDeleteEventListeners = hibernateConfiguration - .getEventListeners().getPreDeleteEventListeners(); - preDeleteEventListeners = ArrayUtil.concatElems( - preDeleteEventListeners, listener); - - PostInsertEventListener[] postInsertEventListeners = hibernateConfiguration - .getEventListeners().getPostInsertEventListeners(); - postInsertEventListeners = ArrayUtil.concatElems( - postInsertEventListeners, listener); - PostLoadEventListener[] postLoadEventListeners = hibernateConfiguration - .getEventListeners().getPostLoadEventListeners(); - postLoadEventListeners = ArrayUtil.concatElems( - postLoadEventListeners, listener); - PostUpdateEventListener[] postUpdateEventListeners = hibernateConfiguration - .getEventListeners().getPostUpdateEventListeners(); - postUpdateEventListeners = ArrayUtil.concatElems( - postUpdateEventListeners, listener); - PostDeleteEventListener[] postDeleteEventListeners = hibernateConfiguration - .getEventListeners().getPostDeleteEventListeners(); - postDeleteEventListeners = ArrayUtil.concatElems( - postDeleteEventListeners, listener); - - hibernateConfiguration.getEventListeners() - .setPreInsertEventListeners(preInsertEventListeners); - hibernateConfiguration.getEventListeners() - .setPreLoadEventListeners(preLoadEventListeners); - hibernateConfiguration.getEventListeners() - .setPreUpdateEventListeners(preUpdateEventListeners); - hibernateConfiguration.getEventListeners() - .setPreDeleteEventListeners(preDeleteEventListeners); - - hibernateConfiguration.getEventListeners() - .setPostInsertEventListeners(postInsertEventListeners); - hibernateConfiguration.getEventListeners() - .setPostLoadEventListeners(postLoadEventListeners); - hibernateConfiguration.getEventListeners() - .setPostUpdateEventListeners(postUpdateEventListeners); - hibernateConfiguration.getEventListeners() - .setPostDeleteEventListeners(postDeleteEventListeners); - - // ajout des repertoires contenant les mappings hibernate - String[] dirs = getConfig().getProperty( - TOPIA_PERSISTENCE_DIRECTORIES, "").split(","); - for (String dir : dirs) { - dir = dir.trim(); - if (!"".equals(dir)) { - hibernateConfiguration.addDirectory(new File(dir)); - } - } - - // ajout des classes dites persistentes - String listPersistenceClasses = getConfig().getProperty( - TOPIA_PERSISTENCE_CLASSES, ""); - - for (TopiaService service : getAllServices()) { - Class<?>[] persistenceClasses = service - .getPersistenceClasses(); - - // certains service n'ont pas de classe persistantes - if (persistenceClasses != null) { - for (Class<?> clazz : persistenceClasses) { - hibernateConfiguration.addClass(clazz); - } - } - } - - String[] classes = listPersistenceClasses.split(","); - for (String classname : classes) { - classname = classname.trim(); - if (!"".equals(classname)) { - Class<?> clazz; - try { - clazz = Class.forName(classname); - } catch (ClassNotFoundException eee) { - throw new TopiaNotFoundException( - "Persistent class " + classname - + " not found"); - } - persistenceClasses.add(clazz); - hibernateConfiguration.addClass(clazz); - } - } - - Properties prop = new Properties(); - prop.putAll(hibernateConfiguration.getProperties()); - prop.putAll(getConfig()); - prop.putAll(TopiaUtil.getProperties(getConfig().getProperty( - TOPIA_PERSISTENCE_PROPERTIES_FILE))); - hibernateConfiguration.setProperties(prop); - } - } - return hibernateConfiguration; - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.framework.TopiaContextImplementor#getDAO(java.lang.Class) - */ - @SuppressWarnings("unchecked") - public <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass) - throws TopiaException { - if (entityClass == null) { - throw new IllegalArgumentException("null is not valid entity class"); - } - if (getRootContext() == this) { - throw new TopiaException("Vous êtes sur le root context vous" - + " devez ouvrir une transaction pour pouvoir accèder" - + " aux données"); - } - if (getHibernateFactory().getClassMetadata(entityClass) == null - && getHibernateFactory().getClassMetadata( - entityClass.getName() + "Impl") == null - && getHibernateFactory().getClassMetadata( - entityClass.getName() + "Abstract") == null) { - log.info("Classes supportées par ce TopiaContext: " - + getHibernateFactory().getAllClassMetadata().keySet()); - throw new TopiaException( - "La classe " - + entityClass.getName() - + " n'est pas supportée par ce TopiaContext. Vous avez sans" - + " doute oublié d'ajouter son mapping"); - } - - TopiaDAO<E> result = daoCache.get(entityClass); - if (result == null) { - // recherche du type de DAO a instancier pour cette entity - String defaultDAOClassname = getConfig().getProperty( - "topia.dao.default.class", "hibernate"); - String daoClassname = getConfig().getProperty( - "topia.dao." + entityClass.getName(), defaultDAOClassname); - if ("hibernate".equals(daoClassname)) { - // FIXME nom en dur ? - daoClassname = "org.codelutin.topia.persistence.hibernate.TopiaDAOHibernate"; - } else if ("flatfile".equals(daoClassname)) { - daoClassname = "org.codelutin.topia.persistence.flatfile.TopiaDAOFlatFile"; - } - - try { - Class<TopiaDAO<E>> resultClass = (Class<TopiaDAO<E>>) Class - .forName(daoClassname); - result = resultClass.newInstance(); - result.init(this, entityClass); - } catch (ClassNotFoundException eee) { - throw new TopiaException("Can't find DAO class " + daoClassname); - } catch (InstantiationException eee) { - throw new TopiaException("Can't instanciate DAO class " - + daoClassname); - } catch (IllegalAccessException eee) { - throw new TopiaException("Can't access DAO class " - + daoClassname); - } - - // looking for specialized DAO - // normalement il en existe un car il est généré automatiquement - // si on utilise la génération - daoClassname = entityClass.getName() + "DAO"; - try { - Class<TopiaDAODelegator<E>> daoClass = (Class<TopiaDAODelegator<E>>) Class - .forName(daoClassname); - TopiaDAODelegator<E> spe = daoClass.newInstance(); - spe.setParentDAO(result); - result = spe; - } catch (Exception eee) { - log.warn("specialized DAO " + daoClassname - + " not found, use default TopiaDAOHibernate"); - } - daoCache.put(entityClass, result); - } - return result; - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.TopiaContext#beginTransaction() - */ - public TopiaContext beginTransaction() throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible de commencer une transaction"); - TopiaContextImpl result = new TopiaContextImpl(this); - - SessionFactory factory = getHibernateFactory(); - result.hibernate = factory.openSession(); - // new TopiaInterceptor(result)); - // on ne synchronise jamais les données avec la base tant que - // l'utilisateur n'a pas fait de commit du context - result.hibernate.setFlushMode(FlushMode.MANUAL); - - // 20060926 poussin ajouter pour voir si ca regle les problemes de deadlock h2 - // Conclusion, il faut bien ouvrir une transaction maintenant, sinon - // lorsque l'on fait des acces a la base, une transaction par defaut est - // utilisé mais elle n'est jamais vraiment fermé ce qui pose des problemes - // de lock sur les tables. - result.hibernate.beginTransaction(); - - // 20081217 : add child AFTER hibernate session is opened - addChildContext(result); - - // fire event - getFiresSupport().fireOnBeginTransaction(result); - - return result; - } - - // Transaction tx = null; - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.TopiaContext#commitTransaction() - */ - public void commitTransaction() throws TopiaException { - if (getRootContext() == this) { - throw new TopiaException( - "Vous êtes sur le root context le commit est impossible"); - } - checkClosed("Ce contexte a ete ferme, impossible de faire un commit"); - try { - for (TopiaDAO<TopiaEntity> dao : daoCache.values()) { - dao.commitTransaction(); - } - Transaction tx = hibernate.getTransaction(); - // Transaction tx = hibernate.beginTransaction(); - hibernate.flush(); - tx.commit(); - - getFiresSupport().fireOnPostCommit(this); - TopiaContextImplementor parent = getParentContext(); - if (parent != null) { - parent.getFiresSupport().fireOnPostCommit(this); - } - - hibernate.beginTransaction(); - // it's seem necessary to change session after commit - // NON, NON, NON, il ne faut surtout pas le faire, ca pose plein de probleme - // hibernate = getHibernateFactory().openSession(); - // hibernate.setFlushMode(FlushMode.NEVER); - } catch (Exception eee) { - throw new TopiaException("Error during commit", eee); - } - } - - /* - * (non-Javadoc) - * - * @see org.codelutin.topia.TopiaContext#rollbackTransaction() - */ - public void rollbackTransaction() throws TopiaException { - if (getRootContext() == this) { - throw new TopiaException( - "Vous êtes sur le root context le rollback est impossible"); - } - checkClosed("Ce contexte a ete ferme, impossible de faire un rollback"); - try { - for (TopiaDAO<TopiaEntity> dao : daoCache.values()) { - dao.rollbackTransaction(); - } - Transaction tx = hibernate.getTransaction(); - // Transaction tx = hibernate.beginTransaction(); - hibernate.clear(); - tx.rollback(); - hibernate.close(); - // it's very important to change the session after rollback - // otherwize there are many error during next Entity's modification - hibernate = getHibernateFactory().openSession(); - hibernate.setFlushMode(FlushMode.MANUAL); - - hibernate.beginTransaction(); - - getFiresSupport().fireOnPostRollback(this); - TopiaContextImplementor parent = getParentContext(); - if (parent != null) { - parent.getFiresSupport().fireOnPostRollback(this); - } - - } catch (HibernateException eee) { - throw new TopiaException(eee); - } - } - - public void closeContext() throws TopiaException { - // 20060926 poussin: Si si on peut, ca ferme en fait tous les enfants et c tout - // if (getRootContext() == this) { - // throw new TopiaException( - // "Vous ne pouvez pas fermer le root context"); - // } - - checkClosed("Ce contexte a deja ete ferme"); - - // suppression des contexts fils - TopiaContextImplementor[] childs = childContext - .toArray(new TopiaContextImplementor[childContext.size()]); - for (TopiaContextImplementor child : childs) { - if (!child.isClosed()) { - child.closeContext(); - } - } - // for (Iterator iter = childContext.iterator(); iter.hasNext();) { - // TopiaContextImplementor child = (TopiaContextImplementor) iter.next(); - // child.closeContext(); - // iter.remove(); - // } - - // on se desenregistre du context pere et on ferme les connexions si - // on est pas le root context - if (getRootContext() != this) { - this.closed = true; - hibernate.close(); - getParentContext().removeChildContext(this); - } else { - if (hibernateFactory != null) { - hibernateFactory.close(); - this.closed = true; - TopiaContextFactory.removeContext(this); - log.debug("TopiaContext finalized"); - } - } - } - - /** - * Pour le context root on ferme tous les fils, et la factory hibernate - * @see java.lang.Object#finalize() - */ - @Override - protected void finalize() throws Throwable { - if (hibernateFactory != null) { - closeContext(); - hibernateFactory.close(); - this.closed = true; - log.debug("TopiaContext finalized"); - } - } - - public boolean isClosed() { - return closed; - } - - private void checkClosed(String message) throws TopiaException { - if (closed) { - throw new TopiaException(message); - } - } - - /* (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#findByTopiaId(java.lang.String) - */ - public TopiaEntity findByTopiaId(String topiaId) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); - TopiaEntity result; - Class<? extends TopiaEntity> entityClass = TopiaId - .getClassName(topiaId); - TopiaDAO dao = getDAO(entityClass); - result = dao.findByTopiaId(topiaId); - return result; - } - - /* - * (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#find(java.lang.String, java.lang.Object[]) - */ - public List find(String hql, Object... args) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); - try { - Query query = getHibernate().createQuery(hql); - for (int j = 0; j < args.length; j += 2) { - String name = (String) args[j]; - Object value = args[j + 1]; - if (value.getClass().isArray()) { - query.setParameterList(name, (Object[]) value); - } else { - query.setParameter(name, value); - } - } - List result = query.list(); - result = firesSupport.fireEntitiesLoad(this, result); - return result; - } catch (HibernateException eee) { - throw new TopiaException("Error during query execution: " + hql, - eee); - } - } - - public List find(String hql, int startIndex, int endIndex, Object... args) - throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); - try { - Query query = getHibernate().createQuery(hql); - for (int j = 0; j < args.length; j += 2) { - String name = (String) args[j]; - Object value = args[j + 1]; - if (value.getClass().isArray()) { - query.setParameterList(name, (Object[]) value); - } else { - query.setParameter(name, value); - } - } - query.setFirstResult(startIndex); - query.setMaxResults(endIndex - startIndex + 1); - List result = query.list(); - result = firesSupport.fireEntitiesLoad(this, result); - return result; - } catch (HibernateException eee) { - throw new TopiaException("Error during query execution: " + hql, - eee); - } - } - - /** - * Execute HQL operation on data (Update, Delete) - * @param hql - * @param args - * @return The number of entities updated or deleted. - * @throws TopiaException - */ - public int execute(String hql, Object... args) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); - try { - Query query = getHibernate().createQuery(hql); - for (int j = 0; j < args.length; j += 2) { - query.setParameter((String) args[j], args[j + 1]); - } - int result = query.executeUpdate(); - return result; - } catch (HibernateException eee) { - throw new TopiaException("Error during query execution: " + hql, - eee); - } - } - - /* (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#add(org.codelutin.topia.persistence.TopiaEntity) - */ - public void add(TopiaEntity e) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible d'ajouter une entite"); - String id = e.getTopiaId(); - Class entityClass = TopiaId.getClassName(id); - TopiaDAO dao = getDAO(entityClass); - dao.update(e); - } - - /** (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#importXML(java.io.Reader) - */ - public void importXML(Reader xml) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible d'effectuer l'import"); - Document doc; - - SAXReader xmlReader = new SAXReader(); - try { - doc = xmlReader.read(xml); - if (log.isDebugEnabled()) { - log.debug("Lecture du document terminee"); - } - } catch (DocumentException de) { - throw new TopiaException("Lecture du document impossible", de); - } - - if (doc != null) { - Session sessionDom4j = getHibernate().getSession(EntityMode.DOM4J); - Element rootElement = doc.getRootElement(); - Iterator it = rootElement.elementIterator(); - while (it.hasNext()) { - Element entity = (Element) it.next(); - try { - sessionDom4j.replicate(entity, ReplicationMode.EXCEPTION); - } catch (HibernateException he) { - log.warn("Echec de replication sur " + entity, he); - } - } - } else { - throw new TopiaException("Document vide"); - } - } - - /** (non-Javadoc) - * @see org.codelutin.topia.TopiaContext#exportXML(java.io.Writer, java.lang.Object...) - */ - public void exportXML(Writer xml, Object... entityAndcondition) - throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible d'effectuer l'export"); - try { - Class entityClass; - String condition; - - // si entityAndcondition est vide alors il faut le remplir - // avec toutes les entités du mapping (class, null) - if (entityAndcondition.length == 0) { - entityAndcondition = new Object[getHibernateFactory() - .getAllClassMetadata().size() * 2]; - int i = 0; - for (Object className : getHibernateFactory() - .getAllClassMetadata().keySet()) { - entityAndcondition[i++] = Class.forName((String) className); - entityAndcondition[i++] = null; - } - } - - Session sessionDom4j = getHibernate().getSession(EntityMode.DOM4J); - - Document doc = DocumentFactory.getInstance().createDocument(); - Element rootElement = doc.addElement("topiaExport"); - DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); - String date = format.format(new Date(System.currentTimeMillis())); - rootElement.addAttribute("date", date); - - for (int i = 0; i < entityAndcondition.length;) { - try { - entityClass = (Class) entityAndcondition[i++]; - condition = (String) entityAndcondition[i++]; - - String query = "from " + entityClass.getName(); - if (condition != null && "".equals(condition) == false) { - query += " where " + condition; - } - - for (Object o : sessionDom4j.createQuery(query).list()) { - rootElement.add((Element) o); - } - } catch (ClassCastException eee) { - if (i % 2 == 0) { - throw new IllegalArgumentException( - "Others arguement must be String not " - + entityAndcondition[i - 1], eee); - } else { - throw new IllegalArgumentException( - "Others arguement must be Class not " - + entityAndcondition[i - 1], eee); - } - } catch (IndexOutOfBoundsException eee) { - throw new IllegalArgumentException( - "Others arguement must be couple of (Class, String)", - eee); - } - } - - XMLWriter result = new XMLWriter(xml, OutputFormat - .createPrettyPrint()); - result.write(doc); - result.close(); - - } catch (HibernateException eee) { - throw new TopiaException("Can't export XML", eee); - } catch (IOException eee) { - throw new TopiaException("Can't export XML", eee); - } catch (ClassNotFoundException eee) { - // cette exception ne devrait pas survenir - throw new TopiaException("Can't export XML", eee); - } - } - - /* - * (non-Javadoc) - * @see org.codelutin.topia.framework.TopiaContextImplementor#getFiresSupport() - */ - public TopiaFiresSupport getFiresSupport() { - return firesSupport; - } - - /** - * Backup database in gzip compressed file - * Only work for h2 database - * - * @param file file to write backup - * @param compress if true then use gzip to compress file - * - * @see TopiaContext#backup(java.io.File,boolean) - */ - public void backup(File file, boolean compress) throws TopiaException { - checkClosed("Ce contexte a ete ferme, impossible d'effectuer le backup"); - try { - // Statement stat = getHibernate().connection().createStatement(); - // ResultSet rs = stat.executeQuery("SCRIPT TO '" + file.getAbsolutePath() + "'"); - - // Bug dans h2 v0.9, on ne peut pas directement passer le fichier dans le SQL - // Il y a un ArrayOutBoundException -> org.h2.command.dml.Script.add:203 - // pour certaines lignes. C dommage, car on est obligé de rammener - // tout en texte, ce qui peut-etre gros pour la memoire :( - - String options = ""; - if (compress) { - options += " COMPRESSION GZIP"; - } - - SQLQuery query = getHibernate().createSQLQuery( - "SCRIPT TO '" + file.getAbsolutePath() + "'" + options); - query.list(); - - // List<String> lines = query.list(); - - // // en fait on est un peu obligé d'exporter toute la base - // // (creation du schema compris) car sinon lors de la restauration - // // si le schema a ete creer avant il contient aussi les - // // contrainte et du coup les inserts se passent mal :( - // // Si on ne voulait que les inserts, lors de la resauration il - // // faudrait desactiver les contraintes et les reactiver ensuite - // - // OutputStream os = new BufferedOutputStream ( - // new FileOutputStream(file)); - // - // PrintStream out; - // if (compress) { - // out = new PrintStream(new GZIPOutputStream(os)); - // } else { - // out = new PrintStream(os); - // } - // - // for (String line : lines) { - // out.println(line + ";"); - // } - // out.close(); - } catch (Exception eee) { - throw new TopiaException("Can't backup", eee); - } - } - - /** - * Read database from gzip compressed file - * - * Only work for h2 database - * - * @see org.codelutin.topia.TopiaContext#restore(java.io.File) - */ - public void restore(File file) throws TopiaException { - // send event - getFiresSupport().firePreRestoreSchema(this); - - checkClosed("Ce contexte a ete ferme, impossible d'effectuer le restore"); - String sql = null; - try { - // decompresse file in temporary file - InputStream in = new BufferedInputStream(new FileInputStream(file)); - in.mark(2); - - // read header to see if is compressed file - int b = in.read(); - int magic = ((int) in.read() << 8) | b; - in.reset(); - - String options = ""; - - if (magic == GZIPInputStream.GZIP_MAGIC) { - // in = new GZIPInputStream(in); - options += " COMPRESSION GZIP"; - } - in.close(); - - SQLQuery query = getHibernate() - .createSQLQuery( - "RUNSCRIPT FROM '" + file.getAbsolutePath() + "'" - + options); - query.executeUpdate(); - - // send event AFTER restore - getFiresSupport().firePostRestoreSchema(this); - - // BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - // Connection conn = getHibernate().connection(); - // conn.setAutoCommit(false); - // Statement stat = conn.createStatement(); - // - // while((sql = reader.readLine()) != null) { - // // FIXME remove next line when h2 will do the bug correction (normaly in october 2006) - // // this permit database restauration - //// if (sql.startsWith("ALTER TABLE")) { - //// sql = sql.replaceAll("INDEX CONSTRAINT_INDEX_\\d*", ""); - //// } - // stat.execute(sql); - // } - // stat.close(); - // conn.commit(); - // conn.close(); - - // // by default we supposed that file is not compressed - // File tmp = file; - // if (magic == GZIPInputStream.GZIP_MAGIC) { - // // in fact file is compressed, use temporaly file - // tmp = File.createTempFile("tmp-topia-restore", ".sql"); - // tmp.deleteOnExit(); - // - // // decompresse file in temporary file - // InputStream gzin = new GZIPInputStream(in); - // - // OutputStream out = new BufferedOutputStream( - // new FileOutputStream(tmp)); - // - // byte [] buffer = new byte[64 * 1024]; - // int len = 0; - // while ((len = gzin.read(buffer)) != -1) { - // out.write(buffer, 0, len); - // } - // out.close(); - // gzin.close(); - // } - // - // // restore data - // Statement stat = getHibernate().connection().createStatement(); - // stat.execute("RUNSCRIPT FROM '" + tmp.getAbsolutePath() + "'"); - // - //// SQLQuery query = getHibernate().createSQLQuery("RUNSCRIPT FROM '" + file.getAbsolutePath() + "'"); - //// List result = query.list(); - } catch (Exception eee) { - throw new TopiaException("Can't restore. Last sql instruction was:" - + sql, eee); - } - } - - /** - * Only h2 supported for now - * @see org.codelutin.topia.TopiaContext#clear(boolean) - */ - public void clear(boolean dropDatabase) throws TopiaException { - try { - TopiaContextImpl root = (TopiaContextImpl) getRootContext(); - TopiaContextImpl tx = (TopiaContextImpl) root.beginTransaction(); - - String sql = "DROP ALL OBJECTS"; - if (dropDatabase) { - sql += " DELETE FILES"; - } - Query query = tx.getHibernate().createSQLQuery(sql); - query.executeUpdate(); - tx.closeContext(); - root.finalize(); - } catch (Throwable eee) { - throw new TopiaException("Can't clear topia context", eee); - } - } - - public List<Class> getPersistenceClasses() { - return persistenceClasses; - } - - /* Adders */ - public void addTopiaEntityListener(TopiaEntityListener listener) { - getFiresSupport().addTopiaEntityListener(listener); - } - - public void addTopiaEntityListener( - Class<? extends TopiaEntity> entityClass, - TopiaEntityListener listener) { - getFiresSupport().addTopiaEntityListener(entityClass, listener); - } - - public void addTopiaEntityVetoable(TopiaEntityVetoable vetoable) { - getFiresSupport().addTopiaEntityVetoable(TopiaEntity.class, vetoable); - } - - public void addTopiaEntityVetoable( - Class<? extends TopiaEntity> entityClass, - TopiaEntityVetoable vetoable) { - getFiresSupport().addTopiaEntityVetoable(entityClass, vetoable); - } - - public void addTopiaTransactionListener(TopiaTransactionListener listener) { - getFiresSupport().addTopiaTransactionListener(listener); - } - - public void addTopiaTransactionVetoable(TopiaTransactionVetoable vetoable) { - getFiresSupport().addTopiaTransactionVetoable(vetoable); - } - - public void addPropertyChangeListener(PropertyChangeListener listener) { - getFiresSupport().addPropertyChangeListener(listener); - } - - public void addTopiaContextListener(TopiaContextListener listener) { - getFiresSupport().addTopiaContextListener(listener); - } - - /* Removers */ - public void removeTopiaEntityListener(TopiaEntityListener listener) { - getFiresSupport() - .removeTopiaEntityListener(TopiaEntity.class, listener); - } - - public void removeTopiaEntityListener( - Class<? extends TopiaEntity> entityClass, - TopiaEntityListener listener) { - getFiresSupport().removeTopiaEntityListener(entityClass, listener); - } - - public void removeTopiaEntityVetoable(TopiaEntityVetoable vetoable) { - getFiresSupport() - .removeTopiaEntityVetoable(TopiaEntity.class, vetoable); - } - - public void removeTopiaEntityVetoable( - Class<? extends TopiaEntity> entityClass, - TopiaEntityVetoable vetoable) { - getFiresSupport().removeTopiaEntityVetoable(entityClass, vetoable); - } - - public void removeTopiaTransactionListener(TopiaTransactionListener listener) { - getFiresSupport().removeTopiaTransactionListener(listener); - } - - public void removeTopiaTransactionVetoable(TopiaTransactionVetoable vetoable) { - getFiresSupport().removeTopiaTransactionVetoable(vetoable); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - getFiresSupport().removePropertyChangeListener(listener); - } - - public void removeTopiaContextListener(TopiaContextListener listener) { - getFiresSupport().removeTopiaContextListener(listener); - } - - public void addTopiaEntitiesVetoable(TopiaEntitiesVetoable vetoable) { - getFiresSupport().addTopiaEntitiesVetoable(vetoable); - } - - public void removeTopiaEntitiesVetoable(TopiaEntitiesVetoable vetoable) { - getFiresSupport().removeTopiaEntitiesVetoable(vetoable); - } - -} //TopiaContextImpl Copied: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java (from rev 1298, topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java) =================================================================== --- topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java (rev 0) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/framework/TopiaContextImpl.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,1336 @@ +/* *##% ToPIA - Tools for Portable and Independent Architecture + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ + +/******************************************************************************* + * TopiaContextImpl.java + * + * Created: 23 déc. 2005 16:58:50 + * + * @author poussin + * + * @version $Revision$ + * + * Last update: $Date$ by : $Author$ + */ + +package org.codelutin.topia.framework; + +import org.apache.commons.collections.set.MapBackedSet; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.TopiaContext; +import org.codelutin.topia.TopiaContextFactory; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.TopiaNotFoundException; +import org.codelutin.topia.event.TopiaContextListener; +import org.codelutin.topia.event.TopiaEntitiesVetoable; +import org.codelutin.topia.event.TopiaEntityListener; +import org.codelutin.topia.event.TopiaEntityVetoable; +import org.codelutin.topia.event.TopiaTransactionListener; +import org.codelutin.topia.event.TopiaTransactionVetoable; +import org.codelutin.topia.persistence.TopiaDAO; +import org.codelutin.topia.persistence.TopiaDAODelegator; +import org.codelutin.topia.persistence.TopiaEntity; +import org.codelutin.topia.persistence.TopiaId; +import org.codelutin.util.ArrayUtil; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentFactory; +import org.dom4j.Element; +import org.dom4j.io.OutputFormat; +import org.dom4j.io.SAXReader; +import org.dom4j.io.XMLWriter; +import org.hibernate.EntityMode; +import org.hibernate.FlushMode; +import org.hibernate.HibernateException; +import org.hibernate.Query; +import org.hibernate.ReplicationMode; +import org.hibernate.SQLQuery; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.hibernate.cfg.Configuration; +import org.hibernate.event.PostDeleteEventListener; +import org.hibernate.event.PostInsertEventListener; +import org.hibernate.event.PostLoadEventListener; +import org.hibernate.event.PostUpdateEventListener; +import org.hibernate.event.PreDeleteEventListener; +import org.hibernate.event.PreInsertEventListener; +import org.hibernate.event.PreLoadEventListener; +import org.hibernate.event.PreUpdateEventListener; +import org.hibernate.tool.hbm2ddl.SchemaExport; +import org.hibernate.tool.hbm2ddl.SchemaUpdate; + +import java.beans.PropertyChangeListener; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.Writer; +import java.lang.reflect.Field; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.zip.GZIPInputStream; + +/** + * Le TopiaContextImpl est le point d'entre pour acceder aux donnees. Il est + * configurer par un fichier de propriete + * <p> + * List des proprietes disponible + * <dl> + * <dt> topia.persistence.properties.file + * <dd> le fichier de propriété a utiliser pour configurer hibernate + * + * <dt> topia.persistence.directories + * <dd> la liste des repertoires contenant les mappings hibernates (.hbm.xml) la + * liste de repertoire est separer par des virgules ',' + * + * <dt> topia.persistence.classes + * <dd> la liste des classes que doit géré hibernate. On peut tres bien utiliser + * topia.persistence.directories pour un ensemble d'entié du meme repertoire et + * topia.persistence.classes pour d'autres classes + * </dl> + * + * //@see TopiaSecurityManager + * //@see TopiaIndexService + * //@see TopiaHistoryService + * + * @author poussin + */ +public class TopiaContextImpl implements TopiaContext, TopiaContextImplementor { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + static private Log log = LogFactory.getLog(TopiaContextImpl.class); + + static final private String TOPIA_PERSISTENCE_DIRECTORIES = "topia.persistence.directories"; + + static final private String TOPIA_PERSISTENCE_CLASSES = "topia.persistence.classes"; + + static final private String TOPIA_PERSISTENCE_PROPERTIES_FILE = "topia.persistence.properties.file"; + + /** + * Le pere de ce context, les contexts initaux n'ont pas de context pere + */ + protected TopiaContextImplementor parentContext = null; + + /** + * L'objet configuration utilisé pour la creation de la factory hibernate + */ + protected Configuration hibernateConfiguration = null; + + /** + * la factory permettant de recuperer la session hibernate. Seul les + * TopiaContextImpl initiaux contiennent un hibernateFactory + */ + protected SessionFactory hibernateFactory = null; + + /** + * La session utilisé par le TopiaContextImpl + */ + protected Session hibernate = null; + + /** + * Indique si le contexte a ete ferme + */ + protected boolean closed = false; + + /** + * Propriete de configuration + */ + protected Properties config = null; + + /** + * cache des DAO deja chargé pour ce context + */ + protected Map<Class, TopiaDAO> daoCache = new HashMap<Class, TopiaDAO>(); + + /** + * Set des sous context creer avec un beginTransaction et donc sur lequel + * nous sommes listener + */ + protected Set<TopiaContextImplementor> childContext = MapBackedSet + .decorate(new WeakHashMap<TopiaContextImplementor, Object>()); + + /** key: service name; value: service instance */ + protected Map<String, TopiaService> services = null; + + /** */ + protected TopiaFiresSupport firesSupport = new TopiaFiresSupport(); + + /** Liste des classes perssitance */ + protected List<Class> persistenceClasses = new ArrayList<Class>(); + + /** + * constructeur utilisé par la factory pour creer les contexts initiaux + * + * @param config + * @throws TopiaNotFoundException + */ + public TopiaContextImpl(Properties config) throws TopiaNotFoundException { + this.config = config; + services = loadServices(config); + preInitServices(services); + getHibernateConfiguration(); // force mapping loading + postInitServices(services); + } + + protected Map<String, TopiaService> loadServices(Properties config) { + Map<String, TopiaService> result = new HashMap<String, TopiaService>(); + // recherche des services present dans la config + for (Enumeration<String> e = (Enumeration<String>) config + .propertyNames(); e.hasMoreElements();) { + String key = e.nextElement(); + if (key.matches("^topia\\.service\\.\\w+$")) { + String classService = config.getProperty(key); + try { + Class forName = Class.forName(classService); + Object newInstance = forName.newInstance(); + TopiaService service = (TopiaService) newInstance; + if (key.equals("topia.service." + service.getServiceName())) { + result.put(service.getServiceName(), service); + log.info("Service " + key + " loaded by " + + classService); + } else { + log + .warn("Service config key doesn't match service name, disable it: " + + key + + " != " + + service.getServiceName()); + } + } catch (Throwable eee) { + if (log.isErrorEnabled()) { + log.error("Service class unknow for " + key + ": " + + classService); + } + if (log.isDebugEnabled()) { + log.debug(eee); + } + } + } + } + return result; + } + + protected void preInitServices(Map<String, TopiaService> services) { + for (TopiaService service : services.values()) { + if (!service.preInit(this)) { + log.warn("Can't preInit service disable it: " + + service.getServiceName()); + } + } + } + + protected void postInitServices(Map<String, TopiaService> services) { + for (TopiaService service : services.values()) { + if (!service.postInit(this)) { + log.warn("Can't postInit service disable it: " + + service.getServiceName()); + } + } + } + + public Map<String, TopiaService> getServices() { + TopiaContextImplementor parent = getParentContext(); + + Map<String, TopiaService> result = null; + if (parent != null) { + result = parent.getServices(); + } else { + result = services; + } + return result; + } + + protected boolean serviceEnabled(String name) { + boolean result = getServices().containsKey(name); + return result; + } + + protected TopiaService getService(String name) { + TopiaService result = getServices().get(name); + return result; + } + + public <E extends TopiaService> boolean serviceEnabled( + Class<E> interfaceService) { + boolean result = false; + try { + Field f = interfaceService.getField("SERVICE_NAME"); + String name = (String) f.get(null); + result = serviceEnabled(name); + } catch (Exception eee) { + if (log.isWarnEnabled()) { + log + .warn( + "Can't get service name for: " + + interfaceService, eee); + } + } + return result; + } + + /** + * Take one service, this service must be valid service interface with + * public static final SERVICE_NAME declaration. + * @param <E> + * @throws TopiaNotFoundException + */ + public <E extends TopiaService> E getService(Class<E> interfaceService) + throws TopiaNotFoundException { + try { + Field f = interfaceService.getField("SERVICE_NAME"); + String name = (String) f.get(null); + E result = (E) getService(name); + if (result == null) { + throw new TopiaNotFoundException("Service not available: " + + interfaceService); + } + return result; + } catch (Exception eee) { + throw new TopiaNotFoundException("Can't get service: " + + interfaceService, eee); + } + } + + /* (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaContextImplementor#getAllServices() + */ + public Collection<TopiaService> getAllServices() { + Collection<TopiaService> result = getServices().values(); + return result; + } + + /** + * Constructeur utilisé par le beginTransaction pour créer le context fils. + * + * @param parentContext + * @throws HibernateException + * @throws TopiaNotFoundException + */ + protected TopiaContextImpl(TopiaContextImplementor parentContext) + throws HibernateException, TopiaNotFoundException { + this.parentContext = parentContext; + } + + public Set<TopiaContextImplementor> getChildContext() { + return this.childContext; + } + + protected void addChildContext(TopiaContextImplementor child) { + childContext.add(child); + } + + public void removeChildContext(TopiaContextImplementor child) { + //On ne retire les fils que si ce contexte n'est pas deja ferme. Permet d'eviter les acces concurrentiels + if (!closed) { + childContext.remove(child); + } + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getParentContext() + */ + public TopiaContextImplementor getParentContext() { + return parentContext; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getRootContext() + */ + public TopiaContextImplementor getRootContext() { + TopiaContextImplementor result = this; + if (getParentContext() != null) { + result = getParentContext().getRootContext(); + } + return result; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getConfig() + */ + public Properties getConfig() { + if (config == null && getParentContext() != null) { + config = getParentContext().getConfig(); + } + return config; + } + + /* (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#createSchema() + */ + public void createSchema() throws TopiaException { + try { + boolean showSchema = false; + if (log.isDebugEnabled()) { + showSchema = true; + } + getFiresSupport().firePreCreateSchema(this); + new SchemaExport(getHibernateConfiguration()).create(showSchema, + true); + getFiresSupport().firePostCreateSchema(this); + } catch (HibernateException eee) { + throw new TopiaException("Can't create database schema", eee); + } + } + + /* (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#createSchema() + */ + public void updateSchema() throws TopiaException { + try { + boolean showSchema = false; + if (log.isDebugEnabled()) { + showSchema = true; + } + getFiresSupport().firePreUpdateSchema(this); + new SchemaUpdate(getHibernateConfiguration()).execute(showSchema, + true); + getFiresSupport().firePostUpdateSchema(this); + } catch (HibernateException eee) { + throw new TopiaException("Can't create database schema", eee); + } + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getHibernate() + */ + public Session getHibernate() throws TopiaException { + if (hibernate == null) { + throw new TopiaException( + "No hibernate session available, you must start a transaction with beginTransaction"); + } + return hibernate; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getHibernateFactory() + */ + public SessionFactory getHibernateFactory() throws TopiaNotFoundException { + if (hibernateFactory == null) { + if (getParentContext() != null) { + hibernateFactory = getParentContext().getHibernateFactory(); + } else { + hibernateFactory = getHibernateConfiguration() + .buildSessionFactory(); + } + } + return hibernateFactory; + } + + public Configuration getHibernateConfiguration() + throws TopiaNotFoundException { + if (hibernateConfiguration == null) { + if (getParentContext() != null) { + hibernateConfiguration = getParentContext() + .getHibernateConfiguration(); + } else { + hibernateConfiguration = new Configuration(); + + // Ajout du listeners pour les events + TopiaFiresSupport.TopiaHibernateEvent listener = new TopiaFiresSupport.TopiaHibernateEvent( + this); + + PreInsertEventListener[] preInsertEventListeners = hibernateConfiguration + .getEventListeners().getPreInsertEventListeners(); + preInsertEventListeners = ArrayUtil.concatElems( + preInsertEventListeners, listener); + PreLoadEventListener[] preLoadEventListeners = hibernateConfiguration + .getEventListeners().getPreLoadEventListeners(); + preLoadEventListeners = ArrayUtil.concatElems( + preLoadEventListeners, listener); + PreUpdateEventListener[] preUpdateEventListeners = hibernateConfiguration + .getEventListeners().getPreUpdateEventListeners(); + preUpdateEventListeners = ArrayUtil.concatElems( + preUpdateEventListeners, listener); + PreDeleteEventListener[] preDeleteEventListeners = hibernateConfiguration + .getEventListeners().getPreDeleteEventListeners(); + preDeleteEventListeners = ArrayUtil.concatElems( + preDeleteEventListeners, listener); + + PostInsertEventListener[] postInsertEventListeners = hibernateConfiguration + .getEventListeners().getPostInsertEventListeners(); + postInsertEventListeners = ArrayUtil.concatElems( + postInsertEventListeners, listener); + PostLoadEventListener[] postLoadEventListeners = hibernateConfiguration + .getEventListeners().getPostLoadEventListeners(); + postLoadEventListeners = ArrayUtil.concatElems( + postLoadEventListeners, listener); + PostUpdateEventListener[] postUpdateEventListeners = hibernateConfiguration + .getEventListeners().getPostUpdateEventListeners(); + postUpdateEventListeners = ArrayUtil.concatElems( + postUpdateEventListeners, listener); + PostDeleteEventListener[] postDeleteEventListeners = hibernateConfiguration + .getEventListeners().getPostDeleteEventListeners(); + postDeleteEventListeners = ArrayUtil.concatElems( + postDeleteEventListeners, listener); + + hibernateConfiguration.getEventListeners() + .setPreInsertEventListeners(preInsertEventListeners); + hibernateConfiguration.getEventListeners() + .setPreLoadEventListeners(preLoadEventListeners); + hibernateConfiguration.getEventListeners() + .setPreUpdateEventListeners(preUpdateEventListeners); + hibernateConfiguration.getEventListeners() + .setPreDeleteEventListeners(preDeleteEventListeners); + + hibernateConfiguration.getEventListeners() + .setPostInsertEventListeners(postInsertEventListeners); + hibernateConfiguration.getEventListeners() + .setPostLoadEventListeners(postLoadEventListeners); + hibernateConfiguration.getEventListeners() + .setPostUpdateEventListeners(postUpdateEventListeners); + hibernateConfiguration.getEventListeners() + .setPostDeleteEventListeners(postDeleteEventListeners); + + // ajout des repertoires contenant les mappings hibernate + String[] dirs = getConfig().getProperty( + TOPIA_PERSISTENCE_DIRECTORIES, "").split(","); + for (String dir : dirs) { + dir = dir.trim(); + if (!"".equals(dir)) { + hibernateConfiguration.addDirectory(new File(dir)); + } + } + + // ajout des classes dites persistentes + String listPersistenceClasses = getConfig().getProperty( + TOPIA_PERSISTENCE_CLASSES, ""); + + for (TopiaService service : getAllServices()) { + Class<?>[] persistenceClasses = service + .getPersistenceClasses(); + + // certains service n'ont pas de classe persistantes + if (persistenceClasses != null) { + for (Class<?> clazz : persistenceClasses) { + hibernateConfiguration.addClass(clazz); + } + } + } + + String[] classes = listPersistenceClasses.split(","); + for (String classname : classes) { + classname = classname.trim(); + if (!"".equals(classname)) { + Class<?> clazz; + try { + clazz = Class.forName(classname); + } catch (ClassNotFoundException eee) { + throw new TopiaNotFoundException( + "Persistent class " + classname + + " not found"); + } + persistenceClasses.add(clazz); + hibernateConfiguration.addClass(clazz); + } + } + + Properties prop = new Properties(); + prop.putAll(hibernateConfiguration.getProperties()); + prop.putAll(getConfig()); + prop.putAll(TopiaUtil.getProperties(getConfig().getProperty( + TOPIA_PERSISTENCE_PROPERTIES_FILE))); + hibernateConfiguration.setProperties(prop); + } + } + return hibernateConfiguration; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.framework.TopiaContextImplementor#getDAO(java.lang.Class) + */ + @SuppressWarnings("unchecked") + public <E extends TopiaEntity> TopiaDAO<E> getDAO(Class<E> entityClass) + throws TopiaException { + if (entityClass == null) { + throw new IllegalArgumentException("null is not valid entity class"); + } + if (getRootContext() == this) { + throw new TopiaException("Vous êtes sur le root context vous" + + " devez ouvrir une transaction pour pouvoir accèder" + + " aux données"); + } + if (getHibernateFactory().getClassMetadata(entityClass) == null + && getHibernateFactory().getClassMetadata( + entityClass.getName() + "Impl") == null + && getHibernateFactory().getClassMetadata( + entityClass.getName() + "Abstract") == null) { + log.info("Classes supportées par ce TopiaContext: " + + getHibernateFactory().getAllClassMetadata().keySet()); + throw new TopiaException( + "La classe " + + entityClass.getName() + + " n'est pas supportée par ce TopiaContext. Vous avez sans" + + " doute oublié d'ajouter son mapping"); + } + + TopiaDAO<E> result = daoCache.get(entityClass); + if (result == null) { + // recherche du type de DAO a instancier pour cette entity + String defaultDAOClassname = getConfig().getProperty( + "topia.dao.default.class", "hibernate"); + String daoClassname = getConfig().getProperty( + "topia.dao." + entityClass.getName(), defaultDAOClassname); + if ("hibernate".equals(daoClassname)) { + // FIXME nom en dur ? + daoClassname = "org.codelutin.topia.persistence.hibernate.TopiaDAOHibernate"; + } else if ("flatfile".equals(daoClassname)) { + daoClassname = "org.codelutin.topia.persistence.flatfile.TopiaDAOFlatFile"; + } + + try { + Class<TopiaDAO<E>> resultClass = (Class<TopiaDAO<E>>) Class + .forName(daoClassname); + result = resultClass.newInstance(); + result.init(this, entityClass); + } catch (ClassNotFoundException eee) { + throw new TopiaException("Can't find DAO class " + daoClassname); + } catch (InstantiationException eee) { + throw new TopiaException("Can't instanciate DAO class " + + daoClassname); + } catch (IllegalAccessException eee) { + throw new TopiaException("Can't access DAO class " + + daoClassname); + } + + // looking for specialized DAO + // normalement il en existe un car il est généré automatiquement + // si on utilise la génération + daoClassname = entityClass.getName() + "DAO"; + try { + Class<TopiaDAODelegator<E>> daoClass = (Class<TopiaDAODelegator<E>>) Class + .forName(daoClassname); + TopiaDAODelegator<E> spe = daoClass.newInstance(); + spe.setParentDAO(result); + result = spe; + } catch (Exception eee) { + log.warn("specialized DAO " + daoClassname + + " not found, use default TopiaDAOHibernate"); + } + daoCache.put(entityClass, result); + } + return result; + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.TopiaContext#beginTransaction() + */ + public TopiaContext beginTransaction() throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible de commencer une transaction"); + TopiaContextImpl result = new TopiaContextImpl(this); + + SessionFactory factory = getHibernateFactory(); + result.hibernate = factory.openSession(); + // new TopiaInterceptor(result)); + // on ne synchronise jamais les données avec la base tant que + // l'utilisateur n'a pas fait de commit du context + result.hibernate.setFlushMode(FlushMode.MANUAL); + + // 20060926 poussin ajouter pour voir si ca regle les problemes de deadlock h2 + // Conclusion, il faut bien ouvrir une transaction maintenant, sinon + // lorsque l'on fait des acces a la base, une transaction par defaut est + // utilisé mais elle n'est jamais vraiment fermé ce qui pose des problemes + // de lock sur les tables. + result.hibernate.beginTransaction(); + + // 20081217 : add child AFTER hibernate session is opened + addChildContext(result); + + // fire event + getFiresSupport().fireOnBeginTransaction(result); + + return result; + } + + // Transaction tx = null; + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.TopiaContext#commitTransaction() + */ + public void commitTransaction() throws TopiaException { + if (getRootContext() == this) { + throw new TopiaException( + "Vous êtes sur le root context le commit est impossible"); + } + checkClosed("Ce contexte a ete ferme, impossible de faire un commit"); + try { + for (TopiaDAO<TopiaEntity> dao : daoCache.values()) { + dao.commitTransaction(); + } + Transaction tx = hibernate.getTransaction(); + // Transaction tx = hibernate.beginTransaction(); + hibernate.flush(); + tx.commit(); + + getFiresSupport().fireOnPostCommit(this); + TopiaContextImplementor parent = getParentContext(); + if (parent != null) { + parent.getFiresSupport().fireOnPostCommit(this); + } + + hibernate.beginTransaction(); + // it's seem necessary to change session after commit + // NON, NON, NON, il ne faut surtout pas le faire, ca pose plein de probleme + // hibernate = getHibernateFactory().openSession(); + // hibernate.setFlushMode(FlushMode.NEVER); + } catch (Exception eee) { + throw new TopiaException("Error during commit", eee); + } + } + + /* + * (non-Javadoc) + * + * @see org.codelutin.topia.TopiaContext#rollbackTransaction() + */ + public void rollbackTransaction() throws TopiaException { + if (getRootContext() == this) { + throw new TopiaException( + "Vous êtes sur le root context le rollback est impossible"); + } + checkClosed("Ce contexte a ete ferme, impossible de faire un rollback"); + try { + for (TopiaDAO<TopiaEntity> dao : daoCache.values()) { + dao.rollbackTransaction(); + } + Transaction tx = hibernate.getTransaction(); + // Transaction tx = hibernate.beginTransaction(); + hibernate.clear(); + tx.rollback(); + hibernate.close(); + // it's very important to change the session after rollback + // otherwize there are many error during next Entity's modification + hibernate = getHibernateFactory().openSession(); + hibernate.setFlushMode(FlushMode.MANUAL); + + hibernate.beginTransaction(); + + getFiresSupport().fireOnPostRollback(this); + TopiaContextImplementor parent = getParentContext(); + if (parent != null) { + parent.getFiresSupport().fireOnPostRollback(this); + } + + } catch (HibernateException eee) { + throw new TopiaException(eee); + } + } + + public void closeContext() throws TopiaException { + // 20060926 poussin: Si si on peut, ca ferme en fait tous les enfants et c tout + // if (getRootContext() == this) { + // throw new TopiaException( + // "Vous ne pouvez pas fermer le root context"); + // } + + checkClosed("Ce contexte a deja ete ferme"); + + // suppression des contexts fils + TopiaContextImplementor[] childs = childContext + .toArray(new TopiaContextImplementor[childContext.size()]); + for (TopiaContextImplementor child : childs) { + if (!child.isClosed()) { + child.closeContext(); + } + } + // for (Iterator iter = childContext.iterator(); iter.hasNext();) { + // TopiaContextImplementor child = (TopiaContextImplementor) iter.next(); + // child.closeContext(); + // iter.remove(); + // } + + // on se desenregistre du context pere et on ferme les connexions si + // on est pas le root context + if (getRootContext() != this) { + this.closed = true; + hibernate.close(); + getParentContext().removeChildContext(this); + } else { + if (hibernateFactory != null) { + hibernateFactory.close(); + this.closed = true; + TopiaContextFactory.removeContext(this); + log.debug("TopiaContext finalized"); + } + } + } + + /** + * Pour le context root on ferme tous les fils, et la factory hibernate + * @see java.lang.Object#finalize() + */ + @Override + protected void finalize() throws Throwable { + if (hibernateFactory != null) { + closeContext(); + hibernateFactory.close(); + this.closed = true; + log.debug("TopiaContext finalized"); + } + } + + public boolean isClosed() { + return closed; + } + + private void checkClosed(String message) throws TopiaException { + if (closed) { + throw new TopiaException(message); + } + } + + /* (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#findByTopiaId(java.lang.String) + */ + public TopiaEntity findByTopiaId(String topiaId) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); + TopiaEntity result; + Class<? extends TopiaEntity> entityClass = TopiaId + .getClassName(topiaId); + TopiaDAO dao = getDAO(entityClass); + result = dao.findByTopiaId(topiaId); + return result; + } + + /* + * (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#find(java.lang.String, java.lang.Object[]) + */ + public List find(String hql, Object... args) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); + try { + Query query = getHibernate().createQuery(hql); + for (int j = 0; j < args.length; j += 2) { + String name = (String) args[j]; + Object value = args[j + 1]; + if (value.getClass().isArray()) { + query.setParameterList(name, (Object[]) value); + } else { + query.setParameter(name, value); + } + } + List result = query.list(); + result = firesSupport.fireEntitiesLoad(this, result); + return result; + } catch (HibernateException eee) { + throw new TopiaException("Error during query execution: " + hql, + eee); + } + } + + public List find(String hql, int startIndex, int endIndex, Object... args) + throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); + try { + Query query = getHibernate().createQuery(hql); + for (int j = 0; j < args.length; j += 2) { + String name = (String) args[j]; + Object value = args[j + 1]; + if (value.getClass().isArray()) { + query.setParameterList(name, (Object[]) value); + } else { + query.setParameter(name, value); + } + } + query.setFirstResult(startIndex); + query.setMaxResults(endIndex - startIndex + 1); + List result = query.list(); + result = firesSupport.fireEntitiesLoad(this, result); + return result; + } catch (HibernateException eee) { + throw new TopiaException("Error during query execution: " + hql, + eee); + } + } + + /** + * Execute HQL operation on data (Update, Delete) + * @param hql + * @param args + * @return The number of entities updated or deleted. + * @throws TopiaException + */ + public int execute(String hql, Object... args) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible de faire une recherche"); + try { + Query query = getHibernate().createQuery(hql); + for (int j = 0; j < args.length; j += 2) { + query.setParameter((String) args[j], args[j + 1]); + } + int result = query.executeUpdate(); + return result; + } catch (HibernateException eee) { + throw new TopiaException("Error during query execution: " + hql, + eee); + } + } + + /* (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#add(org.codelutin.topia.persistence.TopiaEntity) + */ + public void add(TopiaEntity e) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible d'ajouter une entite"); + String id = e.getTopiaId(); + Class entityClass = TopiaId.getClassName(id); + TopiaDAO dao = getDAO(entityClass); + dao.update(e); + } + + /** (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#importXML(java.io.Reader) + */ + public void importXML(Reader xml) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible d'effectuer l'import"); + Document doc; + + SAXReader xmlReader = new SAXReader(); + try { + doc = xmlReader.read(xml); + if (log.isDebugEnabled()) { + log.debug("Lecture du document terminee"); + } + } catch (DocumentException de) { + throw new TopiaException("Lecture du document impossible", de); + } + + if (doc != null) { + Session sessionDom4j = getHibernate().getSession(EntityMode.DOM4J); + Element rootElement = doc.getRootElement(); + Iterator it = rootElement.elementIterator(); + while (it.hasNext()) { + Element entity = (Element) it.next(); + try { + sessionDom4j.replicate(entity, ReplicationMode.EXCEPTION); + } catch (HibernateException he) { + log.warn("Echec de replication sur " + entity, he); + } + } + } else { + throw new TopiaException("Document vide"); + } + } + + /** (non-Javadoc) + * @see org.codelutin.topia.TopiaContext#exportXML(java.io.Writer, java.lang.Object...) + */ + public void exportXML(Writer xml, Object... entityAndcondition) + throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible d'effectuer l'export"); + + Class entityClass; + String condition; + + // si entityAndcondition est vide alors il faut le remplir + // avec toutes les entités du mapping (class, null) + if (entityAndcondition.length == 0) { + entityAndcondition = new Object[getHibernateFactory() + .getAllClassMetadata().size() * 2]; + int i = 0; + for (Object className : getHibernateFactory() + .getAllClassMetadata().keySet()) { + try { + entityAndcondition[i++] = Class.forName((String) className); + entityAndcondition[i++] = null; + } catch (ClassNotFoundException e) { + // cette exception ne devrait pas survenir + throw new TopiaException("Can't export XML", e); + } + } + } + + // prepare queries to perform beofre opening any transaction + if (entityAndcondition.length % 2 != 0) { + throw new IllegalArgumentException("entityAndcondition muts be a couple of (Class, String)"); + } + String queries[] = new String[entityAndcondition.length / 2]; + for (int i = 0; i < entityAndcondition.length;) { + try { + entityClass = (Class) entityAndcondition[i++]; + condition = (String) entityAndcondition[i++]; + String query = "from " + entityClass.getName(); + if (condition != null && !condition.isEmpty()) { + query += " where " + condition; + } + queries[(i-1) / 2] = query; + } catch (ClassCastException e) { + if (i % 2 == 0) { + throw new IllegalArgumentException( + "Others arguement must be String not " + + entityAndcondition[i - 1], e); + } else { + throw new IllegalArgumentException( + "Others arguement must be Class not " + + entityAndcondition[i - 1], e); + } + } + } + + // performs queries + try { + Session sessionDom4j = getHibernate().getSession(EntityMode.DOM4J); + + Document doc = DocumentFactory.getInstance().createDocument(); + Element rootElement = doc.addElement("topiaExport"); + DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); + String date = format.format(new Date(System.currentTimeMillis())); + rootElement.addAttribute("date", date); + + for (String query : queries) { + List list = sessionDom4j.createQuery(query).list(); + for (Object o : list) { + rootElement.add((Element) o); + } + } + + /*for (int i = 0; i < entityAndcondition.length;) { + try { + entityClass = (Class) entityAndcondition[i++]; + condition = (String) entityAndcondition[i++]; + + String query = "from " + entityClass.getName(); + if (condition != null && !condition.isEmpty()) { + query += " where " + condition; + } + + for (Object o : sessionDom4j.createQuery(query).list()) { + rootElement.add((Element) o); + } + } catch (ClassCastException eee) { + if (i % 2 == 0) { + throw new IllegalArgumentException( + "Others arguement must be String not " + + entityAndcondition[i - 1], eee); + } else { + throw new IllegalArgumentException( + "Others arguement must be Class not " + + entityAndcondition[i - 1], eee); + } + } catch (IndexOutOfBoundsException eee) { + throw new IllegalArgumentException( + "Others arguement must be couple of (Class, String)", + eee); + } + }*/ + + XMLWriter result = new XMLWriter(xml, OutputFormat + .createPrettyPrint()); + result.write(doc); + result.close(); + + } catch (HibernateException eee) { + throw new TopiaException("Can't export XML", eee); + } catch (IOException eee) { + throw new TopiaException("Can't export XML", eee); + } + } + + /* + * (non-Javadoc) + * @see org.codelutin.topia.framework.TopiaContextImplementor#getFiresSupport() + */ + public TopiaFiresSupport getFiresSupport() { + return firesSupport; + } + + /** + * Backup database in gzip compressed file + * Only work for h2 database + * + * @param file file to write backup + * @param compress if true then use gzip to compress file + * + * @see TopiaContext#backup(java.io.File,boolean) + */ + public void backup(File file, boolean compress) throws TopiaException { + checkClosed("Ce contexte a ete ferme, impossible d'effectuer le backup"); + try { + // Statement stat = getHibernate().connection().createStatement(); + // ResultSet rs = stat.executeQuery("SCRIPT TO '" + file.getAbsolutePath() + "'"); + + // Bug dans h2 v0.9, on ne peut pas directement passer le fichier dans le SQL + // Il y a un ArrayOutBoundException -> org.h2.command.dml.Script.add:203 + // pour certaines lignes. C dommage, car on est obligé de rammener + // tout en texte, ce qui peut-etre gros pour la memoire :( + + String options = ""; + if (compress) { + options += " COMPRESSION GZIP"; + } + + SQLQuery query = getHibernate().createSQLQuery( + "SCRIPT TO '" + file.getAbsolutePath() + "'" + options); + query.list(); + + // List<String> lines = query.list(); + + // // en fait on est un peu obligé d'exporter toute la base + // // (creation du schema compris) car sinon lors de la restauration + // // si le schema a ete creer avant il contient aussi les + // // contrainte et du coup les inserts se passent mal :( + // // Si on ne voulait que les inserts, lors de la resauration il + // // faudrait desactiver les contraintes et les reactiver ensuite + // + // OutputStream os = new BufferedOutputStream ( + // new FileOutputStream(file)); + // + // PrintStream out; + // if (compress) { + // out = new PrintStream(new GZIPOutputStream(os)); + // } else { + // out = new PrintStream(os); + // } + // + // for (String line : lines) { + // out.println(line + ";"); + // } + // out.close(); + } catch (Exception eee) { + throw new TopiaException("Can't backup", eee); + } + } + + /** + * Read database from gzip compressed file + * + * Only work for h2 database + * + * @see org.codelutin.topia.TopiaContext#restore(java.io.File) + */ + public void restore(File file) throws TopiaException { + // send event + getFiresSupport().firePreRestoreSchema(this); + + checkClosed("Ce contexte a ete ferme, impossible d'effectuer le restore"); + String sql = null; + try { + // decompresse file in temporary file + InputStream in = new BufferedInputStream(new FileInputStream(file)); + in.mark(2); + + // read header to see if is compressed file + int b = in.read(); + int magic = ((int) in.read() << 8) | b; + in.reset(); + + String options = ""; + + if (magic == GZIPInputStream.GZIP_MAGIC) { + // in = new GZIPInputStream(in); + options += " COMPRESSION GZIP"; + } + in.close(); + + SQLQuery query = getHibernate() + .createSQLQuery( + "RUNSCRIPT FROM '" + file.getAbsolutePath() + "'" + + options); + query.executeUpdate(); + + // send event AFTER restore + getFiresSupport().firePostRestoreSchema(this); + + // BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + // Connection conn = getHibernate().connection(); + // conn.setAutoCommit(false); + // Statement stat = conn.createStatement(); + // + // while((sql = reader.readLine()) != null) { + // // FIXME remove next line when h2 will do the bug correction (normaly in october 2006) + // // this permit database restauration + //// if (sql.startsWith("ALTER TABLE")) { + //// sql = sql.replaceAll("INDEX CONSTRAINT_INDEX_\\d*", ""); + //// } + // stat.execute(sql); + // } + // stat.close(); + // conn.commit(); + // conn.close(); + + // // by default we supposed that file is not compressed + // File tmp = file; + // if (magic == GZIPInputStream.GZIP_MAGIC) { + // // in fact file is compressed, use temporaly file + // tmp = File.createTempFile("tmp-topia-restore", ".sql"); + // tmp.deleteOnExit(); + // + // // decompresse file in temporary file + // InputStream gzin = new GZIPInputStream(in); + // + // OutputStream out = new BufferedOutputStream( + // new FileOutputStream(tmp)); + // + // byte [] buffer = new byte[64 * 1024]; + // int len = 0; + // while ((len = gzin.read(buffer)) != -1) { + // out.write(buffer, 0, len); + // } + // out.close(); + // gzin.close(); + // } + // + // // restore data + // Statement stat = getHibernate().connection().createStatement(); + // stat.execute("RUNSCRIPT FROM '" + tmp.getAbsolutePath() + "'"); + // + //// SQLQuery query = getHibernate().createSQLQuery("RUNSCRIPT FROM '" + file.getAbsolutePath() + "'"); + //// List result = query.list(); + } catch (Exception eee) { + throw new TopiaException("Can't restore. Last sql instruction was:" + + sql, eee); + } + } + + /** + * Only h2 supported for now + * @see org.codelutin.topia.TopiaContext#clear(boolean) + */ + public void clear(boolean dropDatabase) throws TopiaException { + try { + TopiaContextImpl root = (TopiaContextImpl) getRootContext(); + TopiaContextImpl tx = (TopiaContextImpl) root.beginTransaction(); + + String sql = "DROP ALL OBJECTS"; + if (dropDatabase) { + sql += " DELETE FILES"; + } + Query query = tx.getHibernate().createSQLQuery(sql); + query.executeUpdate(); + tx.closeContext(); + root.finalize(); + } catch (Throwable eee) { + throw new TopiaException("Can't clear topia context", eee); + } + } + + public List<Class> getPersistenceClasses() { + return persistenceClasses; + } + + /* Adders */ + public void addTopiaEntityListener(TopiaEntityListener listener) { + getFiresSupport().addTopiaEntityListener(listener); + } + + public void addTopiaEntityListener( + Class<? extends TopiaEntity> entityClass, + TopiaEntityListener listener) { + getFiresSupport().addTopiaEntityListener(entityClass, listener); + } + + public void addTopiaEntityVetoable(TopiaEntityVetoable vetoable) { + getFiresSupport().addTopiaEntityVetoable(TopiaEntity.class, vetoable); + } + + public void addTopiaEntityVetoable( + Class<? extends TopiaEntity> entityClass, + TopiaEntityVetoable vetoable) { + getFiresSupport().addTopiaEntityVetoable(entityClass, vetoable); + } + + public void addTopiaTransactionListener(TopiaTransactionListener listener) { + getFiresSupport().addTopiaTransactionListener(listener); + } + + public void addTopiaTransactionVetoable(TopiaTransactionVetoable vetoable) { + getFiresSupport().addTopiaTransactionVetoable(vetoable); + } + + public void addPropertyChangeListener(PropertyChangeListener listener) { + getFiresSupport().addPropertyChangeListener(listener); + } + + public void addTopiaContextListener(TopiaContextListener listener) { + getFiresSupport().addTopiaContextListener(listener); + } + + /* Removers */ + public void removeTopiaEntityListener(TopiaEntityListener listener) { + getFiresSupport() + .removeTopiaEntityListener(TopiaEntity.class, listener); + } + + public void removeTopiaEntityListener( + Class<? extends TopiaEntity> entityClass, + TopiaEntityListener listener) { + getFiresSupport().removeTopiaEntityListener(entityClass, listener); + } + + public void removeTopiaEntityVetoable(TopiaEntityVetoable vetoable) { + getFiresSupport() + .removeTopiaEntityVetoable(TopiaEntity.class, vetoable); + } + + public void removeTopiaEntityVetoable( + Class<? extends TopiaEntity> entityClass, + TopiaEntityVetoable vetoable) { + getFiresSupport().removeTopiaEntityVetoable(entityClass, vetoable); + } + + public void removeTopiaTransactionListener(TopiaTransactionListener listener) { + getFiresSupport().removeTopiaTransactionListener(listener); + } + + public void removeTopiaTransactionVetoable(TopiaTransactionVetoable vetoable) { + getFiresSupport().removeTopiaTransactionVetoable(vetoable); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + getFiresSupport().removePropertyChangeListener(listener); + } + + public void removeTopiaContextListener(TopiaContextListener listener) { + getFiresSupport().removeTopiaContextListener(listener); + } + + public void addTopiaEntitiesVetoable(TopiaEntitiesVetoable vetoable) { + getFiresSupport().addTopiaEntitiesVetoable(vetoable); + } + + public void removeTopiaEntitiesVetoable(TopiaEntitiesVetoable vetoable) { + getFiresSupport().removeTopiaEntitiesVetoable(vetoable); + } + +} //TopiaContextImpl Deleted: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java =================================================================== --- topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,486 +0,0 @@ -/* *##% ToPIA - Tools for Portable and Independent Architecture - * Copyright (C) 2004 - 2008 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - -/* * -* EntityHibernateMappingGenerator.java -* -* Created: 12 déc. 2005 -* -* @author Arnaud Thimel <thimel@codelutin.com> -* @version $Revision$ -* -* Mise a jour: $Date$ -* par : $Author$ -* Mise a jour: $Date$ -* par : $Author$ -*/ - -package org.codelutin.topia.generator; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codelutin.generator.Generator; -import org.codelutin.generator.ObjectModelGenerator; -import org.codelutin.generator.Util; -import org.codelutin.generator.models.object.ObjectModelAssociationClass; -import org.codelutin.generator.models.object.ObjectModelAttribute; -import org.codelutin.generator.models.object.ObjectModelClass; -import static org.codelutin.topia.generator.GeneratorUtil.PERSISTENCE_TYPE_HIBERNATE; -import static org.codelutin.topia.generator.GeneratorUtil.STEREOTYPE_ENTITY; -import static org.codelutin.topia.generator.GeneratorUtil.TAG_ACCESS; -import static org.codelutin.topia.generator.GeneratorUtil.hasUnidirectionalRelationOnAbstractType; -import static org.codelutin.topia.generator.GeneratorUtil.notEmpty; - -import java.io.File; -import java.io.IOException; -import java.io.Writer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * FIXME mettre les attributs node="..." sur tous les attributs - * @author poussin - * - */ -public class EntityHibernateMappingGenerator extends ObjectModelGenerator { - - /** - * Logger for this class - */ - private static final Log log = LogFactory - .getLog(EntityHibernateMappingGenerator.class); - - private Map<String, String[]> columnNamesMap = new HashMap<String, String[]>(); - - public EntityHibernateMappingGenerator() { - super(); - } - - public EntityHibernateMappingGenerator(Generator parent) { - super(parent); - } - - @Override - public String getFilenameForClass(ObjectModelClass clazz) { - String DOName = GeneratorUtil.getDOType(clazz, model); - return DOName.replace('.', File.separatorChar) + ".hbm.xml"; - } - - @Override - public void generateFromClass(Writer output, ObjectModelClass clazz) throws IOException { - String persistenceType = GeneratorUtil.getPersistenceType(clazz); - if (!clazz.hasStereotype(STEREOTYPE_ENTITY) && PERSISTENCE_TYPE_HIBERNATE.equals(persistenceType)) { - return; - } -/*{<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> -<hibernate-mapping default-access="field" auto-import="true" package="<%=clazz.getPackageName()%>"> -}*/ - boolean haveSuper = clazz.getSuperclasses().size() > 0; - List<ObjectModelAttribute> noneNaturalAttributes = new ArrayList<ObjectModelAttribute >(); - if (haveSuper) { - ObjectModelClass superClass = clazz.getSuperclasses().iterator().next(); - String superClassname = superClass.getQualifiedName(); - if (log.isDebugEnabled()) {log.debug("superClass for " + clazz.getQualifiedName() + " is " + superClassname);} -/*{ <union-subclass }*/ -/*{name="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ -/*{extends="<%=GeneratorUtil.getDOType(superClassname, model)%>" }*/ -/*{table="<%=GeneratorUtil.getDBName(clazz)%>" }*/ - String schema = GeneratorUtil.getSchemaName(clazz, model); - if (schema != null) { -/*{schema="<%=schema%>" }*/ - } -/*{node="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ -/*{abstract="<%=(clazz.isAbstract()?"true":"false")%>" }*/ - //On précise au proxy de quelle interface hérite l'objet -/*{proxy="<%=clazz.getQualifiedName()%>" }*/ -/*{> - <!--key column="topiaId"/--> -}*/ - } else { -/*{ <class }*/ -/*{name="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ -/*{table="<%=GeneratorUtil.getDBName(clazz)%>" }*/ - String schema = GeneratorUtil.getSchemaName(clazz, model); - if (schema != null) { -/*{schema="<%=schema%>" }*/ - } -/*{node="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ -/*{abstract="<%=(clazz.isAbstract()?"true":"false")%>" }*/ - //On précise au proxy de quelle interface hérite l'objet -/*{proxy="<%=clazz.getQualifiedName()%>" }*/ -/*{> - <id name="topiaId" type="string" length="255" node="@topiaId"/> -}*/ - List<String> attributes = GeneratorUtil.getNaturalId(clazz); - if (log.isDebugEnabled()) { - log.debug("natural-id for class "+clazz.getName()+" : "+attributes); - } - - if (attributes.isEmpty()) { - // pas de clef metiers sur la classe - noneNaturalAttributes.addAll(clazz.getAttributes()); - } else { - // une clef métier sur la classe a ete detectee - List<ObjectModelAttribute> naturalAttributes = new ArrayList<ObjectModelAttribute >(attributes.size()); - for (ObjectModelAttribute attr : clazz.getAttributes()) { - if (attributes.contains(attr.getName())) { - naturalAttributes.add(attr); - } else { - noneNaturalAttributes.add(attr); - } - } -/*{ <natural-id> -}*/ - generateAttributes(output, clazz, naturalAttributes," "); -/*{ </natural-id> -}*/ - } - -/*{ <version name="topiaVersion" type="long" node="@topiaVersion"/> - <property name="topiaCreateDate" type="date" node="@topiaCreateDate"/> -}*/ - } - generateAttributes(output, clazz, noneNaturalAttributes,""); - - if (haveSuper) { -/*{ </union-subclass> -}*/ - } else { -/*{ </class> -}*/ - } -/*{</hibernate-mapping> -}*/ - } - - protected void generateAttributes(Writer output, ObjectModelClass clazz, List<ObjectModelAttribute> attributes,String prefix) throws IOException { - for (ObjectModelAttribute attr : attributes) { - ObjectModelAttribute reverse = attr.getReverseAttribute(); - - // pour les asso quoi qu'il arrive il faut les lier des 2 cotes - // pour pouvoir supprimer en cascade l'asso lors de la suppression - // d'un des cotes - if (attr.isNavigable() - || hasUnidirectionalRelationOnAbstractType(reverse, model) - || attr.hasAssociationClass()) { - if (!Util.isNMultiplicity(attr)) { - if (attr.getClassifier() != null && attr.getClassifier().hasStereotype(STEREOTYPE_ENTITY)) { - if (Util.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { - generateHibernateManyToOne(output, attr, prefix); - } else { - generateHibernateOneToOne(output, attr, prefix); - } - } else { - generateHibernateProperty(output, attr, prefix); - } - } else { - if (attr.getClassifier() != null && attr.getClassifier().hasStereotype(STEREOTYPE_ENTITY)) { - if (Util.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { - generateHibernateManyToMany(output, attr, prefix); - } else { - generateHibernateOneToMany(output, attr, prefix); - } - } else { - generateHibernateMany(output, attr, prefix); - } - } - } - } - - //Attributs pour les classes d'association - if (clazz instanceof ObjectModelAssociationClass) { - ObjectModelAssociationClass assoc = (ObjectModelAssociationClass)clazz; - for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { - if (attr != null) { - -// Note(poussin) pour moi quoi qu'il arrive sur la classe d'association il faut -// un many-to-one, sinon on a des problemes. -// if ((!attr.getReverseAttribute().isNavigable()) || !Util.isNMultiplicity(attr.getReverseAttribute())) { -// / *{ <one-to-one name="<%=getName(attr, true)%>" class="<%=getType(attr, true)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%><%=(attr.isComposite()?" cascade=\"delete\"":"")%>/> -// } */ -// } else { - String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); - if (notNull!=null) { - notNull = "not-null=\""+notNull.trim()+"\""; - } -/*{<%=prefix%> <many-to-one name="<%=getName(attr, true)%>" class="<%=getType(attr, true)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="<%=getName(attr, true)%>/@topiaId" embed-xml="false" <%=notNull%> /> -}*/ -// } - //Ne sert plus grâce à l'utilisation de la navigabilité -// if (!attr.getReverseAttribute().isNavigable()) { -// String type = GeneratorUtil.getDOType(((ObjectModelClassifier)attr.getDeclaringElement()).getQualifiedName(), model); -// String name = Util.toLowerCaseFirstLetter(attr.getDeclaringElement().getName()); -// if (log.isTraceEnabled()) {log.trace("reverse: " + type + " " + name);} -// if (!Util.isNMultiplicity(attr)) { -//{<!-- <one-to-one name="<%=name%>" class="<%=type%>"/> -//} -// } else { -//{ <many-to-one name="<%=name%>" class="<%=type%>" column="<%=name.toLowerCase()%>"/> --> -//} -// } -// } - } - } - } - - } - protected String getName(ObjectModelAttribute attr) { - return getName(attr, false); - } - - protected String getName(ObjectModelAttribute attr, boolean isAssoc) { - String result = Util.toLowerCaseFirstLetter(attr.getName()); - if (attr.hasAssociationClass() && !isAssoc) { - result = GeneratorUtil.getAssocAttrName(attr); - } - return result; - } - - protected String getType(ObjectModelAttribute attr) { - return getType(attr, false); - } - - protected String getType(ObjectModelAttribute attr, boolean isAssoc) { - String type = attr.getType(); - if (GeneratorUtil.notEmpty(model.getTagValue(type))) { - String typeString = model.getTagValue(type); - int bracketIndex = typeString.indexOf('('); - if (bracketIndex != -1) { - type = typeString.substring(0, bracketIndex); - int bracketEndIndex = typeString.indexOf(')', bracketIndex + 1); - String colmunList; - if (bracketEndIndex != -1) { - colmunList = typeString.substring(bracketIndex + 1, bracketEndIndex); - } else { - colmunList = typeString.substring(bracketIndex); - } - columnNamesMap.put(type, colmunList.split(",")); - } else { - type = typeString; - } - } - if (attr.hasAssociationClass() && !isAssoc) { - type = attr.getAssociationClass().getQualifiedName(); - } - return GeneratorUtil.getDOType(type, model); - } - - protected void generateHibernateProperty(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - String type = getType(attr); - if (type.trim().endsWith("[]")) { - type = type.trim().substring(0, type.trim().length()-2); -/*{<%=prefix%> <primitive-array name="<%=getName(attr)%>" table="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>" }*/ - String accessField = attr.getTagValue(TAG_ACCESS); - if (notEmpty(accessField)) { -/*{access="<%=accessField%>" }*/ - } else { -/*{access="field" }*/ - } - String schema = GeneratorUtil.getSchemaName(attr, model); - if (schema != null) { -/*{schema="<%=schema%>" }*/ - } - if (attr.isIndexed()) { -/*{index="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>_idx" }*/ - } -/*{> -<%=prefix%> <key column="<%=GeneratorUtil.getDBName(attr.getDeclaringElement())%>"/> -<%=prefix%> <list-index column="<%=getName(attr)%>_idx"/> -<%=prefix%> <element type="<%=type%>"/> -<%=prefix%> </primitive-array> -}*/ - } else { -/*{<%=prefix%> <property name="<%=getName(attr)%>" type="<%=type%>" }*/ - String accessField = attr.getTagValue(TAG_ACCESS); - if (notEmpty(accessField)) { -/*{access="<%=accessField%>" }*/ - } else { -/*{access="field" }*/ - } - if (attr.isIndexed()) { -/*{index="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>_idx" }*/ - } - String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); - if (notNull != null) { -/*{ not-null="<%=notNull.trim()%>" }*/ - } - String[] columnNames = this.columnNamesMap.get(type); - if (columnNames == null || columnNames.length == 0) { -/*{column="<%=GeneratorUtil.getDBName(attr)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%> node="<%=getName(attr)%>"/> -}*/ - } else { -/*{> -}*/ - for (String columnName : columnNames) { - columnName = columnName.trim(); -/*{<%=prefix%> <column name="<%=getName(attr) + "_" + columnName%>"/> -}*/ - } -/*{<%=prefix%> </property> -}*/ - } - } - } - - protected void generateHibernateOneToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - generateHibernateManyToOne(output, attr, true, prefix); -// boolean accessField = hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model); -/// *{ <one-to-one name="<%=getName(attr)%>" class="<%=getType(attr)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%><%=((attr.isComposite() || attr.hasAssociationClass())?" cascade=\"delete\"":"")%><%=((accessField)?" access=\"field\"":"")%> node="<%=getName(attr)%>/@topiaId" embed-xml="false"/> -//} */ - } - - protected void generateHibernateOneToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - boolean needsIndex = attr.isIndexed(); - boolean isInverse = attr.getReverseAttribute().isNavigable(); - isInverse |= hasUnidirectionalRelationOnAbstractType(attr, model); - String orderBy = attr.getTagValue(GeneratorUtil.TAG_ORDER_BY); - if (orderBy == null) { - orderBy = ""; - } else { - orderBy = "order-by=\"" + orderBy + "\""; - } - - String cascade = ""; - if (attr.isComposite() || attr.hasAssociationClass()) { - cascade += "cascade=\"all,delete-orphan\""; - } - - String lazy = "lazy=\""; - if (attr.getTagValue(GeneratorUtil.TAG_LAZY) != null){ - lazy += attr.getTagValue(GeneratorUtil.TAG_LAZY); - } - else { - lazy += "true"; - } - lazy += "\""; - - String fetch = ""; - if (attr.getTagValue(GeneratorUtil.TAG_FETCH) != null){ - fetch = "fetch=\"" + attr.getTagValue(GeneratorUtil.TAG_FETCH) + "\""; - } - - String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); - if (!needsIndex) { -/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>" <%=orderBy%> <%=((!isInverse)?"":"inverse=\"true\"")%> <%=fetch%> <%=lazy%> <%=cascade%> node="<%=getName(attr)%>" embed-xml="true"> -<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> -<%=prefix%> <one-to-many class="<%=getType(attr)%>" node="topiaId" embed-xml="false"/> -<%=prefix%> </<%=collType%>> -}*/ - }else { -/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>"<%=((!isInverse)?"":" inverse=\"true\"")%> <%=lazy%> <%=cascade%> node="<%=getName(attr)%>" embed-xml="false"> -<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> -<%=prefix%> <list-index column="<%=GeneratorUtil.getReverseDBName(attr)%>_idx"/> -<%=prefix%> <one-to-many class="<%=getType(attr)%>" node="topiaId" embed-xml="false"/> -<%=prefix%> </<%=collType%>> -}*/ - } - } - - protected void generateHibernateMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - boolean needsIndex = attr.isIndexed(); - String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); - String lazy = ""; - if (attr.getTagValue(GeneratorUtil.TAG_LAZY) != null) { - lazy = "lazy=\"" + attr.getTagValue(GeneratorUtil.TAG_LAZY) + "\""; - } - -/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>" node="<%=getName(attr)%>" embed-xml="true" <%=lazy%>> -<%=prefix%> <key column="OWNER"/> -}*/ - if (needsIndex) { -/*{<%=prefix%> <list-index/> -}*/ - } -/*{<%=prefix%> <element type="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="id"/> -<%=prefix%> </<%=collType%>> -}*/ - } - - protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - generateHibernateManyToOne(output, attr, false, prefix); - } - - protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, boolean isUnique, String prefix) throws IOException { -/*{<%=prefix%> <many-to-one name="<%=getName(attr)%>" class="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>"}*/ - if (attr.isComposite() || attr.hasAssociationClass()) { -/*{ cascade="delete"}*/ - } - // Pour le test suivant, on verifie d'abord que l'attribut a un reverse. - // S'il n'en a pas, cela signifie qu'il ne s'agit pas d'un entite - // (au sens stereotype entity), donc a donc pas besoin de faire un access=field. - if (attr.getReverseAttribute() != null && hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model)) { -/*{ access="field"}*/ - } - if (isUnique) { -/*{ unique="true"}*/ - } -/*{ node="<%=getName(attr)%>/@topiaId" embed-xml="false"}*/ - - // vérifier si le tag lazy est defini par defaut dans le fichier de proprietes - if (attr.getTagValue("lazy") != null){ -/*{ lazy="<%=attr.getTagValue("lazy")%>"}*/ - } - String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); - if (notNull != null) { -/*{ not-null="<%=notNull.trim()%>"}*/ - } -/*{/> -}*/ - } - - protected void generateHibernateManyToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { - // On ne met le inverse="true" uniquement pour un seul coté de la relation. - // Dans le cas contraire, les modifications dans la relation ne seront - // pas sauvegardées. Ceci n'est vrai que si les deux coté sont navigable - boolean isInverse = attr.isNavigable() && attr.getReverseAttribute().isNavigable(); - //isInverse |= !Util.isFirstAttribute(attr); - //isInverse = false; // 20070117 poussin: pour du many, jamais de inverse - isInverse &= Util.isFirstAttribute(attr); - - boolean needsIndex = attr.isIndexed(); - String cascade = ""; - if (attr.isComposite() || attr.hasAssociationClass()) { - cascade += "cascade=\"delete,delete-orphan\""; - } - cascade += ""; - - String lazy = "lazy=\""; - if (attr.getTagValue("lazy") != null){ - lazy += attr.getTagValue("lazy"); - } - else { - lazy += "true"; - } - lazy += "\""; - String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); - -/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>" table="<%=GeneratorUtil.getManyToManyTableName(attr)%>" <%=(isInverse?"inverse=\"true\" ":"")%> <%=lazy%> <%=cascade%> node="<%=getName(attr)%>" embed-xml="true"> -<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> -}*/ - if (needsIndex) { -/*{<%=prefix%> <list-index column="<%=GeneratorUtil.getReverseDBName(attr)%>_idx"/> -}*/ - } -/*{<%=prefix%> <many-to-many class="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="topiaId"/> -<%=prefix%> </<%=collType%>> -}*/ - } - -} //EntityHibernateMappingGenerator Copied: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java (from rev 1301, topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java) =================================================================== --- topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java (rev 0) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/EntityHibernateMappingGenerator.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,493 @@ +/* *##% ToPIA - Tools for Portable and Independent Architecture + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ + +/* * +* EntityHibernateMappingGenerator.java +* +* Created: 12 déc. 2005 +* +* @author Arnaud Thimel <thimel@codelutin.com> +* @version $Revision$ +* +* Mise a jour: $Date$ +* par : $Author$ +* Mise a jour: $Date$ +* par : $Author$ +*/ + +package org.codelutin.topia.generator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.generator.Generator; +import org.codelutin.generator.ObjectModelGenerator; +import org.codelutin.generator.Util; +import org.codelutin.generator.models.object.ObjectModelAssociationClass; +import org.codelutin.generator.models.object.ObjectModelAttribute; +import org.codelutin.generator.models.object.ObjectModelClass; +import static org.codelutin.topia.generator.GeneratorUtil.PERSISTENCE_TYPE_HIBERNATE; +import static org.codelutin.topia.generator.GeneratorUtil.STEREOTYPE_ENTITY; +import static org.codelutin.topia.generator.GeneratorUtil.TAG_ACCESS; +import static org.codelutin.topia.generator.GeneratorUtil.hasUnidirectionalRelationOnAbstractType; +import static org.codelutin.topia.generator.GeneratorUtil.notEmpty; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * FIXME mettre les attributs node="..." sur tous les attributs + * @author poussin + * + */ +public class EntityHibernateMappingGenerator extends ObjectModelGenerator { + + /** + * Logger for this class + */ + private static final Log log = LogFactory + .getLog(EntityHibernateMappingGenerator.class); + + private Map<String, String[]> columnNamesMap = new HashMap<String, String[]>(); + + public EntityHibernateMappingGenerator() { + super(); + } + + public EntityHibernateMappingGenerator(Generator parent) { + super(parent); + } + + @Override + public String getFilenameForClass(ObjectModelClass clazz) { + String DOName = GeneratorUtil.getDOType(clazz, model); + return DOName.replace('.', File.separatorChar) + ".hbm.xml"; + } + + @Override + public void generateFromClass(Writer output, ObjectModelClass clazz) throws IOException { + String persistenceType = GeneratorUtil.getPersistenceType(clazz); + if (!clazz.hasStereotype(STEREOTYPE_ENTITY) && PERSISTENCE_TYPE_HIBERNATE.equals(persistenceType)) { + return; + } +/*{<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> +<hibernate-mapping default-access="field" auto-import="true" package="<%=clazz.getPackageName()%>"> +}*/ + boolean haveSuper = clazz.getSuperclasses().size() > 0; + // la liste des attributs faisant parti de la clef metier + List<ObjectModelAttribute> naturalAttributes = new ArrayList<ObjectModelAttribute>(); + // la liste des autres attributs + List<ObjectModelAttribute> noneNaturalAttributes = new ArrayList<ObjectModelAttribute>(); + if (haveSuper) { + ObjectModelClass superClass = clazz.getSuperclasses().iterator().next(); + String superClassname = superClass.getQualifiedName(); + if (log.isDebugEnabled()) {log.debug("superClass for " + clazz.getQualifiedName() + " is " + superClassname);} +/*{ <union-subclass }*/ +/*{name="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ +/*{extends="<%=GeneratorUtil.getDOType(superClassname, model)%>" }*/ +/*{table="<%=GeneratorUtil.getDBName(clazz)%>" }*/ + String schema = GeneratorUtil.getSchemaName(clazz, model); + if (schema != null) { +/*{schema="<%=schema%>" }*/ + } +/*{node="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ +/*{abstract="<%=(clazz.isAbstract()?"true":"false")%>" }*/ + //On précise au proxy de quelle interface hérite l'objet +/*{proxy="<%=clazz.getQualifiedName()%>" }*/ +/*{> + <!--key column="topiaId"/--> +}*/ + } else { +/*{ <class }*/ +/*{name="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ +/*{table="<%=GeneratorUtil.getDBName(clazz)%>" }*/ + String schema = GeneratorUtil.getSchemaName(clazz, model); + if (schema != null) { +/*{schema="<%=schema%>" }*/ + } +/*{node="<%=GeneratorUtil.getDOType(clazz, model)%>" }*/ +/*{abstract="<%=(clazz.isAbstract()?"true":"false")%>" }*/ + //On précise au proxy de quelle interface hérite l'objet +/*{proxy="<%=clazz.getQualifiedName()%>" }*/ +/*{> + <id name="topiaId" type="string" length="255" node="@topiaId"/> +}*/ + // on detecte les attributs des clef metiers + for (ObjectModelAttribute attr : clazz.getAttributes()) { + if (GeneratorUtil.isNaturalId(attr)) { + // attribut metier + naturalAttributes.add(attr); + } else { + // attribut normal + noneNaturalAttributes.add(attr); + } + } + if (!naturalAttributes.isEmpty()) { + // generation de la clef metier + boolean mutable = GeneratorUtil.isNaturalIdMutable(clazz); + String mutableStr = mutable ? " mutable=\"true\"" : ""; + if (log.isDebugEnabled()) { + log.debug("natural-id detected for class " + clazz.getName() + " (" + mutableStr + ") attributes : " + naturalAttributes); + } +/*{ <natural-id<%=mutableStr%>> +}*/ + generateAttributes(output, clazz, naturalAttributes," "); +/*{ </natural-id> +}*/ + } +/*{ <version name="topiaVersion" type="long" node="@topiaVersion"/> + <property name="topiaCreateDate" type="date" node="@topiaCreateDate"/> +}*/ + } + generateAttributes(output, clazz, noneNaturalAttributes,""); + + if (haveSuper) { +/*{ </union-subclass> +}*/ + } else { +/*{ </class> +}*/ + } +/*{</hibernate-mapping> +}*/ + } + + protected void generateAttributes(Writer output, ObjectModelClass clazz, List<ObjectModelAttribute> attributes,String prefix) throws IOException { + for (ObjectModelAttribute attr : attributes) { + ObjectModelAttribute reverse = attr.getReverseAttribute(); + + // pour les asso quoi qu'il arrive il faut les lier des 2 cotes + // pour pouvoir supprimer en cascade l'asso lors de la suppression + // d'un des cotes + if (attr.isNavigable() + || hasUnidirectionalRelationOnAbstractType(reverse, model) + || attr.hasAssociationClass()) { + if (!Util.isNMultiplicity(attr)) { + if (attr.getClassifier() != null && attr.getClassifier().hasStereotype(STEREOTYPE_ENTITY)) { + if (Util.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { + generateHibernateManyToOne(output, attr, prefix); + } else { + generateHibernateOneToOne(output, attr, prefix); + } + } else { + generateHibernateProperty(output, attr, prefix); + } + } else { + if (attr.getClassifier() != null && attr.getClassifier().hasStereotype(STEREOTYPE_ENTITY)) { + if (Util.isNMultiplicity(attr.getReverseMaxMultiplicity()) && !attr.hasAssociationClass()) { + generateHibernateManyToMany(output, attr, prefix); + } else { + generateHibernateOneToMany(output, attr, prefix); + } + } else { + generateHibernateMany(output, attr, prefix); + } + } + } + } + + //Attributs pour les classes d'association + if (clazz instanceof ObjectModelAssociationClass) { + ObjectModelAssociationClass assoc = (ObjectModelAssociationClass)clazz; + for (ObjectModelAttribute attr : assoc.getParticipantsAttributes()) { + if (attr != null) { + +// Note(poussin) pour moi quoi qu'il arrive sur la classe d'association il faut +// un many-to-one, sinon on a des problemes. +// if ((!attr.getReverseAttribute().isNavigable()) || !Util.isNMultiplicity(attr.getReverseAttribute())) { +// / *{ <one-to-one name="<%=getName(attr, true)%>" class="<%=getType(attr, true)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%><%=(attr.isComposite()?" cascade=\"delete\"":"")%>/> +// } */ +// } else { + String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); + if (notEmpty(notNull)) { + notNull = " not-null=\""+notNull.trim()+"\""; + } +/*{<%=prefix%> <many-to-one name="<%=getName(attr, true)%>" class="<%=getType(attr, true)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="<%=getName(attr, true)%>/@topiaId" embed-xml="false"<%=notNull%> /> +}*/ +// } + //Ne sert plus grâce à l'utilisation de la navigabilité +// if (!attr.getReverseAttribute().isNavigable()) { +// String type = GeneratorUtil.getDOType(((ObjectModelClassifier)attr.getDeclaringElement()).getQualifiedName(), model); +// String name = Util.toLowerCaseFirstLetter(attr.getDeclaringElement().getName()); +// if (log.isTraceEnabled()) {log.trace("reverse: " + type + " " + name);} +// if (!Util.isNMultiplicity(attr)) { +//{<!-- <one-to-one name="<%=name%>" class="<%=type%>"/> +//} +// } else { +//{ <many-to-one name="<%=name%>" class="<%=type%>" column="<%=name.toLowerCase()%>"/> --> +//} +// } +// } + } + } + } + + } + protected String getName(ObjectModelAttribute attr) { + return getName(attr, false); + } + + protected String getName(ObjectModelAttribute attr, boolean isAssoc) { + String result = Util.toLowerCaseFirstLetter(attr.getName()); + if (attr.hasAssociationClass() && !isAssoc) { + result = GeneratorUtil.getAssocAttrName(attr); + } + return result; + } + + protected String getType(ObjectModelAttribute attr) { + return getType(attr, false); + } + + protected String getType(ObjectModelAttribute attr, boolean isAssoc) { + String type = attr.getType(); + if (GeneratorUtil.notEmpty(model.getTagValue(type))) { + String typeString = model.getTagValue(type); + int bracketIndex = typeString.indexOf('('); + if (bracketIndex != -1) { + type = typeString.substring(0, bracketIndex); + int bracketEndIndex = typeString.indexOf(')', bracketIndex + 1); + String colmunList; + if (bracketEndIndex != -1) { + colmunList = typeString.substring(bracketIndex + 1, bracketEndIndex); + } else { + colmunList = typeString.substring(bracketIndex); + } + columnNamesMap.put(type, colmunList.split(",")); + } else { + type = typeString; + } + } + if (attr.hasAssociationClass() && !isAssoc) { + type = attr.getAssociationClass().getQualifiedName(); + } + return GeneratorUtil.getDOType(type, model); + } + + protected void generateHibernateProperty(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + String type = getType(attr); + if (type.trim().endsWith("[]")) { + type = type.trim().substring(0, type.trim().length()-2); +/*{<%=prefix%> <primitive-array name="<%=getName(attr)%>" table="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>" }*/ + String accessField = attr.getTagValue(TAG_ACCESS); + if (notEmpty(accessField)) { +/*{access="<%=accessField%>" }*/ + } else { +/*{access="field" }*/ + } + String schema = GeneratorUtil.getSchemaName(attr, model); + if (schema != null) { +/*{schema="<%=schema%>" }*/ + } + if (attr.isIndexed()) { +/*{index="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>_idx" }*/ + } +/*{> +<%=prefix%> <key column="<%=GeneratorUtil.getDBName(attr.getDeclaringElement())%>"/> +<%=prefix%> <list-index column="<%=getName(attr)%>_idx"/> +<%=prefix%> <element type="<%=type%>"/> +<%=prefix%> </primitive-array> +}*/ + } else { +/*{<%=prefix%> <property name="<%=getName(attr)%>" type="<%=type%>" }*/ + String accessField = attr.getTagValue(TAG_ACCESS); + if (notEmpty(accessField)) { +/*{access="<%=accessField%>" }*/ + } else { +/*{access="field" }*/ + } + if (attr.isIndexed()) { +/*{index="<%=GeneratorUtil.getDBName(attr.getDeclaringElement()) + "_" + getName(attr)%>_idx" }*/ + } + String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); + if (notNull != null) { +/*{ not-null="<%=notNull.trim()%>" }*/ + } + String[] columnNames = this.columnNamesMap.get(type); + if (columnNames == null || columnNames.length == 0) { +/*{column="<%=GeneratorUtil.getDBName(attr)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%> node="<%=getName(attr)%>"/> +}*/ + } else { +/*{> +}*/ + for (String columnName : columnNames) { + columnName = columnName.trim(); +/*{<%=prefix%> <column name="<%=getName(attr) + "_" + columnName%>"/> +}*/ + } +/*{<%=prefix%> </property> +}*/ + } + } + } + + protected void generateHibernateOneToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + generateHibernateManyToOne(output, attr, true, prefix); +// boolean accessField = hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model); +/// *{ <one-to-one name="<%=getName(attr)%>" class="<%=getType(attr)%>"<%=(GeneratorUtil.notEmpty(attr.getTagValue(GeneratorUtil.TAG_LENGTH))?(" length=\"" + attr.getTagValue(GeneratorUtil.TAG_LENGTH) + "\""):"")%><%=((attr.isComposite() || attr.hasAssociationClass())?" cascade=\"delete\"":"")%><%=((accessField)?" access=\"field\"":"")%> node="<%=getName(attr)%>/@topiaId" embed-xml="false"/> +//} */ + } + + protected void generateHibernateOneToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + boolean needsIndex = attr.isIndexed(); + boolean isInverse = attr.getReverseAttribute().isNavigable(); + isInverse |= hasUnidirectionalRelationOnAbstractType(attr, model); + String orderBy = attr.getTagValue(GeneratorUtil.TAG_ORDER_BY); + if (orderBy == null) { + orderBy = ""; + } else { + orderBy = " order-by=\"" + orderBy + "\""; + } + + String cascade = ""; + if (attr.isComposite() || attr.hasAssociationClass()) { + cascade += " cascade=\"all,delete-orphan\""; + } + + String lazy = " lazy=\""; + if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_LAZY))){ + lazy += attr.getTagValue(GeneratorUtil.TAG_LAZY); + } + else { + lazy += "true"; + } + lazy += "\""; + + String fetch = ""; + if (notEmpty(attr.getTagValue(GeneratorUtil.TAG_FETCH))){ + fetch = " fetch=\"" + attr.getTagValue(GeneratorUtil.TAG_FETCH) + "\""; + } + + String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); + if (!needsIndex) { + //fixme pour le moment, on ne calcule pas si on doit autoriser le embed-xml à true + // on le positionne manuellement + //TC-20090115 embed-xml wasat true but nobody could tellme why +/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>"<%=orderBy%><%=((!isInverse)?"":" inverse=\"true\"")%><%=fetch%><%=lazy%><%=cascade%> node="<%=getName(attr)%>" embed-xml="false"> +<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> +<%=prefix%> <one-to-many class="<%=getType(attr)%>" node="topiaId" embed-xml="false"/> +<%=prefix%> </<%=collType%>> +}*/ + }else { +/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>"<%=((!isInverse)?"":" inverse=\"true\"")%><%=lazy%><%=cascade%> node="<%=getName(attr)%>" embed-xml="false"> +<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> +<%=prefix%> <list-index column="<%=GeneratorUtil.getReverseDBName(attr)%>_idx"/> +<%=prefix%> <one-to-many class="<%=getType(attr)%>" node="topiaId" embed-xml="false"/> +<%=prefix%> </<%=collType%>> +}*/ + } + } + + protected void generateHibernateMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + boolean needsIndex = attr.isIndexed(); + String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); + String lazy = ""; + if (attr.getTagValue(GeneratorUtil.TAG_LAZY) != null) { + lazy = " lazy=\"" + attr.getTagValue(GeneratorUtil.TAG_LAZY) + "\""; + } + +/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>" node="<%=getName(attr)%>" embed-xml="true"<%=lazy%>> +<%=prefix%> <key column="OWNER"/> +}*/ + if (needsIndex) { +/*{<%=prefix%> <list-index/> +}*/ + } +/*{<%=prefix%> <element type="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="id"/> +<%=prefix%> </<%=collType%>> +}*/ + } + + protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + generateHibernateManyToOne(output, attr, false, prefix); + } + + protected void generateHibernateManyToOne(Writer output, ObjectModelAttribute attr, boolean isUnique, String prefix) throws IOException { +/*{<%=prefix%> <many-to-one name="<%=getName(attr)%>" class="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>"}*/ + if (attr.isComposite() || attr.hasAssociationClass()) { +/*{ cascade="delete"}*/ + } + // Pour le test suivant, on verifie d'abord que l'attribut a un reverse. + // S'il n'en a pas, cela signifie qu'il ne s'agit pas d'un entite + // (au sens stereotype entity), donc a donc pas besoin de faire un access=field. + if (attr.getReverseAttribute() != null && hasUnidirectionalRelationOnAbstractType(attr.getReverseAttribute(), model)) { +/*{ access="field"}*/ + } + if (isUnique) { +/*{ unique="true"}*/ + } +/*{ node="<%=getName(attr)%>/@topiaId" embed-xml="false"}*/ + + // vérifier si le tag lazy est defini par defaut dans le fichier de proprietes + if (attr.getTagValue(GeneratorUtil.TAG_LAZY) != null){ +/*{ lazy="<%=attr.getTagValue("lazy")%>"}*/ + } + String notNull = attr.getTagValue(GeneratorUtil.TAG_NOT_NULL); + if (notNull != null) { +/*{ not-null="<%=notNull.trim()%>"}*/ + } +/*{/> +}*/ + } + + protected void generateHibernateManyToMany(Writer output, ObjectModelAttribute attr, String prefix) throws IOException { + // On ne met le inverse="true" uniquement pour un seul coté de la relation. + // Dans le cas contraire, les modifications dans la relation ne seront + // pas sauvegardées. Ceci n'est vrai que si les deux coté sont navigable + boolean isInverse = attr.isNavigable() && attr.getReverseAttribute().isNavigable(); + //isInverse |= !Util.isFirstAttribute(attr); + //isInverse = false; // 20070117 poussin: pour du many, jamais de inverse + isInverse &= Util.isFirstAttribute(attr); + + boolean needsIndex = attr.isIndexed(); + String cascade = ""; + if (attr.isComposite() || attr.hasAssociationClass()) { + // a quoi ca sert ? de concatener "" avec autre chose ??? + //cascade += "cascade=\"delete,delete-orphan\""; + cascade = " cascade=\"delete,delete-orphan\""; + } + // a quoi ca sert ? :) + //cascade += ""; + + String lazy = " lazy=\""; + if (attr.getTagValue(GeneratorUtil.TAG_LAZY) != null){ + lazy += attr.getTagValue(GeneratorUtil.TAG_LAZY); + } + else { + lazy += "true"; + } + lazy += "\""; + String collType = GeneratorUtil.getNMultiplicityHibernateType(attr); + +/*{<%=prefix%> <<%=collType%> name="<%=getName(attr)%>" table="<%=GeneratorUtil.getManyToManyTableName(attr)%>"<%=(isInverse?" inverse=\"true\" ":"")%><%=lazy%><%=cascade%> node="<%=getName(attr)%>" embed-xml="true"> +<%=prefix%> <key column="<%=GeneratorUtil.getReverseDBName(attr)%>"/> +}*/ + if (needsIndex) { +/*{<%=prefix%> <list-index column="<%=GeneratorUtil.getReverseDBName(attr)%>_idx"/> +}*/ + } +/*{<%=prefix%> <many-to-many class="<%=getType(attr)%>" column="<%=GeneratorUtil.getDBName(attr)%>" node="topiaId"/> +<%=prefix%> </<%=collType%>> +}*/ + } + +} //EntityHibernateMappingGenerator Deleted: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java =================================================================== --- topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,635 +0,0 @@ -/* *##% ToPIA - Tools for Portable and Independent Architecture - * Copyright (C) 2004 - 2008 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - -/******************************************************************************* - * GeneratorUtil.java - * - * Created: 13 déc. 2005 - * - * @author Arnaud Thimel <thimel@codelutin.com> - * - * @version $Revision$ - * - * Mise a jour: $Date$ par : $Author$ - */ - -package org.codelutin.topia.generator; - -import org.apache.commons.lang.StringUtils; -import org.codelutin.generator.Generator; -import org.codelutin.generator.Util; -import org.codelutin.generator.models.Model; -import org.codelutin.generator.models.object.ObjectModel; -import org.codelutin.generator.models.object.ObjectModelAttribute; -import org.codelutin.generator.models.object.ObjectModelClass; -import org.codelutin.generator.models.object.ObjectModelElement; -import org.codelutin.generator.models.object.ObjectModelInterface; -import org.codelutin.generator.models.object.ObjectModelOperation; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -/** Classe regroupant divers méthodes utiles pour la génération des entités */ -public class GeneratorUtil extends Util { - - /** Stéréotype pour les interfaces devant être générées sous forme de facades */ - public final static String STEREOTYPE_FACADE = "facade"; - - /** Stéréotype pour les objets devant être générées sous forme d'entités */ - public static final String STEREOTYPE_ENTITY = "entity"; - - /** Stéréotype pour les objets devant être générées sous forme de DTO */ - public static final String STEREOTYPE_DTO = "dto"; - - /** - * Stéréotype pour les interfaces devant être générées sous forme de - * services - */ - public static final String STEREOTYPE_SERVICE = "service"; - - /** Stéréotype pour les interfaces devant être générées sous forme de DAO */ - public static final String STEREOTYPE_DAO = "dao"; - - /** Stéréotype pour les attributs à indexer en base */ - public static final String STEREOTYPE_INDEXED = "indexed"; - - /** Stéréotype pour les collections avec unicité */ - public static final String STEREOTYPE_UNIQUE = "unique"; - - /** Stéréotype pour les attributs étant des clés primaires */ - public static final String STEREOTYPE_PRIMARYKAY = "primaryKey"; - - /** Tag pour le type de persistence */ - public static final String TAG_PERSISTENCE_TYPE = "persistenceType"; - - /** Tag pour le nom du champ / entité en BD */ - public static final String TAG_DB_NAME = "dbName"; - - /** Tag pour le nom du schema en BD */ - public static final String TAG_SCHEMA_NAME = "dbSchema"; - - /** Tag pour la taille du champ en BD */ - public static final String TAG_LENGTH = "length"; - - /** Tag pour ajouter une annotation à un champ */ - public static final String TAG_ANNOTATION = "annotation"; - - /** Tag pour ajouter specifier le copyright d'un fichier */ - public static final String TAG_COPYRIGHT = "copyright"; - - /** Tag pour specfier le type d'acces a un champ */ - public static final String TAG_ACCESS = "access"; - - /** Tag pour specfier si on doit générer i18n */ - public static final String TAG_I18N_PREFIX = "i18n"; - - /** Tag pour ajouter un attribut dans une clef métier */ - public static final String TAG_NATURAL_ID = "naturalId"; - - /** Tag pour spécifier la caractèrelazy d'une association multiple */ - public static final String TAG_LAZY = "lazy"; - - /** Tag pour spécifier la caractère fetch d'une association multiple */ - public static final String TAG_FETCH = "fetch"; - - /** Tag pour spécifier la caractère order-by d'une association multiple */ - public static final String TAG_ORDER_BY = "orderBy"; - - /** Tag pour spécifier la caractère not-null d'un attribut */ - public static final String TAG_NOT_NULL = "notNull"; - - /** Type de persistence Hibernate */ - public static final String PERSISTENCE_TYPE_HIBERNATE = "hibernate"; - - /** Type de persistence LDAP */ - public static final String PERSISTENCE_TYPE_LDAP = "ldap"; - - /** Type de persistence par défaut (si aucun précisé) */ - public static final String PERSISTENCE_TYPE_DEFAULT = PERSISTENCE_TYPE_HIBERNATE; - - /** Propriété des générateurs indiquant le package par défaut */ - public static final String PROPERTY_DEFAULT_PACKAGE = "defaultPackage"; - - /** Le package par défaut si aucun n'est spécifié */ - public static final String DEFAULT_PACKAGE = "org.codelutin.malo"; - - /** - * Renvoie le package par défaut pour le générateur donné - * - * @param generator le générateur donné - * @return le package par défaut du générator donné - */ - public static String getDefaultPackage(Generator generator) { - String packageName = generator.getProperty(PROPERTY_DEFAULT_PACKAGE); - if (packageName == null || "".equals(packageName)) { - packageName = DEFAULT_PACKAGE; - } - return packageName; - } - - /** - * Indique si l'élément spécifié dispose de documentation - * - * @param element l'élément à tester - * @return true s'il y a documentation, false sinon - */ - public static boolean hasDocumentation(ObjectModelElement element) { - return notEmpty(element.getDocumentation()); - } - - /** - * Indique si la chaine de caratère n'est pas vide (null ou "") - * - * @param s la chaine de caractères à tester - * @return true si <code>s</code> n'est pas vide - */ - public static boolean notEmpty(String s) { - return (s != null && !"".equals(s)); - } - - /** - * Renvoie l'interface DAO associée à la classe passée en paramètre - * - * @param clazz la classe à tester - * @param model le modele utilisé - * @return l'interface trouvée ou null sinon - */ - public static ObjectModelInterface getDAOInterface(ObjectModelClass clazz, - ObjectModel model) { - for (Object o : model.getInterfaces()) { - ObjectModelInterface daoInterface = (ObjectModelInterface) o; - if (daoInterface.getName().equals(clazz.getName() + "DAO")) { - if (daoInterface.hasStereotype(STEREOTYPE_DAO)) { - return daoInterface; - } - } - } - return null; - } - - /** - * Renvoie le type de persistence pour l'élément donné. Si aucun n'est - * trouvé, le type par défaut est utilisé - * - * @param element l'élément à tester - * @return le type de persitence pour l'élément donné. - */ - public static String getPersistenceType(ObjectModelElement element) { - String tag = element.getTagValue(TAG_PERSISTENCE_TYPE); - if (tag == null) { - tag = PERSISTENCE_TYPE_DEFAULT; - } - return tag; - } - - public static String getReverseDBName(ObjectModelAttribute attr) { - if (attr.getReverseAttribute() != null) { - return getDBName(attr.getReverseAttribute()); - } else { - return getDBName(attr) + "_id"; - } - } - - /** - * Renvoie le nom BD de l'élement passé en paramètre. Elle se base sur le - * tag associé si il existe, sinon sur le nom de l'élément - * - * @param element l'élément à tester - * @return le nom de table - */ - public static String getDBName(ObjectModelElement element) { - if (element == null) { - return null; - } - if (notEmpty(element.getTagValue(TAG_DB_NAME))) { - return element.getTagValue(TAG_DB_NAME); - } - return toLowerCaseFirstLetter(element.getName()); - } - - /** - * Cherche et renvoie le schema a utiliser sur cet element, sinon sur le model. - * - * @param element l'élément à tester - * @param model le modele utilisé - * @return le nom du schema ou null - */ - public static String getSchemaName(ObjectModelElement element, - ObjectModel model) { - return findTagValue(TAG_SCHEMA_NAME, element, model); - } - - /** - * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur le model. - * - * @param element l'élément à tester - * @param model le modele utilisé - * @return le prefix i18n ou <code>null</code> si non spécifié - */ - public static String getI18nPrefix(ObjectModelElement element, - ObjectModel model) { - return findTagValue(TAG_I18N_PREFIX, element, model); - } - - /** - * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. - * - * @param clazz la classe à tester - * @return la liste des attributs de la clef métier ou null si pas de clef métier. - */ - public static List<String> getNaturalId(ObjectModelClass clazz) { - - String value = clazz.getTagValue(TAG_NATURAL_ID); - if (value == null || value.trim().isEmpty()) { - return java.util.Collections.emptyList(); - } - List<String> result = new ArrayList<String>(); - for (String attribute : value.split(",")) { - result.add(attribute.trim()); - } - return result; - } - - /** - * Cherches et renvoie le copyright a utiliser sur le model. - * - * @param model le modele utilisé - * @return le texte du copyright ou null - */ - public static String getCopyright(Model model) { - return findTagValue(TAG_COPYRIGHT, null, model); - } - - /** - * Cherches et renvoie la valeur du tagvalue indique sur cet element, - * sinon sur le model. - * - * @param tagName le nom du tag - * @param element l'élément à tester - * @param model le modele utilisé - * @return la valeur du tagValue ou null - */ - public static String findTagValue(String tagName, - ObjectModelElement element, Model model) { - if (element == null) { - if (model != null) { - if (notEmpty(model.getTagValue(tagName))) { - return model.getTagValue(tagName); - } - } - return null; - } - if (notEmpty(element.getTagValue(tagName))) { - return element.getTagValue(tagName); - } - //On va chercher sur l'element declarant - return findTagValue(tagName, element.getDeclaringElement(), model); - } - - public static <Type extends ObjectModelElement> Collection<Type> getElementsWithStereotype( - Collection<Type> elements, String... stereotypes) { - Collection<Type> result = new ArrayList<Type>(); - for (Type element : elements) { - if (hasStereotypes(element, stereotypes)) { - result.add(element); - } - } - return result; - } - - public static boolean hasStereotypes(ObjectModelElement element, - String... stereotypes) { - for (String stereotype : stereotypes) { - if (!element.hasStereotype(stereotype)) { - return false; - } - } - return true; - } - - public static String getPrimaryKeyAttributesListDeclaration( - ObjectModelClass clazz, boolean includeName) { - String attributes = ""; - for (ObjectModelAttribute attr : getElementsWithStereotype(clazz - .getAttributes(), STEREOTYPE_PRIMARYKAY)) { - attributes += attr.getType(); - if (includeName) { - attributes += " " + attr.getName(); - } - attributes += ", "; - } - if (attributes.length() > 0) { - attributes = attributes.substring(0, attributes.length() - 2); - } - return attributes; - } - - public static String capitalize(String s) { - return StringUtils.capitalize(s); - } - - public static boolean isAssociationClassDoublon(ObjectModelAttribute attr) { - return (attr.getReverseAttribute() != null) - && (attr.getDeclaringElement().equals(attr - .getReverseAttribute().getDeclaringElement())) - && (!Util.isFirstAttribute(attr)); - } - - /** - * Renvoie le nom de l'attribut de classe d'association en fonction des cas: - * Si l'attribut porte le même nom que le type (extrémité inverse de - * l'association), on lui ajoute le nom de la classe d'association - * - * @param attr l'attribut a traiter - * @return le nom de l'attribut de classe d'association - */ - public static String getAssocAttrName(ObjectModelAttribute attr) { - String typeName = attr.getType().substring( - attr.getType().lastIndexOf(".") + 1); - String result = attr.getName(); - if (attr.getName().equalsIgnoreCase(typeName)) { - result += GeneratorUtil.capitalize(attr.getAssociationClass() - .getName()); - } - return result; - } - - public static String getDOType(ObjectModelElement elem, ObjectModel model) { - String type = elem.getName(); - if (elem instanceof ObjectModelAttribute) { - type = ((ObjectModelAttribute) elem).getType(); - } - if (elem instanceof ObjectModelClass) { - type = ((ObjectModelClass) elem).getQualifiedName(); - } - return getDOType(type, model); - } - - public static String getDOType(String type, ObjectModel model) { - if (!model.hasClass(type)) { - return type; - } - ObjectModelClass clazz = model.getClass(type); - if (clazz.hasStereotype(STEREOTYPE_ENTITY)) { - if (shouldBeAbstract(clazz)) { - type += "Abstract"; - } else { - type += "Impl"; - } - } - return type; - } - - private static Set<String> numberTypes = new HashSet<String>(); - - static { - numberTypes.add("byte"); - numberTypes.add("java.lang.Byte"); - numberTypes.add("short"); - numberTypes.add("java.lang.Short"); - numberTypes.add("int"); - numberTypes.add("java.lang.Integer"); - numberTypes.add("long"); - numberTypes.add("java.lang.Long"); - numberTypes.add("float"); - numberTypes.add("java.lang.Float"); - numberTypes.add("double"); - numberTypes.add("java.lang.Double"); - } - - public static boolean isNumericType(ObjectModelAttribute attr) { - return numberTypes.contains(attr.getType()); - } - - private static Set<String> textTypes = new HashSet<String>(); - - static { - textTypes.add("char"); - textTypes.add("java.lang.Char"); - textTypes.add("java.lang.String"); - } - - public static boolean isTextType(ObjectModelAttribute attr) { - return textTypes.contains(attr.getType()); - } - - public static boolean isDateType(ObjectModelAttribute attr) { - return "java.util.Date".equals(attr.getType()); - } - - public static boolean isBooleanType(ObjectModelAttribute attr) { - return ("boolean".equals(attr.getType()) || "java.lang.Boolean" - .equals(attr.getType())); - } - - /** - * Indique si la classe specifiee n'a aucune ou que des methodes abstraites - * - * @param clazz l'instance de ObjectModelClass - * @return true si la classe n'a que des operations abstraite ou aucune - * operation - */ - public static boolean hasNothingOrAbstractMethods(ObjectModelClass clazz) { - boolean result = true; - Iterator operations = clazz.getOperations().iterator(); - while (result && operations.hasNext()) { - ObjectModelOperation op = (ObjectModelOperation) operations.next(); - result = op.isAbstract(); - } - return result; - } - - /** - * Indique si la classe specifiee devrait etre abstraite - * - * @param clazz l'instance de ObjectModelClass - * @return true dans ce cas, false sinon - */ - public static boolean shouldBeAbstract(ObjectModelClass clazz) { - return clazz != null - && (clazz.isAbstract() && hasNothingOrAbstractMethods(clazz)); - } - - /** - * <p> - * Cette méthode permet de détecter si - * - l'attribut représente une relation 1-n - * - cette relation est unidirectionnelle - * - le type de l'attribut représente un entité - * - cette entité a des sous-classes dans le modèle - * <p/> - * Ce cas correspond à une incompatibilité d'Hibernate qui nous oblige a - * adopter un comportement particulier. - * </p> - * - * @param attr l'attribut a tester - * @param model le model - * @return true si et seulement si il s'agit bien de ce type de relation - */ - public static boolean hasUnidirectionalRelationOnAbstractType( - ObjectModelAttribute attr, ObjectModel model) { - ObjectModelAttribute reverse = attr.getReverseAttribute(); - //relation 1-n - if (reverse != null && isNMultiplicity(attr) - && !isNMultiplicity(reverse)) { - //Pas de navigabilité - if (!reverse.isNavigable()) { - //Il s'agit d'une entity - ObjectModelClass clazz = model.getClass(attr.getType()); - if (clazz != null && clazz.hasStereotype(STEREOTYPE_ENTITY)) { - //Cette classe a des sous-classes dans le modèle - for (ObjectModelClass subClass : model.getClasses()) { - if (subClass.getSuperclasses().contains(clazz)) { - return true; - } - } - } - } - } - return false; - } - - /** - * Renvoie le nom unique de table pour une relation ManyToMany en fonction - * de l'attribut <code>attr</code> - * <p/> - * Plusieurs cas de figure: - * <li> - * - * @param attr l'attribut servant de base au calcul du nom - * @return le nom de la table - */ - public static String getManyToManyTableName(ObjectModelAttribute attr) { - String result; - - if (attr.hasAssociationClass()) { - result = GeneratorUtil.getDBName(attr.getAssociationClass()); - } else { - String name = attr.getName(); - String revers = attr.getReverseAttributeName(); - - if (name.compareToIgnoreCase(revers) < 0) { - result = name + "_" + revers; - } else { - result = revers + "_" + name; - } - } - // String result; - // if (!Util.isFirstAttribute(attr)) { - // result = attr.getDeclaringElement().getName() + "_" + attr.getReverseAttribute().getDeclaringElement().getName(); - // } else { - // result = attr.getReverseAttribute().getDeclaringElement().getName() + "_" + attr.getDeclaringElement().getName(); - // } - return result.toLowerCase(); - } - - /** - * Renvoie le type d'interface à utiliser en fonction de l'attribut - * - * @param attr l'attribut a traiter - * @return String - */ - public static String getNMultiplicityInterfaceType(ObjectModelAttribute attr) { - if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { - return Set.class.getName(); - } else if (attr.isIndexed() || attr.isOrdered()) { - return List.class.getName(); - } - return Collection.class.getName(); - } - - /** - * Renvoie le type d'objet (instance) à utiliser en fonction de l'attribut - * - * @param attr l'attribut a traiter - * @return String - */ - public static String getNMultiplicityObjectType(ObjectModelAttribute attr) { - if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { - return HashSet.class.getName(); - } else if (attr.isIndexed() || attr.isOrdered()) { - //On considère qu'on ne sait pas traiter vraiment l'attribut "ordered" - // puisqu'on va conserver l'ordre d'insertion, et non un ordre en - // fonction d'un élément donné. Donc on renvoi une ArrayList - return ArrayList.class.getName(); - } - LinkedList.class.getName(); - return ArrayList.class.getName(); - } - - /** - * Renvoie le type d'interface à utiliser en fonction de l'attribut - * - * @param attr l'attribut a traiter - * @return String - */ - public static String getNMultiplicityHibernateType(ObjectModelAttribute attr) { - if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { - return "set"; - } else if (attr.isIndexed()) { - return "list"; - } - //attr.isOrdered() - On génère le ordered en bag - return "bag"; - } - - /** - * Obtain the list of entities classes with the possibility to sort the result. - * - * @param model the current model to scan - * @param sort flag to allow sort the result - * @return the list of filtred classes by their stereotype - */ - public static List<ObjectModelClass> getEntityClasses(ObjectModel model, - boolean sort) { - return getClassesByStereotype(STEREOTYPE_ENTITY, model, sort); - } - - /** - * Obtain the list of classes for a given stereotype with the possibility to sort the result. - * - * @param stereotype filter stereotype - * @param model the current model to scan - * @param sort flag to allow sort the result - * @return the list of filtred classes by their stereotype - */ - public static List<ObjectModelClass> getClassesByStereotype( - String stereotype, ObjectModel model, boolean sort) { - List<ObjectModelClass> classes = new ArrayList<ObjectModelClass>(); - for (ObjectModelClass clazz : model.getClasses()) { - if (clazz.hasStereotype(stereotype)) { - classes.add(clazz); - } - } - if (sort && !classes.isEmpty()) { - java.util.Collections.sort(classes, - new java.util.Comparator<ObjectModelClass>() { - public int compare(ObjectModelClass o1, - ObjectModelClass o2) { - return o1.getQualifiedName().compareTo( - o2.getQualifiedName()); - } - }); - } - return classes; - } -} // GeneratorUtil Copied: topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java (from rev 1298, topia/trunk/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java) =================================================================== --- topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java (rev 0) +++ topia/tags/2.1.2/topia-persistence/src/main/java/org/codelutin/topia/generator/GeneratorUtil.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,685 @@ +/* *##% ToPIA - Tools for Portable and Independent Architecture + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ + +/******************************************************************************* + * GeneratorUtil.java + * + * Created: 13 déc. 2005 + * + * @author Arnaud Thimel <thimel@codelutin.com> + * + * @version $Revision$ + * + * Mise a jour: $Date$ par : $Author$ + */ + +package org.codelutin.topia.generator; + +import org.apache.commons.lang.StringUtils; +import org.codelutin.generator.Generator; +import org.codelutin.generator.Util; +import org.codelutin.generator.models.Model; +import org.codelutin.generator.models.object.ObjectModel; +import org.codelutin.generator.models.object.ObjectModelAttribute; +import org.codelutin.generator.models.object.ObjectModelClass; +import org.codelutin.generator.models.object.ObjectModelElement; +import org.codelutin.generator.models.object.ObjectModelInterface; +import org.codelutin.generator.models.object.ObjectModelOperation; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +/** Classe regroupant divers méthodes utiles pour la génération des entités */ +public class GeneratorUtil extends Util { + + /** Stéréotype pour les interfaces devant être générées sous forme de facades */ + public final static String STEREOTYPE_FACADE = "facade"; + + /** Stéréotype pour les objets devant être générées sous forme d'entités */ + public static final String STEREOTYPE_ENTITY = "entity"; + + /** Stéréotype pour les objets devant être générées sous forme de DTO */ + public static final String STEREOTYPE_DTO = "dto"; + + /** + * Stéréotype pour les interfaces devant être générées sous forme de + * services + */ + public static final String STEREOTYPE_SERVICE = "service"; + + /** Stéréotype pour les interfaces devant être générées sous forme de DAO */ + public static final String STEREOTYPE_DAO = "dao"; + + /** Stéréotype pour les attributs à indexer en base */ + public static final String STEREOTYPE_INDEXED = "indexed"; + + /** Stéréotype pour les collections avec unicité */ + public static final String STEREOTYPE_UNIQUE = "unique"; + + /** Stéréotype pour les attributs étant des clés primaires */ + public static final String STEREOTYPE_PRIMARYKAY = "primaryKey"; + + /** Tag pour le type de persistence */ + public static final String TAG_PERSISTENCE_TYPE = "persistenceType"; + + /** Tag pour le nom du champ / entité en BD */ + public static final String TAG_DB_NAME = "dbName"; + + /** Tag pour le nom du schema en BD */ + public static final String TAG_SCHEMA_NAME = "dbSchema"; + + /** Tag pour la taille du champ en BD */ + public static final String TAG_LENGTH = "length"; + + /** Tag pour ajouter une annotation à un champ */ + public static final String TAG_ANNOTATION = "annotation"; + + /** Tag pour ajouter specifier le copyright d'un fichier */ + public static final String TAG_COPYRIGHT = "copyright"; + + /** Tag pour specfier le type d'acces a un champ */ + public static final String TAG_ACCESS = "access"; + + /** Tag pour specfier si on doit générer i18n */ + public static final String TAG_I18N_PREFIX = "i18n"; + + /** Tag pour ajouter un attribut dans une clef métier */ + public static final String TAG_NATURAL_ID = "naturalId"; + + /** Tag pour specifier si une clef metier est mutable */ + public static final String TAG_NATURAL_ID_MUTABLE = "naturalIdMutable"; + + /** Tag pour spécifier la caractèrelazy d'une association multiple */ + public static final String TAG_LAZY = "lazy"; + + /** Tag pour spécifier la caractère fetch d'une association multiple */ + public static final String TAG_FETCH = "fetch"; + + /** Tag pour spécifier la caractère order-by d'une association multiple */ + public static final String TAG_ORDER_BY = "orderBy"; + + /** Tag pour spécifier la caractère not-null d'un attribut */ + public static final String TAG_NOT_NULL = "notNull"; + + /** Tag pour spécifier la caractère embed-xml d'une association */ + public static final String TAG_EMBED_XML = "embedXml"; + + /** Type de persistence Hibernate */ + public static final String PERSISTENCE_TYPE_HIBERNATE = "hibernate"; + + /** Type de persistence LDAP */ + public static final String PERSISTENCE_TYPE_LDAP = "ldap"; + + /** Type de persistence par défaut (si aucun précisé) */ + public static final String PERSISTENCE_TYPE_DEFAULT = PERSISTENCE_TYPE_HIBERNATE; + + /** Propriété des générateurs indiquant le package par défaut */ + public static final String PROPERTY_DEFAULT_PACKAGE = "defaultPackage"; + + /** Le package par défaut si aucun n'est spécifié */ + public static final String DEFAULT_PACKAGE = "org.codelutin.malo"; + + /** + * Renvoie le package par défaut pour le générateur donné + * + * @param generator le générateur donné + * @return le package par défaut du générator donné + */ + public static String getDefaultPackage(Generator generator) { + String packageName = generator.getProperty(PROPERTY_DEFAULT_PACKAGE); + if (packageName == null || "".equals(packageName)) { + packageName = DEFAULT_PACKAGE; + } + return packageName; + } + + /** + * Indique si l'élément spécifié dispose de documentation + * + * @param element l'élément à tester + * @return true s'il y a documentation, false sinon + */ + public static boolean hasDocumentation(ObjectModelElement element) { + return notEmpty(element.getDocumentation()); + } + + /** + * Indique si la chaine de caratère n'est pas vide (null ou "") + * + * @param s la chaine de caractères à tester + * @return true si <code>s</code> n'est pas vide + */ + public static boolean notEmpty(String s) { + return (s != null && !"".equals(s)); + } + + /** + * Renvoie l'interface DAO associée à la classe passée en paramètre + * + * @param clazz la classe à tester + * @param model le modele utilisé + * @return l'interface trouvée ou null sinon + */ + public static ObjectModelInterface getDAOInterface(ObjectModelClass clazz, + ObjectModel model) { + for (Object o : model.getInterfaces()) { + ObjectModelInterface daoInterface = (ObjectModelInterface) o; + if (daoInterface.getName().equals(clazz.getName() + "DAO")) { + if (daoInterface.hasStereotype(STEREOTYPE_DAO)) { + return daoInterface; + } + } + } + return null; + } + + /** + * Renvoie le type de persistence pour l'élément donné. Si aucun n'est + * trouvé, le type par défaut est utilisé + * + * @param element l'élément à tester + * @return le type de persitence pour l'élément donné. + */ + public static String getPersistenceType(ObjectModelElement element) { + String tag = element.getTagValue(TAG_PERSISTENCE_TYPE); + if (tag == null) { + tag = PERSISTENCE_TYPE_DEFAULT; + } + return tag; + } + + public static String getReverseDBName(ObjectModelAttribute attr) { + if (attr.getReverseAttribute() != null) { + return getDBName(attr.getReverseAttribute()); + } else { + return getDBName(attr) + "_id"; + } + } + + /** + * Renvoie le nom BD de l'élement passé en paramètre. Elle se base sur le + * tag associé si il existe, sinon sur le nom de l'élément + * + * @param element l'élément à tester + * @return le nom de table + */ + public static String getDBName(ObjectModelElement element) { + if (element == null) { + return null; + } + if (notEmpty(element.getTagValue(TAG_DB_NAME))) { + return element.getTagValue(TAG_DB_NAME); + } + return toLowerCaseFirstLetter(element.getName()); + } + + /** + * Cherche et renvoie le schema a utiliser sur cet element, sinon sur le model. + * + * @param element l'élément à tester + * @param model le modele utilisé + * @return le nom du schema ou null + */ + public static String getSchemaName(ObjectModelElement element, + ObjectModel model) { + return findTagValue(TAG_SCHEMA_NAME, element, model); + } + + /** + * Cherche et renvoie le prefixe i18n à utiliser sur cet element, sinon sur le model. + * + * @param element l'élément à tester + * @param model le modele utilisé + * @return le prefix i18n ou <code>null</code> si non spécifié + */ + public static String getI18nPrefix(ObjectModelElement element, + ObjectModel model) { + return findTagValue(TAG_I18N_PREFIX, element, model); + } + + /** + * Cherche et renvoie la liste des attributs constituant la clef metier d'une classe. + * + * @param clazz la classe à tester + * @return la liste des attributs de la clef métier ou null si pas de clef métier. + */ + public static List<String> getNaturalId(ObjectModelClass clazz) { + String value = clazz.getTagValue(TAG_NATURAL_ID); + if (value == null || value.trim().isEmpty()) { + return java.util.Collections.emptyList(); + } + List<String> result = new ArrayList<String>(); + for (String attribute : value.split(",")) { + result.add(attribute.trim()); + } + return result; + } + + /** + * Detecte si un attribut fait partie d'une clef metier. + * + * @param attribute l'attribut à tester + * @return <code>true</code> si l'attribut fait partie d'une clef metier, <code>false</cdoe> sinon. + */ + public static boolean isNaturalId(ObjectModelAttribute attribute) { + String value = attribute.getTagValue(TAG_NATURAL_ID); + if (!notEmpty(value)) { + // valeur null, donc pas positionnee + return false; + } + try { + return Boolean.valueOf(value.trim()); + } catch (Exception e) { + // on a pas reussi a convertir en boolean. + //todo peut-être declancher une exception ? + return false; + } + } + + /** + * Cherches et renvoie le copyright a utiliser sur le model. + * + * @param model le modele utilisé + * @return le texte du copyright ou null + */ + public static String getCopyright(Model model) { + return findTagValue(TAG_COPYRIGHT, null, model); + } + + /** + * Cherches et renvoie la valeur du tagvalue indique sur cet element, + * sinon sur le model. + * + * @param tagName le nom du tag + * @param element l'élément à tester + * @param model le modele utilisé + * @return la valeur du tagValue ou null + */ + public static String findTagValue(String tagName, + ObjectModelElement element, Model model) { + if (element == null) { + if (model != null) { + if (notEmpty(model.getTagValue(tagName))) { + return model.getTagValue(tagName); + } + } + return null; + } + if (notEmpty(element.getTagValue(tagName))) { + return element.getTagValue(tagName); + } + //On va chercher sur l'element declarant + return findTagValue(tagName, element.getDeclaringElement(), model); + } + + public static <Type extends ObjectModelElement> Collection<Type> getElementsWithStereotype( + Collection<Type> elements, String... stereotypes) { + Collection<Type> result = new ArrayList<Type>(); + for (Type element : elements) { + if (hasStereotypes(element, stereotypes)) { + result.add(element); + } + } + return result; + } + + public static boolean hasStereotypes(ObjectModelElement element, + String... stereotypes) { + for (String stereotype : stereotypes) { + if (!element.hasStereotype(stereotype)) { + return false; + } + } + return true; + } + + public static String getPrimaryKeyAttributesListDeclaration( + ObjectModelClass clazz, boolean includeName) { + String attributes = ""; + for (ObjectModelAttribute attr : getElementsWithStereotype(clazz + .getAttributes(), STEREOTYPE_PRIMARYKAY)) { + attributes += attr.getType(); + if (includeName) { + attributes += " " + attr.getName(); + } + attributes += ", "; + } + if (attributes.length() > 0) { + attributes = attributes.substring(0, attributes.length() - 2); + } + return attributes; + } + + public static String capitalize(String s) { + return StringUtils.capitalize(s); + } + + public static boolean isAssociationClassDoublon(ObjectModelAttribute attr) { + return (attr.getReverseAttribute() != null) + && (attr.getDeclaringElement().equals(attr + .getReverseAttribute().getDeclaringElement())) + && (!Util.isFirstAttribute(attr)); + } + + /** + * Renvoie le nom de l'attribut de classe d'association en fonction des cas: + * Si l'attribut porte le même nom que le type (extrémité inverse de + * l'association), on lui ajoute le nom de la classe d'association + * + * @param attr l'attribut a traiter + * @return le nom de l'attribut de classe d'association + */ + public static String getAssocAttrName(ObjectModelAttribute attr) { + String typeName = attr.getType().substring( + attr.getType().lastIndexOf(".") + 1); + String result = attr.getName(); + if (attr.getName().equalsIgnoreCase(typeName)) { + result += GeneratorUtil.capitalize(attr.getAssociationClass() + .getName()); + } + return result; + } + + public static String getDOType(ObjectModelElement elem, ObjectModel model) { + String type = elem.getName(); + if (elem instanceof ObjectModelAttribute) { + type = ((ObjectModelAttribute) elem).getType(); + } + if (elem instanceof ObjectModelClass) { + type = ((ObjectModelClass) elem).getQualifiedName(); + } + return getDOType(type, model); + } + + public static String getDOType(String type, ObjectModel model) { + if (!model.hasClass(type)) { + return type; + } + ObjectModelClass clazz = model.getClass(type); + if (clazz.hasStereotype(STEREOTYPE_ENTITY)) { + if (shouldBeAbstract(clazz)) { + type += "Abstract"; + } else { + type += "Impl"; + } + } + return type; + } + + private static Set<String> numberTypes = new HashSet<String>(); + + static { + numberTypes.add("byte"); + numberTypes.add("java.lang.Byte"); + numberTypes.add("short"); + numberTypes.add("java.lang.Short"); + numberTypes.add("int"); + numberTypes.add("java.lang.Integer"); + numberTypes.add("long"); + numberTypes.add("java.lang.Long"); + numberTypes.add("float"); + numberTypes.add("java.lang.Float"); + numberTypes.add("double"); + numberTypes.add("java.lang.Double"); + } + + public static boolean isNumericType(ObjectModelAttribute attr) { + return numberTypes.contains(attr.getType()); + } + + private static Set<String> textTypes = new HashSet<String>(); + + static { + textTypes.add("char"); + textTypes.add("java.lang.Char"); + textTypes.add("java.lang.String"); + } + + public static boolean isTextType(ObjectModelAttribute attr) { + return textTypes.contains(attr.getType()); + } + + public static boolean isDateType(ObjectModelAttribute attr) { + return "java.util.Date".equals(attr.getType()); + } + + public static boolean isBooleanType(ObjectModelAttribute attr) { + return ("boolean".equals(attr.getType()) || "java.lang.Boolean" + .equals(attr.getType())); + } + + /** + * Indique si la classe specifiee n'a aucune ou que des methodes abstraites + * + * @param clazz l'instance de ObjectModelClass + * @return true si la classe n'a que des operations abstraite ou aucune + * operation + */ + public static boolean hasNothingOrAbstractMethods(ObjectModelClass clazz) { + boolean result = true; + Iterator operations = clazz.getOperations().iterator(); + while (result && operations.hasNext()) { + ObjectModelOperation op = (ObjectModelOperation) operations.next(); + result = op.isAbstract(); + } + return result; + } + + /** + * Indique si la classe specifiee devrait etre abstraite + * + * @param clazz l'instance de ObjectModelClass + * @return true dans ce cas, false sinon + */ + public static boolean shouldBeAbstract(ObjectModelClass clazz) { + return clazz != null + && (clazz.isAbstract() && hasNothingOrAbstractMethods(clazz)); + } + + /** + * <p> + * Cette méthode permet de détecter si + * - l'attribut représente une relation 1-n + * - cette relation est unidirectionnelle + * - le type de l'attribut représente un entité + * - cette entité a des sous-classes dans le modèle + * <p/> + * Ce cas correspond à une incompatibilité d'Hibernate qui nous oblige a + * adopter un comportement particulier. + * </p> + * + * @param attr l'attribut a tester + * @param model le model + * @return true si et seulement si il s'agit bien de ce type de relation + */ + public static boolean hasUnidirectionalRelationOnAbstractType( + ObjectModelAttribute attr, ObjectModel model) { + ObjectModelAttribute reverse = attr.getReverseAttribute(); + //relation 1-n + if (reverse != null && isNMultiplicity(attr) + && !isNMultiplicity(reverse)) { + //Pas de navigabilité + if (!reverse.isNavigable()) { + //Il s'agit d'une entity + ObjectModelClass clazz = model.getClass(attr.getType()); + if (clazz != null && clazz.hasStereotype(STEREOTYPE_ENTITY)) { + //Cette classe a des sous-classes dans le modèle + for (ObjectModelClass subClass : model.getClasses()) { + if (subClass.getSuperclasses().contains(clazz)) { + return true; + } + } + } + } + } + return false; + } + + /** + * Renvoie le nom unique de table pour une relation ManyToMany en fonction + * de l'attribut <code>attr</code> + * <p/> + * Plusieurs cas de figure: + * <li> + * + * @param attr l'attribut servant de base au calcul du nom + * @return le nom de la table + */ + public static String getManyToManyTableName(ObjectModelAttribute attr) { + String result; + + if (attr.hasAssociationClass()) { + result = GeneratorUtil.getDBName(attr.getAssociationClass()); + } else { + String name = attr.getName(); + String revers = attr.getReverseAttributeName(); + + if (name.compareToIgnoreCase(revers) < 0) { + result = name + "_" + revers; + } else { + result = revers + "_" + name; + } + } + // String result; + // if (!Util.isFirstAttribute(attr)) { + // result = attr.getDeclaringElement().getName() + "_" + attr.getReverseAttribute().getDeclaringElement().getName(); + // } else { + // result = attr.getReverseAttribute().getDeclaringElement().getName() + "_" + attr.getDeclaringElement().getName(); + // } + return result.toLowerCase(); + } + + /** + * Renvoie le type d'interface à utiliser en fonction de l'attribut + * + * @param attr l'attribut a traiter + * @return String + */ + public static String getNMultiplicityInterfaceType(ObjectModelAttribute attr) { + if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { + return Set.class.getName(); + } else if (attr.isIndexed() || attr.isOrdered()) { + return List.class.getName(); + } + return Collection.class.getName(); + } + + /** + * Renvoie le type d'objet (instance) à utiliser en fonction de l'attribut + * + * @param attr l'attribut a traiter + * @return String + */ + public static String getNMultiplicityObjectType(ObjectModelAttribute attr) { + if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { + return HashSet.class.getName(); + } else if (attr.isIndexed() || attr.isOrdered()) { + //On considère qu'on ne sait pas traiter vraiment l'attribut "ordered" + // puisqu'on va conserver l'ordre d'insertion, et non un ordre en + // fonction d'un élément donné. Donc on renvoi une ArrayList + return ArrayList.class.getName(); + } + LinkedList.class.getName(); + return ArrayList.class.getName(); + } + + /** + * Renvoie le type d'interface à utiliser en fonction de l'attribut + * + * @param attr l'attribut a traiter + * @return String + */ + public static String getNMultiplicityHibernateType(ObjectModelAttribute attr) { + if (attr.hasStereotype(STEREOTYPE_UNIQUE)) { + return "set"; + } else if (attr.isIndexed()) { + return "list"; + } + //attr.isOrdered() - On génère le ordered en bag + return "bag"; + } + + /** + * Obtain the list of entities classes with the possibility to sort the result. + * + * @param model the current model to scan + * @param sort flag to allow sort the result + * @return the list of filtred classes by their stereotype + */ + public static List<ObjectModelClass> getEntityClasses(ObjectModel model, + boolean sort) { + return getClassesByStereotype(STEREOTYPE_ENTITY, model, sort); + } + + /** + * Obtain the list of classes for a given stereotype with the possibility to sort the result. + * + * @param stereotype filter stereotype + * @param model the current model to scan + * @param sort flag to allow sort the result + * @return the list of filtred classes by their stereotype + */ + public static List<ObjectModelClass> getClassesByStereotype( + String stereotype, ObjectModel model, boolean sort) { + List<ObjectModelClass> classes = new ArrayList<ObjectModelClass>(); + for (ObjectModelClass clazz : model.getClasses()) { + if (clazz.hasStereotype(stereotype)) { + classes.add(clazz); + } + } + if (sort && !classes.isEmpty()) { + java.util.Collections.sort(classes, + new java.util.Comparator<ObjectModelClass>() { + public int compare(ObjectModelClass o1, + ObjectModelClass o2) { + return o1.getQualifiedName().compareTo( + o2.getQualifiedName()); + } + }); + } + return classes; + } + + /** + * Detecte si la clef metier d'une classe est mutable ou pas. + * <p/> + * On respecte la valeur par defaut d'hibernate, à savoir que par default une clef metier est non mutable. + * + * @param clazz la classe a tester + * @return <code>true</code> si le tag value a ete positionne sur la classe via le tag + * {@link #TAG_NATURAL_ID_MUTABLE}, , <code>false</code> sinon. + */ + public static boolean isNaturalIdMutable(ObjectModelClass clazz) { + String value = clazz.getTagValue(TAG_NATURAL_ID_MUTABLE); + if (!notEmpty(value)) { + // valeur null, donc par default positionnee + return false; + } + try { + return Boolean.valueOf(value.trim()); + } catch (Exception e) { + // on a pas reussi a convertir en boolean. + //todo peut-être declancher une exception ? + return false; + } + } +} // GeneratorUtil Deleted: topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst =================================================================== --- topia/trunk/topia-persistence/src/site/fr/rst/howto.rst 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,244 +0,0 @@ -How to -====== - -Ce document a pour objectif de prendre en main le framework Topia. Le document -est constitué de 4 parties, la modèlisation, la génération, la configuration et -l'utilisation. - -Modélisation ------------- - -La première étape constiste à réaliser le modèle UML soit avec Argouml -(http://argouml.tigris.org) soit avec Poséidon (http://www.gentleware.com). - -Le stérotype «entity» sur les classes permet de préciser que la classe est -persister par Topia. D'autre stérotypes (extern, service, ...) sont disponiples -mais ne sont pas présenté. - -Le fichier de modélisation peut être compléter par un fichier de configuration -nommé <nom fichier modélisation>.properties. Il contient des informations -techniques propres au librairie utilisé par Topia. - -Exemple : - -# Précise comment est mappé un type -# model.tagvalue.<type java>=<type base de donnée> -model.tagvalue.java.lang.String=text - -# Précise le schema de la base de données par défaut -# model.tagvalue.dbSchema=<nom schéma> -model.tagvalue.dbSchema=test - -# Précise l'entête de l'ensemble des fichiers générés -# model.tagvalue.copyright=<valeur> -model.tagvalue.copyright=/* *##%\n Copyright (C) 2007 Code Lutin\n *##% */ - -# Force le chargement d'un attribut -# <nom paquetage>.<nom entité>.attribute.<nom attribut>.tagvalue.lazy=false -org.codelutin.Person.attribute.association.tagvalue.lazy=false - -Génération ----------- - -La génération des fichiers Topia se font par l'utilisation d'un plugin maven. -Le plugin est disponnible sur le repository maven de Code Lutin à l'adresse -suivante http://lutinbuilder.labs.libre-entreprise.org/maven2. - -Configuration du plugin maven : - -<plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-generator-plugin</artifactId> - <version>0.63</version> - <executions> - <execution> - <phase>process-sources</phase> - <!--Configuration of model generator--> - <configuration> - <addCompileDirectory>true</addCompileDirectory> - <srcDirZuml>${maven.src.dir}/main/xmi</srcDirZuml> - <srcXmiDest>${maven.gen.dir}/xmi/</srcXmiDest> - <srcGenDest>${maven.gen.dir}/objectmodel/</srcGenDest> - <includes>**/*.objectmodel</includes> - <templates>org.codelutin.topia.generator.TopiaMetaGenerator</templates> - <destDirGen>${maven.gen.dir}/java</destDirGen> - <defaultPackage>org.codelutin</defaultPackage> - <extractedPackages>org.codelutin</extractedPackages> - </configuration> - <goals> - <goal>zargo2xmi</goal> - <goal>xmi2objectmodel</goal> - <goal>generate</goal> - </goals> - </execution> - </executions> - <dependencies> - <dependency> - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-persistence</artifactId> - <version>2.1.0-SNAPSHOT</version> - <scope>compile</scope> - </dependency> - </dependencies> -</plugin> - -Le plugin utilise lutin generator avec les templates de génération de Topia, le -fichier argouml ou poséidon doit se trouver dans le répertoire -${maven.src.dir}/main/xmi. Les fichiers sont générés dans le répertoire -${maven.gen.dir}/java. Il faut préciser au plugin les paquetages à traiter avec -le defaultPackage et extractedPackages. - -Ajout dans des dépendances de Topia pour la compilation des fichiers générés : - -<dependency> - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-persistence</artifactId> - <version>2.1.1</version> - <scope>compile</scope> -</dependency> - -Pour une classe modélisé, nous retrouvons 6 fichiers : - * Une interface - * Une classe abstraite - * Une implantation - * Une configuration hibernate - * Un DAO abstrait - * Une implantation du DAO - -Une classe Helper est aussi générée, permettant l'accès à l'ensemble des DAO. - -Configuration -------------- - -Un fichier contenant les informations de connexion à la base de données et de -configuration de Topia doit être créé au niveau des ressources du projet. - -Exemple : - -# Permet la création, la modification, ou pas automatique de la base de données -# [create | update | none] -hibernate.hbm2ddl.auto=update - -# Affichage des requêtes dans la console -# [true | false] -hibernate.show_sql=false - -# Permet de préciser les classes à persister -topia.persistence.classes=org.codelutin.Person, org.codelutin.Pet - -# Informations de connection : - -# Dialect à utiliser -hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect - -# Driver JDBC -hibernate.connection.driver_class=org.postgresql.Driver - -# URL de connection -hibernate.connection.url=jdbc:postgresql://localhost/mydb - -# Login de l'utilisateur qui se connecte -hibernate.connection.username=user - -# Mot de passe de l'utilisateur -hibernate.connection.password=xxxx - -Utilisation ------------ - -Implantation des méthodes -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Si des méthodes ont été définis dans le modèle de données il faut créer -l'implantation correspondante. Le paquetage doit porter le même nom que celui de -la génération. - -Gestion des transactions -~~~~~~~~~~~~~~~~~~~~~~~~ - ->>> Properties conf = Resource.getConfigProperties("/TopiaContext.properties"); - -Permet de charger un fichier contenant les informations de connexion à la base -et de configuration de Topia. - ->>> TopiaContext rootContext = TopiaContextFactory.getContext(conf); - -Récupère le context de départ pour la création de sous context pour la gestion -des entités. - ->>> TopiaContext transaction = rootContext.beginTransaction(); - -Création d'un sous context pour la gestion des entités. - ->>> transaction.commitTransaction(); - -Validation de l'état du context, les modifications des entités sont reportées -dans la base de données. - ->>> transaction.rollBackTransaction(); - -Invalidation de l'état du context, les modifications des entités ne sont pas -reportées dans la base de données. - ->>> transaction.closeContext(); - -Relâche la connexion JDBC d'un sous context et de ses sous contexts sans -validation de l'état des contexts. - ->>> rootContext.closeContext(); - -Relâche l'ensemble des ressources (cache, pools, ...) et relâche la connexion -JDBC des sous contexts avec validation de l'état des contexts. - -Manipulation des entités -~~~~~~~~~~~~~~~~~~~~~~~~ - ->>> PersonDAO personDAO = <nom modele>Helper.getPersonDAO(transaction); - -Récupération d'un DAO pour accéder à une entité. - ->>> Person person = personDAO.findByTopiaId(id); - -Les méthodes find permettent de récupérer une ou plusieurs selon différents -critères. - ->>> person.setName("tutu"); - -Manipulation de l'entité par les getters et setters. - ->>> Person person = personDAO.create(); - -Création d'une entité. Si vous utilisez l'instanciation classique java avec le -new, l'entité n'est pas persistée. - ->>> personDAO.update(person); - -Modification d'un entité. - ->>> personDAO.delete(person); - -Suppression d'une entité. - -Exemple -~~~~~~~ - -Properties conf = Resource.getConfigProperties("/TopiaContext.properties"); -TopiaContext rootContext = TopiaContextFactory.getContext(conf); - -TopiaContext transaction = rootContext.beginTransaction(); -PersonDAO personDAO = ModelHelper.getPersonDAO(transaction); - -Person person = personDAO.create(); -person.set...(...); -person.set...(...); -personDAO.update(person); - -person.get...(...); -person.get...(...); - -personDAO.delete(person); - -transaction.commitTransaction(); -transaction.closeContext(); - -rootContext.closeContext(); Copied: topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst (from rev 1298, topia/trunk/topia-persistence/src/site/fr/rst/howto.rst) =================================================================== --- topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst (rev 0) +++ topia/tags/2.1.2/topia-persistence/src/site/fr/rst/howto.rst 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,244 @@ +How to +====== + +Ce document a pour objectif de prendre en main le framework Topia. Le document +est constitué de 4 parties, la modèlisation, la génération, la configuration et +l'utilisation. + +Modélisation +------------ + +La première étape constiste à réaliser le modèle UML soit avec Argouml +(http://argouml.tigris.org) soit avec Poséidon (http://www.gentleware.com). + +Le stérotype «entity» sur les classes permet de préciser que la classe est +persistée par Topia. D'autre stérotypes (extern, service, ...) sont disponiples +mais ne sont pas présentés. + +Le fichier de modélisation peut être compléter par un fichier de configuration +nommé <nom fichier modélisation>.properties. Il contient des informations +techniques propres au librairie utilisé par Topia. + +Exemple : + +# Précise comment est mappé un type +# model.tagvalue.<type java>=<type base de donnée> +model.tagvalue.java.lang.String=text + +# Précise le schema de la base de données par défaut +# model.tagvalue.dbSchema=<nom schéma> +model.tagvalue.dbSchema=test + +# Précise l'entête de l'ensemble des fichiers générés +# model.tagvalue.copyright=<valeur> +model.tagvalue.copyright=/* *##%\n Copyright (C) 2007 Code Lutin\n *##% */ + +# Force le chargement d'un attribut +# <nom paquetage>.<nom entité>.attribute.<nom attribut>.tagvalue.lazy=false +org.codelutin.Person.attribute.association.tagvalue.lazy=false + +Génération +---------- + +La génération des fichiers Topia se font par l'utilisation d'un plugin maven. +Le plugin est disponnible sur le repository maven de Code Lutin à l'adresse +suivante http://lutinbuilder.labs.libre-entreprise.org/maven2. + +Configuration du plugin maven : + +<plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-generator-plugin</artifactId> + <version>0.63</version> + <executions> + <execution> + <phase>process-sources</phase> + <!--Configuration of model generator--> + <configuration> + <addCompileDirectory>true</addCompileDirectory> + <srcDirZuml>${maven.src.dir}/main/xmi</srcDirZuml> + <srcXmiDest>${maven.gen.dir}/xmi/</srcXmiDest> + <srcGenDest>${maven.gen.dir}/objectmodel/</srcGenDest> + <includes>**/*.objectmodel</includes> + <templates>org.codelutin.topia.generator.TopiaMetaGenerator</templates> + <destDirGen>${maven.gen.dir}/java</destDirGen> + <defaultPackage>org.codelutin</defaultPackage> + <extractedPackages>org.codelutin</extractedPackages> + </configuration> + <goals> + <goal>zargo2xmi</goal> + <goal>xmi2objectmodel</goal> + <goal>generate</goal> + </goals> + </execution> + </executions> + <dependencies> + <dependency> + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>2.1.0-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + </dependencies> +</plugin> + +Le plugin utilise lutin generator avec les templates de génération de Topia, le +fichier argouml ou poséidon doit se trouver dans le répertoire +${maven.src.dir}/main/xmi. Les fichiers sont générés dans le répertoire +${maven.gen.dir}/java. Il faut préciser au plugin les paquetages à traiter avec +le defaultPackage et extractedPackages. + +Ajout dans des dépendances de Topia pour la compilation des fichiers générés : + +<dependency> + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>2.1.1</version> + <scope>compile</scope> +</dependency> + +Pour une classe modélisé, nous retrouvons 6 fichiers : + * Une interface + * Une classe abstraite + * Une implantation + * Une configuration hibernate + * Un DAO abstrait + * Une implantation du DAO + +Une classe Helper est aussi générée, permettant l'accès à l'ensemble des DAO. + +Configuration +------------- + +Un fichier contenant les informations de connexion à la base de données et de +configuration de Topia doit être créé au niveau des ressources du projet. + +Exemple : + +# Permet la création, la modification, ou pas automatique de la base de données +# [create | update | none] +hibernate.hbm2ddl.auto=update + +# Affichage des requêtes dans la console +# [true | false] +hibernate.show_sql=false + +# Permet de préciser les classes à persister +topia.persistence.classes=org.codelutin.Person, org.codelutin.Pet + +# Informations de connection : + +# Dialect à utiliser +hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect + +# Driver JDBC +hibernate.connection.driver_class=org.postgresql.Driver + +# URL de connection +hibernate.connection.url=jdbc:postgresql://localhost/mydb + +# Login de l'utilisateur qui se connecte +hibernate.connection.username=user + +# Mot de passe de l'utilisateur +hibernate.connection.password=xxxx + +Utilisation +----------- + +Implantation des méthodes +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Si des méthodes ont été définis dans le modèle de données il faut créer +l'implantation correspondante. Le paquetage doit porter le même nom que celui de +la génération. + +Gestion des transactions +~~~~~~~~~~~~~~~~~~~~~~~~ + +>>> Properties conf = Resource.getConfigProperties("/TopiaContext.properties"); + +Permet de charger un fichier contenant les informations de connexion à la base +et de configuration de Topia. + +>>> TopiaContext rootContext = TopiaContextFactory.getContext(conf); + +Récupère le context de départ pour la création de sous context pour la gestion +des entités. + +>>> TopiaContext transaction = rootContext.beginTransaction(); + +Création d'un sous context pour la gestion des entités. + +>>> transaction.commitTransaction(); + +Validation de l'état du context, les modifications des entités sont reportées +dans la base de données. + +>>> transaction.rollBackTransaction(); + +Invalidation de l'état du context, les modifications des entités ne sont pas +reportées dans la base de données. + +>>> transaction.closeContext(); + +Relâche la connexion JDBC d'un sous context et de ses sous contexts sans +validation de l'état des contexts. + +>>> rootContext.closeContext(); + +Relâche l'ensemble des ressources (cache, pools, ...) et relâche la connexion +JDBC des sous contexts avec validation de l'état des contexts. + +Manipulation des entités +~~~~~~~~~~~~~~~~~~~~~~~~ + +>>> PersonDAO personDAO = <nom modele>Helper.getPersonDAO(transaction); + +Récupération d'un DAO pour accéder à une entité. + +>>> Person person = personDAO.findByTopiaId(id); + +Les méthodes find permettent de récupérer une ou plusieurs selon différents +critères. + +>>> person.setName("tutu"); + +Manipulation de l'entité par les getters et setters. + +>>> Person person = personDAO.create(); + +Création d'une entité. Si vous utilisez l'instanciation classique java avec le +new, l'entité n'est pas persistée. + +>>> personDAO.update(person); + +Modification d'un entité. + +>>> personDAO.delete(person); + +Suppression d'une entité. + +Exemple +~~~~~~~ + +Properties conf = Resource.getConfigProperties("/TopiaContext.properties"); +TopiaContext rootContext = TopiaContextFactory.getContext(conf); + +TopiaContext transaction = rootContext.beginTransaction(); +PersonDAO personDAO = ModelHelper.getPersonDAO(transaction); + +Person person = personDAO.create(); +person.set...(...); +person.set...(...); +personDAO.update(person); + +person.get...(...); +person.get...(...); + +personDAO.delete(person); + +transaction.commitTransaction(); +transaction.closeContext(); + +rootContext.closeContext(); Deleted: topia/tags/2.1.2/topia-soa/changelog.txt =================================================================== --- topia/trunk/topia-soa/changelog.txt 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-soa/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,4 +0,0 @@ -2.1.1 chemit 20081215 -* 20081215 [chemit] - new release for isis-fish :) -2.1.0 chemit 20081210 -* 20081205 [chemit] - improve poms, use lutinproject 3.2, tests in JUnit4 but ignore because must be redone! \ No newline at end of file Copied: topia/tags/2.1.2/topia-soa/changelog.txt (from rev 1301, topia/trunk/topia-soa/changelog.txt) =================================================================== --- topia/tags/2.1.2/topia-soa/changelog.txt (rev 0) +++ topia/tags/2.1.2/topia-soa/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,6 @@ +2.1.2 chemit 20090115 (follow other topia-release) + +2.1.1 chemit 20081215 +* 20081215 [chemit] - new release for isis-fish :) +2.1.0 chemit 20081210 +* 20081205 [chemit] - improve poms, use lutinproject 3.2, tests in JUnit4 but ignore because must be redone! \ No newline at end of file Deleted: topia/tags/2.1.2/topia-soa/pom.xml =================================================================== --- topia/trunk/topia-soa/pom.xml 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-soa/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,123 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>topia</artifactId> - <version>2.1.3-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-soa</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-persistence</artifactId> - <version>${project.version}</version> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutingenerator</artifactId> - </dependency> - - <!-- Dependencies for services --> - <dependency> - <groupId>org.apache.xmlrpc</groupId> - <artifactId>xmlrpc-server</artifactId> - <version>3.1</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>org.apache.xmlrpc</groupId> - <artifactId>xmlrpc-client</artifactId> - <version>3.1</version> - <scope>compile</scope> - </dependency> - - <dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> - <version>3.1</version> - <scope>runtime</scope> - </dependency> - - <dependency> - <groupId>org.codehaus.xfire</groupId> - <artifactId>xfire-java5</artifactId> - <version>1.2.6</version> - <exclusions> - <!-- Fix org.apache.ant conflict) --> - <exclusion> - <groupId>ant</groupId> - <artifactId>ant</artifactId> - </exclusion> - </exclusions> - </dependency> - - <!-- branch 5.1 : ne fonctionne pas en 6+ --> - <dependency> - <groupId>jetty</groupId> - <artifactId>jetty</artifactId> - <version>5.1.10</version> - <scope>test</scope> - </dependency> - - <!-- Dependencies for class generation --> - <dependency> - <groupId>asm</groupId> - <artifactId>asm</artifactId> - <version>1.5.3</version> - <scope>compile</scope> - </dependency> - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - - <name>ToPIA - SOA</name> - <description>Service Oriented Architecture module</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <defaultGoal>install</defaultGoal> - <plugins> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-processor-plugin</artifactId> - </plugin> - - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${maven.scm.connection.child}</connection> - <developerConnection>${maven.scm.developerConnection.child}</developerConnection> - <url>${maven.scm.url.child}</url> - </scm> - -</project> Copied: topia/tags/2.1.2/topia-soa/pom.xml (from rev 1302, topia/trunk/topia-soa/pom.xml) =================================================================== --- topia/tags/2.1.2/topia-soa/pom.xml (rev 0) +++ topia/tags/2.1.2/topia-soa/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,123 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>topia</artifactId> + <version>2.1.2</version> + </parent> + + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-soa</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-persistence</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutingenerator</artifactId> + </dependency> + + <!-- Dependencies for services --> + <dependency> + <groupId>org.apache.xmlrpc</groupId> + <artifactId>xmlrpc-server</artifactId> + <version>3.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.xmlrpc</groupId> + <artifactId>xmlrpc-client</artifactId> + <version>3.1</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + <scope>runtime</scope> + </dependency> + + <dependency> + <groupId>org.codehaus.xfire</groupId> + <artifactId>xfire-java5</artifactId> + <version>1.2.6</version> + <exclusions> + <!-- Fix org.apache.ant conflict) --> + <exclusion> + <groupId>ant</groupId> + <artifactId>ant</artifactId> + </exclusion> + </exclusions> + </dependency> + + <!-- branch 5.1 : ne fonctionne pas en 6+ --> + <dependency> + <groupId>jetty</groupId> + <artifactId>jetty</artifactId> + <version>5.1.10</version> + <scope>test</scope> + </dependency> + + <!-- Dependencies for class generation --> + <dependency> + <groupId>asm</groupId> + <artifactId>asm</artifactId> + <version>1.5.3</version> + <scope>compile</scope> + </dependency> + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>ToPIA - SOA</name> + <description>Service Oriented Architecture module</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <build> + <defaultGoal>install</defaultGoal> + <plugins> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-processor-plugin</artifactId> + </plugin> + + </plugins> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-soa</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-soa</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/topia/tags/2.1.2/topia-soa?root=topia</url> + </scm> + +</project> Deleted: topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java =================================================================== --- topia/trunk/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,402 +0,0 @@ -/* *##% ToPIA - Tools for Portable and Independent Architecture - * Copyright (C) 2004 - 2008 CodeLutin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Lesser Public License for more details. - * - * You should have received a copy of the GNU General Lesser Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ - -/** - * - */ -package org.codelutin.topia.service; - -import java.lang.reflect.Proxy; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codelutin.topia.TopiaContext; -import org.codelutin.topia.TopiaException; -import org.codelutin.topia.TopiaNotFoundException; -import org.codelutin.topia.framework.TopiaUtil; -import org.codelutin.topia.service.clients.RMIProxy; -import org.codelutin.topia.service.clients.SOAPProxy; -import org.codelutin.topia.service.clients.XMLRPCProxy; - -/** - * TopiaServiceFactory.java - * - * Classe utilisee pour charger les services. - * - * Deux utilisations possibles : - * <li>client: pour avoir une interface sur un service local ou distant - * <li>serveur: pour avoir un service local au serveur - * - * Sert aussi au serveur pour declarer des services - * - * @author chatellier - * @version $Revision$ - * - * Last update : $Date$ By : $Author$ - */ -public class TopiaApplicationServiceFactory { - - /** Fichier de configuration par defaut */ - public static final String DEFAULT_CONFIG_PROPERTIES = "TopiaContextImpl.properties"; - - /** Nom de la propriete de definition des services utilises */ - public static final String TOPIA_APPLICATION_SERVICE_BEGIN = "topia.application.service."; - - /** Nom de la propriete de definition des services fournit */ - public static final String TOPIA_APPLICATION_PROVIDE_BEGIN = "topia.application.provide."; - - /** Nom de la propriete de definition des ports suivant les protocoles */ - public static final String TOPIA_APPLICATION_SERVER_PORT_BEGIN = "topia.application.server.port."; - - /** - * Nom du dossier ou sont generer certains fichiers (doit etre dans le - * classpath ) - */ - public static String TOPIA_GENERATION_DIRECTORY = "topiagen"; - - /** Fichier de configuration */ - protected static Properties config; - - /** Dispatcher (servers) */ - protected static final TopiaServiceProvider mainDispatcher = new TopiaServiceProvider(); - - /** - * Stockage des services deja instancies - */ - private static Map<Class<? extends TopiaApplicationService>, TopiaApplicationService> mapServiceCache = new HashMap<Class<? extends TopiaApplicationService>, TopiaApplicationService>(); - - /** Logger (common logging) */ - private static final Log log = LogFactory - .getLog(TopiaApplicationServiceFactory.class); - - protected static TopiaContext defaultServiceContext; - - /** - * Retourne la configuration. Charge le fichier s'il n'a pas deja ete - * charge. - * - * @throws TopiaNotFoundException - * si le fichier de configuration ne peut pas etre charge - */ - static Properties getConfiguration() throws TopiaNotFoundException { - if (config == null) { - config = TopiaUtil.getProperties(DEFAULT_CONFIG_PROPERTIES); - } - return config; - } - - /** - * Charge et lance tous les services contenus dans le fichier de - * configuration - * - * @param config - * les proprietes du fichier de configuration - * @param context - * le contexte pere des contextes fournis aux services - * @throws TopiaException - */ - public static void loadServices(Properties config, TopiaContext context) - throws TopiaException { - - if (context == null) { - throw new NullPointerException( - "I need a valid TopiaContext to initialise application services"); - } - - defaultServiceContext = context; - // lecture du fichier de configuration - if (config == null) { - try { - config = getConfiguration(); - } catch (TopiaNotFoundException e) { - throw new TopiaNotFoundException( - "Can't find configuration file " - + DEFAULT_CONFIG_PROPERTIES); - } - } - // pour chaque service applicatif - Set<Object> keySet = config.keySet(); - for (Object key : keySet) { - - if (key.toString().startsWith(TOPIA_APPLICATION_PROVIDE_BEGIN)) { - - // convertir l'URI pour recuperer les parametres - String protos = config.getProperty(key.toString()); - String serviceClassName = ((String) key).replace( - TOPIA_APPLICATION_PROVIDE_BEGIN, ""); - - // lance pour chaque protocole - String[] tabProtos = protos.split(","); - - for (String proto : tabProtos) { - // instancier puis lancer le service - Protocol protocol = Protocol.valueOf(proto.trim().replace( - '-', '_').toUpperCase()); - - // read and set server port - if (config.get(TOPIA_APPLICATION_SERVER_PORT_BEGIN + proto) != null) { - Integer port = null; - try { - port = Integer.valueOf((String) config - .get(TOPIA_APPLICATION_SERVER_PORT_BEGIN - + proto)); - } catch (NumberFormatException e) { - log.warn("Can't convert " + proto - + " server port to integer", e); - } - mainDispatcher.setProtocolPort(protocol, port); - } - - try { - Class serviceInterface = Class.forName(serviceClassName); - Class serviceImplement = Class.forName(serviceClassName - + "Impl"); - - try { - Object newInstance = serviceImplement.newInstance(); - TopiaApplicationService service = (TopiaApplicationService) newInstance; - TopiaContext serviceContext = context - .beginTransaction(); - service.init(serviceContext); - addService(serviceInterface, service, protocol); - } catch (InstantiationException e) { - throw new TopiaException( - "Can't instanciate service class " - + serviceImplement); - } catch (IllegalAccessException e) { - throw new TopiaException( - "Can't access to service class " - + serviceImplement); - } - log.info("service " + serviceClassName - + " added for protocol " + proto); - } catch (ClassNotFoundException e) { - log.error("Class not found for " + serviceClassName, e); - } - } - } - } - } - - /** - * Fournit une interface sur un service en l'implementant comme definit dans - * la configuration. - * - * Configuration (TopiaApplicationServices.properties par defaut) : - * topia.application.service.fqn=local://fqnImpl/#new - * topia.application.service.fqn=local://fqnImpl - * topia.application.service.fqn=rmi://127.0.0.1:1099 - * topia.application.service.fqn=xmlrpc://127.0.0.1:9090 ... - * - * @param <E> - * l'interface doit etendre TopiaApplicationService - * @param serviceclazz - * l'interface du service - * @return l'implementation du service ou <tt>null</tt> si le service ne - * peut etre charge - * @see TopiaApplicationService - * @throws TopiaNotFoundException - * si le fichier de configuration n'existe pas - * @throws TopiaException - * si le service ne peut pas etre charge - */ - public static <E extends TopiaApplicationService> E getService( - Class<E> serviceclazz) throws TopiaNotFoundException, - TopiaException { - - // l'implementation a retourner - E serviceimpl = (E) mapServiceCache.get(serviceclazz); - - // s'il etait dans le cache on le retourne directement - // dans le cas "#new" il n'est jamais dans le cache, donc recree - if (serviceimpl != null) { - return serviceimpl; - } - - // configuration - Properties config = getConfiguration(); - - // recherche du service - String serviceUrl = (String) config.get(TOPIA_APPLICATION_SERVICE_BEGIN - + serviceclazz.getCanonicalName()); - if (serviceUrl == null) { - log.error("Properties '" + TOPIA_APPLICATION_SERVICE_BEGIN - + serviceclazz.getCanonicalName() - + "' not found in configuration"); - throw new TopiaNotFoundException("Service '" - + serviceclazz.getCanonicalName() - + "' not definided in configuration"); - } else { - - try { - // conversion de l'URI - URI uriService = new URI(serviceUrl); - String protocole = uriService.getScheme(); - String host = uriService.getHost(); - String fragment = uriService.getFragment(); - - // ensuite ca depend si le service est local ou distant - // local = local://fqn - // sinon, c'est distant - if ("local".equalsIgnoreCase(protocole)) { - - String fqClassImpl = host; - log.debug("Trying to load local service : " + fqClassImpl); - - // instanciation dynamique - try { - Class<E> resultClass = (Class<E>) Class - .forName(fqClassImpl); - serviceimpl = resultClass.newInstance(); - serviceimpl.init(defaultServiceContext - .beginTransaction()); - - // mise en cache - // sauf dans le cas ou il y a un "#new" a la fin de - // l'uri - if (!"new".equalsIgnoreCase(fragment)) { - mapServiceCache.put(serviceclazz, serviceimpl); - } - } catch (ClassNotFoundException eee) { - throw new TopiaException("Can't find service class " - + fqClassImpl); - } catch (InstantiationException eee) { - throw new TopiaException( - "Can't instanciate service class " - + fqClassImpl); - } catch (IllegalAccessException eee) { - throw new TopiaException("Can't access service class " - + fqClassImpl); - } - } - // prefix non local => proxy - else { - log.debug("Trying to get remote service : " + serviceUrl); - - TopiaProxy tProxy = getProxyForURI(uriService); - - if (tProxy == null) { - log.debug("Unsupported protocole : " + protocole); - } else { - - tProxy.setURI(uriService); - tProxy.setClass(serviceclazz); - - // le proxy tProxy definit suivant le protocole - // gere maintenant tous les appels sur l'interface - // demandee (serviceclazz) - serviceimpl = (E) Proxy.newProxyInstance(serviceclazz - .getClassLoader(), - new Class[] { serviceclazz }, tProxy); - - // mise en cache - mapServiceCache.put(serviceclazz, serviceimpl); - } - } - } catch (URISyntaxException e) { - if(log.isWarnEnabled()) { - log.warn("URI for service '" + serviceclazz.getCanonicalName() - + "' is invalid !", e); - } - } - } - - return serviceimpl; - } - - /** - * Retourne l'implementation d'un TopiaProxy en fonction du protocole de - * l'URI - * - * @param uriService - * @return l'implementation ou null si le protocol n'est pas géré - */ - protected static TopiaProxy getProxyForURI(URI uriService) { - - // result - TopiaProxy tProxy = null; - - if ("rmi".equalsIgnoreCase(uriService.getScheme())) { - tProxy = new RMIProxy(); - } else if ("xml-rpc".equalsIgnoreCase(uriService.getScheme())) { - tProxy = new XMLRPCProxy(); - } else if ("soap".equalsIgnoreCase(uriService.getScheme())) { - tProxy = new SOAPProxy(); - } - - return tProxy; - } - - /** - * Ajoute un service fournit par ToPIA. - * - * @param interfaze - * l'interface du service - * @param clazz - * la classe qui permet de creer des instances de - * l'implementation du service - * @param protocoles - * les protocoles de diffusion du service - * - * @see TopiaApplicationService - */ - public static void addService( - Class<? extends TopiaApplicationService> interfaze, - Class<? extends TopiaApplicationService> clazz, - Protocol... protocoles) { - log.debug("Adding service for '" + interfaze + "' in protocoles : " - + Arrays.toString(protocoles)); - - for (Protocol protocole : protocoles) { - mainDispatcher.addServiceClass(interfaze, clazz, protocole); - } - } - - /** - * Ajoute un service fournit par ToPIA. - * - * Celle-ci renvoie toujours la meme instance du service. - * - * @param <E> - * un type qui etend TopiaApplicationService - * @param interfaze - * l'interface du service - * @param instance - * l'instance de l'implementation du service - * @param protocoles - * les protocoles de diffusion du service - * - * @see TopiaApplicationService - */ - public static <E extends TopiaApplicationService> void addService( - Class<E> interfaze, E instance, Protocol... protocoles) { - log.debug("Adding service for '" + interfaze - + "'(unique instance) in protocoles : " - + Arrays.toString(protocoles)); - - for (Protocol protocole : protocoles) { - mainDispatcher.addServiceInstance(interfaze, instance, protocole); - } - } -} Copied: topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java (from rev 1298, topia/trunk/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java) =================================================================== --- topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java (rev 0) +++ topia/tags/2.1.2/topia-soa/src/main/java/org/codelutin/topia/service/TopiaApplicationServiceFactory.java 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,403 @@ +/* *##% ToPIA - Tools for Portable and Independent Architecture + * Copyright (C) 2004 - 2008 CodeLutin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Lesser Public License for more details. + * + * You should have received a copy of the GNU General Lesser Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/lgpl-3.0.html>. ##%*/ + +/** + * + */ +package org.codelutin.topia.service; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.codelutin.topia.TopiaContext; +import org.codelutin.topia.TopiaException; +import org.codelutin.topia.TopiaNotFoundException; +import org.codelutin.topia.framework.TopiaUtil; +import org.codelutin.topia.service.clients.RMIProxy; +import org.codelutin.topia.service.clients.SOAPProxy; +import org.codelutin.topia.service.clients.XMLRPCProxy; + +import java.lang.reflect.Proxy; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +/** + * TopiaServiceFactory.java + * + * Classe utilisee pour charger les services. + * + * Deux utilisations possibles : + * <li>client: pour avoir une interface sur un service local ou distant + * <li>serveur: pour avoir un service local au serveur + * + * Sert aussi au serveur pour declarer des services + * + * @author chatellier + * @version $Revision$ + * + * Last update : $Date$ By : $Author$ + */ +public class TopiaApplicationServiceFactory { + + /** Fichier de configuration par defaut */ + public static final String DEFAULT_CONFIG_PROPERTIES = "TopiaContextImpl.properties"; + + /** Nom de la propriete de definition des services utilises */ + public static final String TOPIA_APPLICATION_SERVICE_BEGIN = "topia.application.service."; + + /** Nom de la propriete de definition des services fournit */ + public static final String TOPIA_APPLICATION_PROVIDE_BEGIN = "topia.application.provide."; + + /** Nom de la propriete de definition des ports suivant les protocoles */ + public static final String TOPIA_APPLICATION_SERVER_PORT_BEGIN = "topia.application.server.port."; + + /** + * Nom du dossier ou sont generer certains fichiers (doit etre dans le + * classpath ) + */ + public static String TOPIA_GENERATION_DIRECTORY = "topiagen"; + + /** Fichier de configuration */ + protected static Properties config; + + /** Dispatcher (servers) */ + protected static final TopiaServiceProvider mainDispatcher = new TopiaServiceProvider(); + + /** + * Stockage des services deja instancies + */ + private static Map<Class<? extends TopiaApplicationService>, TopiaApplicationService> mapServiceCache = new HashMap<Class<? extends TopiaApplicationService>, TopiaApplicationService>(); + + /** Logger (common logging) */ + private static final Log log = LogFactory + .getLog(TopiaApplicationServiceFactory.class); + + protected static TopiaContext defaultServiceContext; + + /** + * Retourne la configuration. Charge le fichier s'il n'a pas deja ete + * charge. + * + * @throws TopiaNotFoundException + * si le fichier de configuration ne peut pas etre charge + * @return la configuration (et la charge si cela n'est pas déjà fait) + */ + static Properties getConfiguration() throws TopiaNotFoundException { + if (config == null) { + config = TopiaUtil.getProperties(DEFAULT_CONFIG_PROPERTIES); + } + return config; + } + + /** + * Charge et lance tous les services contenus dans le fichier de + * configuration + * + * @param config + * les proprietes du fichier de configuration + * @param context + * le contexte pere des contextes fournis aux services + * @throws TopiaException if any pb with topia + */ + public static void loadServices(Properties config, TopiaContext context) + throws TopiaException { + + if (context == null) { + throw new NullPointerException( + "I need a valid TopiaContext to initialise application services"); + } + + defaultServiceContext = context; + // lecture du fichier de configuration + if (config == null) { + try { + config = getConfiguration(); + } catch (TopiaNotFoundException e) { + throw new TopiaNotFoundException( + "Can't find configuration file " + + DEFAULT_CONFIG_PROPERTIES); + } + } + // pour chaque service applicatif + Set<Object> keySet = config.keySet(); + for (Object key : keySet) { + + if (key.toString().startsWith(TOPIA_APPLICATION_PROVIDE_BEGIN)) { + + // convertir l'URI pour recuperer les parametres + String protos = config.getProperty(key.toString()); + String serviceClassName = ((String) key).replace( + TOPIA_APPLICATION_PROVIDE_BEGIN, ""); + + // lance pour chaque protocole + String[] tabProtos = protos.split(","); + + for (String proto : tabProtos) { + // instancier puis lancer le service + Protocol protocol = Protocol.valueOf(proto.trim().replace( + '-', '_').toUpperCase()); + + // read and set server port + if (config.get(TOPIA_APPLICATION_SERVER_PORT_BEGIN + proto) != null) { + Integer port = null; + try { + port = Integer.valueOf((String) config + .get(TOPIA_APPLICATION_SERVER_PORT_BEGIN + + proto)); + } catch (NumberFormatException e) { + log.warn("Can't convert " + proto + + " server port to integer", e); + } + mainDispatcher.setProtocolPort(protocol, port); + } + + try { + Class serviceInterface = Class.forName(serviceClassName); + Class serviceImplement = Class.forName(serviceClassName + + "Impl"); + + try { + Object newInstance = serviceImplement.newInstance(); + TopiaApplicationService service = (TopiaApplicationService) newInstance; + TopiaContext serviceContext = context + .beginTransaction(); + service.init(serviceContext); + addService(serviceInterface, service, protocol); + } catch (InstantiationException e) { + throw new TopiaException( + "Can't instanciate service class " + + serviceImplement); + } catch (IllegalAccessException e) { + throw new TopiaException( + "Can't access to service class " + + serviceImplement); + } + log.info("service " + serviceClassName + + " added for protocol " + proto); + } catch (ClassNotFoundException e) { + log.error("Class not found for " + serviceClassName, e); + } + } + } + } + } + + /** + * Fournit une interface sur un service en l'implementant comme definit dans + * la configuration. + * + * Configuration (TopiaApplicationServices.properties par defaut) : + * topia.application.service.fqn=local://fqnImpl/#new + * topia.application.service.fqn=local://fqnImpl + * topia.application.service.fqn=rmi://127.0.0.1:1099 + * topia.application.service.fqn=xmlrpc://127.0.0.1:9090 ... + * + * @param <E> + * l'interface doit etendre TopiaApplicationService + * @param serviceclazz + * l'interface du service + * @return l'implementation du service ou <tt>null</tt> si le service ne + * peut etre charge + * @see TopiaApplicationService + * @throws TopiaNotFoundException + * si le fichier de configuration n'existe pas + * @throws TopiaException + * si le service ne peut pas etre charge + */ + public static <E extends TopiaApplicationService> E getService( + Class<E> serviceclazz) throws TopiaNotFoundException, + TopiaException { + + // l'implementation a retourner + E serviceimpl = (E) mapServiceCache.get(serviceclazz); + + // s'il etait dans le cache on le retourne directement + // dans le cas "#new" il n'est jamais dans le cache, donc recree + if (serviceimpl != null) { + return serviceimpl; + } + + // configuration + Properties config = getConfiguration(); + + // recherche du service + String serviceUrl = (String) config.get(TOPIA_APPLICATION_SERVICE_BEGIN + + serviceclazz.getCanonicalName()); + if (serviceUrl == null) { + log.error("Properties '" + TOPIA_APPLICATION_SERVICE_BEGIN + + serviceclazz.getCanonicalName() + + "' not found in configuration"); + throw new TopiaNotFoundException("Service '" + + serviceclazz.getCanonicalName() + + "' not definided in configuration"); + } else { + + try { + // conversion de l'URI + URI uriService = new URI(serviceUrl); + String protocole = uriService.getScheme(); + String host = uriService.getHost(); + String fragment = uriService.getFragment(); + + // ensuite ca depend si le service est local ou distant + // local = local://fqn + // sinon, c'est distant + if ("local".equalsIgnoreCase(protocole)) { + + String fqClassImpl = host; + log.debug("Trying to load local service : " + fqClassImpl); + + // instanciation dynamique + try { + Class<E> resultClass = (Class<E>) Class + .forName(fqClassImpl); + serviceimpl = resultClass.newInstance(); + serviceimpl.init(defaultServiceContext + .beginTransaction()); + + // mise en cache + // sauf dans le cas ou il y a un "#new" a la fin de + // l'uri + if (!"new".equalsIgnoreCase(fragment)) { + mapServiceCache.put(serviceclazz, serviceimpl); + } + } catch (ClassNotFoundException eee) { + throw new TopiaException("Can't find service class " + + fqClassImpl); + } catch (InstantiationException eee) { + throw new TopiaException( + "Can't instanciate service class " + + fqClassImpl); + } catch (IllegalAccessException eee) { + throw new TopiaException("Can't access service class " + + fqClassImpl); + } + } + // prefix non local => proxy + else { + log.debug("Trying to get remote service : " + serviceUrl); + + TopiaProxy tProxy = getProxyForURI(uriService); + + if (tProxy == null) { + log.debug("Unsupported protocole : " + protocole); + } else { + + tProxy.setURI(uriService); + tProxy.setClass(serviceclazz); + + // le proxy tProxy definit suivant le protocole + // gere maintenant tous les appels sur l'interface + // demandee (serviceclazz) + serviceimpl = (E) Proxy.newProxyInstance(serviceclazz + .getClassLoader(), + new Class[] { serviceclazz }, tProxy); + + // mise en cache + mapServiceCache.put(serviceclazz, serviceimpl); + } + } + } catch (URISyntaxException e) { + if(log.isWarnEnabled()) { + log.warn("URI for service '" + serviceclazz.getCanonicalName() + + "' is invalid !", e); + } + } + } + + return serviceimpl; + } + + /** + * Retourne l'implementation d'un TopiaProxy en fonction du protocole de + * l'URI + * + * @param uriService + * @return l'implementation ou null si le protocol n'est pas géré + */ + protected static TopiaProxy getProxyForURI(URI uriService) { + + // result + TopiaProxy tProxy = null; + + if ("rmi".equalsIgnoreCase(uriService.getScheme())) { + tProxy = new RMIProxy(); + } else if ("xml-rpc".equalsIgnoreCase(uriService.getScheme())) { + tProxy = new XMLRPCProxy(); + } else if ("soap".equalsIgnoreCase(uriService.getScheme())) { + tProxy = new SOAPProxy(); + } + + return tProxy; + } + + /** + * Ajoute un service fournit par ToPIA. + * + * @param interfaze + * l'interface du service + * @param clazz + * la classe qui permet de creer des instances de + * l'implementation du service + * @param protocoles + * les protocoles de diffusion du service + * + * @see TopiaApplicationService + */ + public static void addService( + Class<? extends TopiaApplicationService> interfaze, + Class<? extends TopiaApplicationService> clazz, + Protocol... protocoles) { + log.debug("Adding service for '" + interfaze + "' in protocoles : " + + Arrays.toString(protocoles)); + + for (Protocol protocole : protocoles) { + mainDispatcher.addServiceClass(interfaze, clazz, protocole); + } + } + + /** + * Ajoute un service fournit par ToPIA. + * + * Celle-ci renvoie toujours la meme instance du service. + * + * @param <E> + * un type qui etend TopiaApplicationService + * @param interfaze + * l'interface du service + * @param instance + * l'instance de l'implementation du service + * @param protocoles + * les protocoles de diffusion du service + * + * @see TopiaApplicationService + */ + public static <E extends TopiaApplicationService> void addService( + Class<E> interfaze, E instance, Protocol... protocoles) { + log.debug("Adding service for '" + interfaze + + "'(unique instance) in protocoles : " + + Arrays.toString(protocoles)); + + for (Protocol protocole : protocoles) { + mainDispatcher.addServiceInstance(interfaze, instance, protocole); + } + } +} Deleted: topia/tags/2.1.2/topia-ui/changelog.txt =================================================================== --- topia/trunk/topia-ui/changelog.txt 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-ui/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,4 +0,0 @@ -2.1.1 chemit 20081215 -* 20081215 [chemit] - new release for isis-fish :) -2.1.0 chemit 20081210 -* 20081205 [chemit] - improve poms, use lutinproject 3.2 Copied: topia/tags/2.1.2/topia-ui/changelog.txt (from rev 1301, topia/trunk/topia-ui/changelog.txt) =================================================================== --- topia/tags/2.1.2/topia-ui/changelog.txt (rev 0) +++ topia/tags/2.1.2/topia-ui/changelog.txt 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,5 @@ +2.1.2 chemit 20090115 (follow other topia-release) +2.1.1 chemit 20081215 +* 20081215 [chemit] - new release for isis-fish :) +2.1.0 chemit 20081210 +* 20081205 [chemit] - improve poms, use lutinproject 3.2 Deleted: topia/tags/2.1.2/topia-ui/pom.xml =================================================================== --- topia/trunk/topia-ui/pom.xml 2009-01-13 12:59:50 UTC (rev 1296) +++ topia/tags/2.1.2/topia-ui/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -1,74 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - - <modelVersion>4.0.0</modelVersion> - - <!-- ************************************************************* --> - <!-- *** POM Relationships *************************************** --> - <!-- ************************************************************* --> - - <parent> - <groupId>org.codelutin</groupId> - <artifactId>topia</artifactId> - <version>2.1.3-SNAPSHOT</version> - </parent> - - <groupId>org.codelutin.topia</groupId> - <artifactId>topia-ui</artifactId> - - <dependencies> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutinutil</artifactId> - </dependency> - - <dependency> - <groupId>org.codelutin</groupId> - <artifactId>lutingenerator</artifactId> - </dependency> - - <dependency> - <groupId>org.apache.tapestry</groupId> - <artifactId>tapestry-core</artifactId> - <version>5.0.7</version> - <scope>compile</scope> - </dependency> - - </dependencies> - - <!-- ************************************************************* --> - <!-- *** Project Information ************************************* --> - <!-- ************************************************************* --> - - <name>ToPIA - UI</name> - <description>User interface module</description> - - <!-- ************************************************************* --> - <!-- *** Build Settings ****************************************** --> - <!-- ************************************************************* --> - - <packaging>jar</packaging> - - <build> - <defaultGoal>install</defaultGoal> - <plugins> - - <plugin> - <groupId>org.codelutin</groupId> - <artifactId>maven-processor-plugin</artifactId> - </plugin> - - </plugins> - </build> - - <!-- ************************************************************* --> - <!-- *** Build Environment ************************************** --> - <!-- ************************************************************* --> - <scm> - <connection>${maven.scm.connection.child}</connection> - <developerConnection>${maven.scm.developerConnection.child}</developerConnection> - <url>${maven.scm.url.child}</url> - </scm> - -</project> Copied: topia/tags/2.1.2/topia-ui/pom.xml (from rev 1302, topia/trunk/topia-ui/pom.xml) =================================================================== --- topia/tags/2.1.2/topia-ui/pom.xml (rev 0) +++ topia/tags/2.1.2/topia-ui/pom.xml 2009-01-15 17:43:15 UTC (rev 1303) @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <!-- ************************************************************* --> + <!-- *** POM Relationships *************************************** --> + <!-- ************************************************************* --> + + <parent> + <groupId>org.codelutin</groupId> + <artifactId>topia</artifactId> + <version>2.1.2</version> + </parent> + + <groupId>org.codelutin.topia</groupId> + <artifactId>topia-ui</artifactId> + + <dependencies> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutinutil</artifactId> + </dependency> + + <dependency> + <groupId>org.codelutin</groupId> + <artifactId>lutingenerator</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.tapestry</groupId> + <artifactId>tapestry-core</artifactId> + <version>5.0.7</version> + <scope>compile</scope> + </dependency> + + </dependencies> + + <!-- ************************************************************* --> + <!-- *** Project Information ************************************* --> + <!-- ************************************************************* --> + + <name>ToPIA - UI</name> + <description>User interface module</description> + + <!-- ************************************************************* --> + <!-- *** Build Settings ****************************************** --> + <!-- ************************************************************* --> + + <packaging>jar</packaging> + + <build> + <defaultGoal>install</defaultGoal> + <plugins> + + <plugin> + <groupId>org.codelutin</groupId> + <artifactId>maven-processor-plugin</artifactId> + </plugin> + + </plugins> + </build> + + <!-- ************************************************************* --> + <!-- *** Build Environment ************************************** --> + <!-- ************************************************************* --> + <scm> + <connection>scm:svn:svn://anonymous@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-ui</connection> + <developerConnection>scm:svn:svn+ssh://tchemit@labs.libre-entreprise.org/svnroot/topia/topia/tags/2.1.2/topia-ui</developerConnection> + <url>http://labs.libre-entreprise.org/plugins/scmsvn/viewcvs.php/topia/tags/2.1.2/topia-ui?root=topia</url> + </scm> + +</project>