Topia-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
August 2010
- 2 participants
- 19 discussions
r2101 - in trunk/topia-service-replication/src: main/java/org/nuiton/topia/replication main/java/org/nuiton/topia/replication/model main/java/org/nuiton/topia/replication/operation main/resources/META-INF/services test/java/org/nuiton/topia/replication test/java/org/nuiton/topia/replication/operation test/resources/META-INF/services
by tchemit@users.nuiton.org 15 Aug '10
by tchemit@users.nuiton.org 15 Aug '10
15 Aug '10
Author: tchemit
Date: 2010-08-15 13:58:21 +0200 (Sun, 15 Aug 2010)
New Revision: 2101
Url: http://nuiton.org/repositories/revision/topia/2101
Log:
- sanitize replication api
- decouple replication service and replication model builder
Added:
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilder.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilderImpl.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProvider.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProviderImpl.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationLink.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractTopiaReplicationServiceTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplAllTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplTest.java
Removed:
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java
Modified:
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java
trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java
trunk/topia-service-replication/src/test/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
Deleted: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,688 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaEntity;
-import org.nuiton.topia.persistence.TopiaEntityEnum;
-import org.nuiton.topia.persistence.util.TopiaEntityHelper;
-import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
-import org.nuiton.topia.replication.model.ReplicationModel;
-import org.nuiton.topia.replication.model.ReplicationNode;
-import org.nuiton.topia.replication.model.ReplicationOperationDef;
-import org.nuiton.topia.replication.model.ReplicationOperationPhase;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.ServiceLoader;
-import java.util.Set;
-
-import static org.nuiton.i18n.I18n._;
-
-/**
- * Implantation du service de replication.
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.2.0
- */
-public class ReplicationEngine implements TopiaReplicationImplementor {
-
- /** Logger */
- private static final Log log = LogFactory.getLog(ReplicationEngine.class);
-
- /** le contexte sur la base source de la replication */
- protected TopiaContextImplementor context;
-
- /**
- * la liste des operations disponibles (chargee automatiquement via un
- * ServiceLoader sur le contract {@link TopiaReplicationOperation})
- *
- * @see #preInit(TopiaContextImplementor)
- */
- protected TopiaReplicationOperation[] operations;
-
- //--------------------------------------------------------------------------
- //-- TopiaService implementation -------------------------------------------
- //--------------------------------------------------------------------------
-
- @Override
- public String getServiceName() {
- return SERVICE_NAME;
- }
-
- @Override
- public Class<?>[] getPersistenceClasses() {
- // pas de classes persistentes pour ce service
- return null;
- }
-
- @Override
- public boolean preInit(TopiaContextImplementor context) {
- if (operations == null) {
- // chargement des operations disponibles une seule fois
-
- ServiceLoader<TopiaReplicationOperation> loader =
- ServiceLoader.load(TopiaReplicationOperation.class);
-
- List<TopiaReplicationOperation> operations =
- new ArrayList<TopiaReplicationOperation>();
-
- for (TopiaReplicationOperation op : loader) {
- if (log.isDebugEnabled()) {
- log.debug("detected operation " + op);
- }
- operations.add(op);
- }
- this.operations = operations.toArray(
- new TopiaReplicationOperation[operations.size()]);
- }
- return true;
- }
-
- @Override
- public boolean postInit(TopiaContextImplementor context) {
- this.context = context;
- //TODO avoir un objet pour lire les contrainte de resolution de cycle
- //TODO sur les dependances (par exemple, une dependance marquee comme
- // non nulle : ne peut jamais etre dettache, alors que dans le cas
- // contraire on peut dettacher la dependance
- // Cela permet de traiter plus de cas...
-
- //Properties prop = context.getConfig();
- return true;
- }
-
- //--------------------------------------------------------------------------
- //-- TopiaReplicationService implementation --------------------------------
- //--------------------------------------------------------------------------
-
- @Override
- public ReplicationModel prepare(TopiaEntityEnum[] contracts,
- String... entities) throws TopiaException {
- ReplicationModel model = createModel(contracts, entities);
-
- initModel(model, true);
-
- return model;
- }
-
- @Override
- public ReplicationModel prepareForAll(TopiaEntityEnum[] contracts) throws TopiaException {
- ReplicationModel model = createModelForAll(contracts);
-
- initModel(model, true);
-
- return model;
- }
-
- @Override
- public ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts,
- String... topiaIds) throws TopiaException {
- ReplicationModel model = createModelWithComputedOrder(contracts, topiaIds);
-
- initModel(model, false);
-
- return model;
- }
-
- @Override
- public void addBeforeOperation(ReplicationModel model,
- TopiaEntityEnum type,
- Class<? extends TopiaReplicationOperation> operationClass,
- Object... parameters) {
- createOperation(model,
- type,
- ReplicationOperationPhase.before,
- operationClass,
- parameters
- );
- }
-
- @Override
- public void addAfterOperation(ReplicationModel model,
- TopiaEntityEnum type,
- Class<? extends TopiaReplicationOperation> operationClass,
- Object... parameters) {
- createOperation(model,
- type,
- ReplicationOperationPhase.after,
- operationClass,
- parameters
- );
- }
-
- @Override
- public void doReplicate(ReplicationModel model,
- TopiaContext dstCtxt) throws Exception {
-
- checkNotNull("doReplicate", "model", model);
- checkNotNull("doReplicate", "dstCtxt", dstCtxt);
-
- TopiaContextImplementor srcCtxt = null;
-
- TopiaEntityIdsMap data = null;
-
- // keep the list of treated nodes (to roolback them if something
- // is wrong).
- List<ReplicationNode> treated = new ArrayList<ReplicationNode>();
- try {
-
- srcCtxt = (TopiaContextImplementor) context.beginTransaction();
-
- data = getIds(model, srcCtxt);
-
- srcCtxt.closeContext();
-
- model.adjustOperations(data);
-
- //FIXME tchemit 2077-07-26, should use next line when
- // http://nuiton.org/issues/show/779 is closed
- boolean needTransaction = true;
-// boolean needTransaction = ((TopiaContextImplementor) dstCtxt).getRootContext().equals(dstCtxt);
-
- TopiaContext tx;
-
- for (ReplicationNode node : model.getOrder()) {
-
- srcCtxt = (TopiaContextImplementor) context.beginTransaction();
-
- if (needTransaction) {
- tx = dstCtxt.beginTransaction();
- } else {
- tx = dstCtxt;
- }
- try {
- doReplicateNode(node, srcCtxt, tx, data, treated);
- } catch (Exception e) {
-
- // un erreur est survenu sur le noeud de réplication
- // on rollback la transaction de ce noeud
- try {
- tx.rollbackTransaction();
- } finally {
-
- // on revert les noeuds deja commite
- doRollback(model, data, treated, dstCtxt);
- }
-
- throw e;
- } finally {
- srcCtxt.closeContext();
- if (needTransaction) {
- // on doit fermer la transaction car on l'a ouverte dans
- // cette méthode, sinon c'est de la responsabilite du
- // code appellant
- tx.closeContext();
- }
- }
- }
-// } catch (Exception e) {
-// dstCtxt.rollbackTransaction();
-// throw e;
- } finally {
- if (data != null) {
- data.clear();
- }
- if (treated != null) {
- treated.clear();
- }
- // on ne doit jamais commiter sur la base source
- if (srcCtxt != null && !srcCtxt.isClosed()) {
- srcCtxt.rollbackTransaction();
- srcCtxt.closeContext();
- }
-// dstCtxt.closeContext();
- }
- }
-
- @Override
- public void doRollback(ReplicationModel model,
- TopiaEntityIdsMap data,
- List<ReplicationNode> nodes,
- TopiaContext dstCtxt) throws Exception {
- if (nodes.isEmpty()) {
-
- // aucun noeud de réplication commités
- return;
- }
-
- TopiaContextImplementor srcCtxt;
-
- TopiaContext tx;
-
- boolean needTransaction = true;
-
- log.info("Will rollback " + nodes.size() + " nodes...");
-
- for (ReplicationNode node : nodes) {
-
- log.info("Rollback node " + node);
- srcCtxt = (TopiaContextImplementor) context.beginTransaction();
-
- if (needTransaction) {
- tx = dstCtxt.beginTransaction();
- } else {
- tx = dstCtxt;
- }
- try {
- doRollbackNode(node, srcCtxt, tx, data);
- } catch (Exception e) {
-
- // un erreur est survenu sur le noeud de réplication
- // on rollback la transaction de ce noeud
-
- tx.rollbackTransaction();
-
- } finally {
- srcCtxt.rollbackTransaction();
- srcCtxt.closeContext();
-
- if (needTransaction) {
- // on doit fermer la transaction car on l'a ouverte dans
- // cette méthode, sinon c'est de la responsabilite du
- // code appellant
- tx.closeContext();
- }
- }
-
- }
- }
-
- //--------------------------------------------------------------------------
- //-- TopiaReplicationImplementor implementation ----------------------------
- //--------------------------------------------------------------------------
-
- @Override
- public ReplicationModel createModel(TopiaEntityEnum[] contracts,
- String... topiaIds)
- throws TopiaException {
-
- Set<Class<? extends TopiaEntity>> detectTypes =
- detectTypes(contracts, topiaIds);
- ReplicationModel model =
- new ReplicationModel(contracts, detectTypes, topiaIds);
- return model;
- }
-
- @Override
- public ReplicationModel createModelWithComputedOrder(
- TopiaEntityEnum[] contracts, String... topiaIds)
- throws TopiaException {
- ReplicationModel model =
- new ReplicationModel(contracts, false, topiaIds);
- return model;
- }
-
- @Override
- public ReplicationModel createModelForAll(TopiaEntityEnum[] contracts)
- throws TopiaException {
- ReplicationModel model = new ReplicationModel(contracts, true);
- return model;
- }
-
- @Override
- public ReplicationModel initModel(ReplicationModel model,
- boolean computeOrder)
- throws TopiaException {
- checkNotNull("initModel", "model", model);
-
- model.detectAssociations();
- model.detectDirectDependencies();
- if (computeOrder) {
- model.detectShell();
- model.detectDependencies();
- }
- model.detectObjectsToDettach();
- model.detectOperations();
- return model;
- }
-
- @Override
- public TopiaReplicationOperation getOperation(
- Class<? extends TopiaReplicationOperation> operationClass) {
- checkNotNull("getOperation", "operationClass", operationClass);
-
- if (operations == null) {
- throw new IllegalStateException("service was not init!");
- }
- TopiaReplicationOperation result = null;
-
- for (TopiaReplicationOperation op : operations) {
- if (operationClass.isAssignableFrom(op.getClass())) {
- result = op;
- break;
- }
- }
- return result;
- }
-
- @Override
- public void createOperation(ReplicationModel model,
- TopiaEntityEnum type,
- ReplicationOperationPhase phase,
- Class<? extends TopiaReplicationOperation> operationClass,
- Object... parameters) {
-
- checkNotNull("createOperation", "model", model);
- checkNotNull("createOperation", "type", type);
- checkNotNull("createOperation", "phase", phase);
- checkNotNull("createOperation", "operationClass", operationClass);
-
- TopiaReplicationOperation operation = getOperation(operationClass);
-
- if (operation == null) {
- throw new IllegalArgumentException(
- _("topia.replication.engine.error.unkown.operation",
- operationClass.getSimpleName(),
- Arrays.toString(operations))
- );
- }
-
- ReplicationNode node = model.getNode(type);
- if (node == null) {
- throw new IllegalArgumentException(
- _("topia.replication.engine.error.unkown.owner.node",
- type,
- operationClass.getSimpleName(),
- model.getNodes())
- );
- }
- operation.register(model, node, phase, parameters);
- }
-
- @Override
- public Set<Class<? extends TopiaEntity>> detectTypes(
- TopiaEntityEnum[] contracts, String... ids) throws TopiaException {
- TopiaContext ctxt = context.beginTransaction();
- try {
- TopiaEntity[] entities = getEntities(ctxt, ids);
-
- // on detecte tous les types connus pour les entites données
- Set<Class<? extends TopiaEntity>> types =
- TopiaEntityHelper.detectTypes(contracts, entities);
-
- if (log.isDebugEnabled()) {
- log.debug("for type : " + entities.getClass());
- for (Class<? extends TopiaEntity> k : types) {
- log.debug(k);
- }
- }
- return types;
- } finally {
- ctxt.closeContext();
- }
- }
-
- @Override
- public TopiaEntityIdsMap getIds(ReplicationModel model,
- TopiaContextImplementor srcCtxt)
- throws TopiaException {
-
- TopiaEntityIdsMap data;
-
- // on recupere les objets a repliquer par type
- if (model.isReplicateAll()) {
-
- // on recupere pour chaque type tous les ids des entites a repliquer
- data = new TopiaEntityIdsMap();
- for (TopiaEntityEnum e : model.getContracts()) {
- List<String> ids = srcCtxt.getDAO(e.getContract()).findAllIds();
- data.put(e.getContract(), ids);
- }
- } else {
-
- // on recupere les entites specifies a repliquer
- TopiaEntity[] entities = getEntities(srcCtxt,
- model.getTopiaIds()
- );
-
- // on calcule toutes les ids des entites a repliquer
- data = TopiaEntityHelper.detectEntityIds(model.getContracts(),
- model.getTypes(),
- entities
- );
- }
- return data;
- }
-
- @Override
- public void doReplicateNode(
- ReplicationNode node,
- TopiaContext srcCtxt,
- TopiaContext dstCtxt,
- TopiaEntityIdsMap data,
- List<ReplicationNode> treated) throws Exception {
-
- // on trie toujours les operations a realiser selon leur phase
- // (avant ou apres la duplication)
- node.sortOperations();
-
- List<ReplicationOperationDef> operationDefs = node.getOperations();
-
- if (operationDefs.isEmpty()) {
- log.info("skip node " + node + " - no operation detected.");
- } else {
-
- log.info("start for " + node + " : " + operationDefs.size() +
- " operation(s)");
-
- List<String> nodeEntityIds =
- data.get(node.getContract().getContract());
-
- if (log.isInfoEnabled()) {
- log.info("will replicate on " + nodeEntityIds.size() +
- " entity(ies)");
- }
- if (log.isDebugEnabled()) {
- for (String id : nodeEntityIds) {
- log.debug(id);
- }
- }
-
- List<? extends TopiaEntity> nodeEntities = getEntitiesList(
- srcCtxt,
- nodeEntityIds.toArray(new String[nodeEntityIds.size()])
- );
-
- for (ReplicationOperationDef operationDef : operationDefs) {
-
- log.info("start " + operationDef);
-
- TopiaReplicationOperation operation =
- getOperation(operationDef.getOperationClass());
-
- operation.run(operationDef,
- (TopiaContextImplementor) srcCtxt,
- (TopiaContextImplementor) dstCtxt,
- nodeEntities,
- data
- );
-
- }
- // on rollback le context source (car on a peut-etre modifie
- // des associations ou des dependances mais on ne veut rien
- // retenir au niveau d'hibernate, sinon on s'expose a des erreurs
- // lorsque l'on veut recharger des objets dans le context...)
- srcCtxt.rollbackTransaction();
- }
-
- treated.add(node);
- }
-
-
- @Override
- public void doRollbackNode(
- ReplicationNode node,
- TopiaContext srcCtxt,
- TopiaContext dstCtxt,
- TopiaEntityIdsMap data) throws Exception {
-
- // on trie toujours les operations a realiser selon leur phase
- // (avant ou apres la duplication)
- node.sortOperations();
-
- List<ReplicationOperationDef> operationDefs = node.getOperations();
-
- if (operationDefs.isEmpty()) {
- log.info("skip node " + node + " - no operation detected.");
- } else {
-
- log.info("start for " + node + " : " + operationDefs.size() +
- " operation(s)");
-
- List<String> nodeEntityIds =
- data.get(node.getContract().getContract());
- if (log.isInfoEnabled()) {
- log.info("will replicate on " + nodeEntityIds.size() +
- " entity(ies)");
- }
- if (log.isDebugEnabled()) {
- for (String id : nodeEntityIds) {
- log.debug(id);
- }
- }
-
- List<? extends TopiaEntity> nodeEntities = getEntitiesList(
- srcCtxt,
- nodeEntityIds.toArray(new String[nodeEntityIds.size()])
- );
-
- for (ReplicationOperationDef operationDef : operationDefs) {
-
- log.info("start " + operationDef);
-
- TopiaReplicationOperation operation =
- getOperation(operationDef.getOperationClass());
-
- operation.rollback(operationDef,
- (TopiaContextImplementor) srcCtxt,
- (TopiaContextImplementor) dstCtxt,
- nodeEntities,
- data
- );
-
- }
- // on rollback le context source (car on a peut-etre modifie
- // des associations ou des dependances mais on ne veut rien
- // retenir au niveau d'hibernate, sinon on s'expose a des erreurs
- // lorsque l'on veut recharger des objets dans le context...)
- srcCtxt.rollbackTransaction();
- }
- }
-
- @SuppressWarnings({"unchecked"})
- public static <E extends TopiaEntity> List<E> getEntities(
- TopiaContextImplementor srcCtxt,
- List<E> entityList,
- boolean canBeNull) throws TopiaException {
- List<E> srcList = new ArrayList<E>(entityList.size());
- for (E e : entityList) {
- E e2 = (E) srcCtxt.findByTopiaId(e.getTopiaId());
- if (e2 == null && !canBeNull) {
-// if (!canBeNull) {
-// throw new IllegalStateException(
-// "topia.replication.engine.error.entity.must.exists");
-// }
- continue;
- }
- srcList.add(e2);
- }
- return srcList;
- }
-
- public static TopiaEntity[] getEntities(TopiaContext srcCtxt,
- String... entityList)
- throws TopiaException {
- TopiaEntity[] srcList = new TopiaEntity[entityList.length];
- int index = 0;
- for (String id : entityList) {
- TopiaEntity e2 = srcCtxt.findByTopiaId(id);
- srcList[index++] = e2;
- }
- return srcList;
- }
-
- public static List<? extends TopiaEntity> getEntitiesList(
- TopiaContext srcCtxt,
- String... entityList) throws TopiaException {
- List<TopiaEntity> srcList = new ArrayList<TopiaEntity>(entityList.length);
- for (String id : entityList) {
- TopiaEntity e2 = srcCtxt.findByTopiaId(id);
- srcList.add(e2);
- }
- return srcList;
- }
-
- public static void checkNotNull(String methodName,
- String parameterName,
- Object value) {
- if (value == null) {
- throw new NullPointerException(
- _("topia.replication.engine.error.null.param",
- parameterName, methodName));
- }
- }
-
- public static void checkParameters(Class<?>[] paramsType,
- Object... params) {
- checkSize(paramsType.length, params);
- for (int i = 0, j = paramsType.length; i < j; i++) {
- checkType(paramsType, i, params);
- }
- }
-
- public static void checkSize(int size, Object[] params) {
- if (params.length != size) {
- throw new IllegalArgumentException(
- "l'operation requiere " + size + " parametres mais en a " +
- params.length);
- }
- }
-
- public static void checkType(Class<?>[] paramsType,
- int index,
- Object[] params) {
- Class<?> requiredType = paramsType[index];
- Object value = params[index];
- if (value == null) {
- throw new IllegalArgumentException(
- "le parametre de positiion" + index + " est null!");
- }
- Class<?> foundType = value.getClass();
-
- if (!requiredType.isAssignableFrom(foundType)) {
- throw new IllegalArgumentException(
- "le paremetre de position " + index +
- " requiere un parametre de type " + requiredType +
- " mais est de type " + foundType);
- }
- }
-}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -50,12 +50,17 @@
import java.util.Set;
/**
- * Class used internaly in framework, when you want implement new replication
- * engin, you must used this interface
+ * Class <b>previously</b> used internaly in framework, when you wanted
+ * to implement new replication engine.
+ * <p/>
+ * Now we are using a {@link TopiaReplicationModelBuilderImpl} insde the implemented
+ * service.
*
* @author tchemit <chemit(a)codelutin.com>
* @since 2.2.0
+ * @deprecated since 2.4.3, no more need of it, prefer use a {@link TopiaReplicationModelBuilderImpl}.
*/
+@Deprecated
public interface TopiaReplicationImplementor extends TopiaReplicationService {
/**
@@ -171,5 +176,5 @@
ReplicationNode node,
TopiaContext srcCtxt,
TopiaContext dstCtxt,
- TopiaEntityIdsMap data) throws Exception;
+ TopiaEntityIdsMap data) throws Exception;
}
Added: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilder.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilder.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilder.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,146 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+package org.nuiton.topia.replication;
+
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.model.ReplicationOperationPhase;
+
+import java.util.Set;
+
+/**
+ * Helper to create {@link ReplicationModel}.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.4.3
+ */
+public interface TopiaReplicationModelBuilder {
+
+ TopiaReplicationOperationProvider getOperationProvider();
+
+ TopiaReplicationOperation getOperation(Class<? extends TopiaReplicationOperation> operationClass);
+
+ TopiaReplicationOperation[] getOperations();
+
+ /**
+ * Creation d'un modele de replication non initialise.
+ *
+ * @param context topia context on which entities are loaded
+ * @param contracts le contrats d'entites autorises
+ * @param topiaIds les ids des entites a repliquer
+ * @return le modele instancie mais non initialise
+ * @throws TopiaException pour toute erreur
+ */
+ ReplicationModel createModel(TopiaContext context,
+ TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException;
+
+ /**
+ * Creation d'un modele de replication non initialise avec un ordre fixe
+ * (celui des contrats donnés).
+ *
+ * @param contracts le contrats d'entites autorises
+ * @param topiaIds les ids des entities a repliquer
+ * @return le modele instancie mais non initialise
+ * @throws TopiaException pour toute erreur
+ */
+ ReplicationModel createModelWithComputedOrder(
+ TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException;
+
+ /**
+ * Creation d'un modele de replication (en mode tout dupliquer) non initialise.
+ *
+ * @param contracts le contrats d'entites autorises
+ * @return le modele instancie mais non initialise
+ * @throws TopiaException pour toute erreur
+ */
+ ReplicationModel createModelForAll(TopiaEntityEnum[] contracts)
+ throws TopiaException;
+
+
+ ReplicationModel prepare(TopiaContext context,
+ TopiaEntityEnum[] contracts,
+ String... entities) throws TopiaException;
+
+ /**
+ * Prepare le modele de replication pour toutes les entites des types
+ * donnes.
+ * <p/>
+ * La méthode calcule l'ordre de replication des données.
+ * <p/>
+ * Actuellement, on n'est pas capable de calculer l'ordre si le graphe des
+ * entités contient des cycles.
+ * <p/>
+ * TODO : faire en sorte de pouvoir gérer les cycles.
+ *
+ * @param contracts les contrats des types a repliquer
+ * @return le modele pour la replication
+ * @throws TopiaException pour toute erreur rencontree
+ */
+ ReplicationModel prepareForAll(TopiaEntityEnum[] contracts) throws TopiaException;
+
+ /**
+ * Prepare le modele de replication pour les entites données en ne faisant
+ * pas de calcul sur l'ordre des entités à répliquer.
+ * <p/>
+ * L'ordre des types donnees sera celui utilisé.
+ *
+ * @param contracts les contrats a repliquer (dans l'ordre donnée)
+ * @param topiaIds les ids des entites a repliquer
+ * @return le model de replication initialise
+ * @throws TopiaException pour toute erreur recontree
+ */
+ ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException;
+
+ Set<Class<? extends TopiaEntity>> detectTypes(
+ TopiaContext context,
+ TopiaEntityEnum[] contracts, String... ids) throws TopiaException;
+
+ ReplicationModel initModel(ReplicationModel model,
+ boolean computeOrder)
+ throws TopiaException;
+
+ void addBeforeOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters);
+
+ void addAfterOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters);
+
+ void createOperation(
+ ReplicationModel model,
+ TopiaEntityEnum type,
+ ReplicationOperationPhase phase,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters);
+}
Added: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilderImpl.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilderImpl.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationModelBuilderImpl.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,258 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.model.ReplicationNode;
+import org.nuiton.topia.replication.model.ReplicationOperationPhase;
+
+import java.util.Arrays;
+import java.util.Set;
+
+import static org.nuiton.i18n.I18n._;
+
+/**
+ * Default implementation of {@link TopiaReplicationModelBuilder}.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.4.3
+ */
+public class TopiaReplicationModelBuilderImpl implements TopiaReplicationModelBuilder {
+
+ /** Logger */
+ private static final Log log =
+ LogFactory.getLog(TopiaReplicationModelBuilderImpl.class);
+
+ protected TopiaReplicationOperationProvider operationProvider;
+
+ @Override
+ public TopiaReplicationOperationProvider getOperationProvider() {
+ if (operationProvider == null) {
+ operationProvider = new TopiaReplicationOperationProviderImpl();
+ }
+ return operationProvider;
+ }
+
+ @Override
+ public TopiaReplicationOperation getOperation(Class<? extends TopiaReplicationOperation> operationClass) {
+ return getOperationProvider().getOperation(operationClass);
+ }
+
+ @Override
+ public TopiaReplicationOperation[] getOperations() {
+ return getOperationProvider().getOperations();
+ }
+
+
+ @Override
+ public ReplicationModel createModel(TopiaContext context,
+ TopiaEntityEnum[] contracts,
+ String... topiaIds)
+ throws TopiaException {
+
+ Set<Class<? extends TopiaEntity>> detectTypes =
+ detectTypes(context, contracts, topiaIds);
+ ReplicationModel model =
+ new ReplicationModel(contracts, detectTypes, topiaIds);
+ return model;
+ }
+
+
+ @Override
+ public ReplicationModel createModelWithComputedOrder(
+ TopiaEntityEnum[] contracts,
+ String... topiaIds)
+ throws TopiaException {
+ ReplicationModel model =
+ new ReplicationModel(contracts, false, topiaIds);
+ return model;
+ }
+
+
+ @Override
+ public ReplicationModel createModelForAll(TopiaEntityEnum[] contracts)
+ throws TopiaException {
+ ReplicationModel model = new ReplicationModel(contracts, true);
+ return model;
+ }
+
+ @Override
+ public void createOperation(
+ ReplicationModel model,
+ TopiaEntityEnum type,
+ ReplicationOperationPhase phase,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+
+ TopiaEntityHelper.checkNotNull("createOperation", "provider", operationProvider);
+ TopiaEntityHelper.checkNotNull("createOperation", "model", model);
+ TopiaEntityHelper.checkNotNull("createOperation", "type", type);
+ TopiaEntityHelper.checkNotNull("createOperation", "phase", phase);
+ TopiaEntityHelper.checkNotNull("createOperation", "operationClass", operationClass);
+
+ TopiaReplicationOperation operation = operationProvider.getOperation(operationClass);
+
+ if (operation == null) {
+ throw new IllegalArgumentException(
+ _("topia.replication.engine.error.unkown.operation",
+ operationClass.getSimpleName(),
+ Arrays.toString(operationProvider.getOperations()))
+ );
+ }
+
+ ReplicationNode node = model.getNode(type);
+ if (node == null) {
+ throw new IllegalArgumentException(
+ _("topia.replication.engine.error.unkown.owner.node",
+ type,
+ operationClass.getSimpleName(),
+ model.getNodes())
+ );
+ }
+ operation.register(model, node, phase, parameters);
+ }
+
+
+ @Override
+ public ReplicationModel prepare(TopiaContext context,
+ TopiaEntityEnum[] contracts,
+ String... entities) throws TopiaException {
+ ReplicationModel model =
+ createModel(context, contracts, entities);
+ initModel(model, true);
+ return model;
+ }
+
+
+ @Override
+ public ReplicationModel prepareForAll(TopiaEntityEnum[] contracts) throws TopiaException {
+ ReplicationModel model = createModelForAll(contracts);
+ initModel(model, true);
+ return model;
+ }
+
+
+ @Override
+ public ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException {
+ ReplicationModel model =
+ createModelWithComputedOrder(contracts, topiaIds);
+ initModel(model, false);
+ return model;
+ }
+
+ @Override
+ public Set<Class<? extends TopiaEntity>> detectTypes(TopiaContext context,
+ TopiaEntityEnum[] contracts,
+ String... ids) throws TopiaException {
+
+ TopiaContext ctxt = context.beginTransaction();
+ try {
+ TopiaEntity[] entities = TopiaEntityHelper.getEntities(ctxt, ids);
+
+ // on detecte tous les types connus pour les entites données
+ Set<Class<? extends TopiaEntity>> types =
+ TopiaEntityHelper.detectTypes(contracts, entities);
+
+ if (log.isDebugEnabled()) {
+ log.debug("for type : " + entities.getClass());
+ for (Class<? extends TopiaEntity> k : types) {
+ log.debug(k);
+ }
+ }
+ return types;
+ } finally {
+ ctxt.closeContext();
+ }
+ }
+
+ @Override
+ public ReplicationModel initModel(ReplicationModel model,
+ boolean computeOrder) throws TopiaException {
+ TopiaEntityHelper.checkNotNull("initModel", "model", model);
+
+ model.detectAssociations();
+ model.detectDirectDependencies();
+ if (computeOrder) {
+ model.detectShell();
+ model.detectDependencies();
+ }
+ model.detectObjectsToDettach();
+ model.detectOperations();
+ return model;
+ }
+
+
+ /**
+ * Ajouter une nouvelle operation pre-replication, sur un type de donnee.
+ *
+ * @param model le modele de replication
+ * @param type le type du noeud de replication
+ * @param operationClass l'implantation de l'operation
+ * @param parameters les parametres supplementaires pour l'operation
+ */
+ @Override
+ public void addBeforeOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ createOperation(
+ model,
+ type,
+ ReplicationOperationPhase.before,
+ operationClass,
+ parameters
+ );
+ }
+
+ /**
+ * Ajouter une nouvelle operation post-replication, sur un type de donnee.
+ *
+ * @param model le modele de replication
+ * @param type le type du noeud de replication
+ * @param operationClass l'implantation de l'operation
+ * @param parameters les parametres supplementaires pour l'operation
+ */
+ @Override
+ public void addAfterOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ createOperation(
+ model,
+ type,
+ ReplicationOperationPhase.after,
+ operationClass,
+ parameters
+ );
+ }
+}
Added: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProvider.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProvider.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProvider.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,53 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+package org.nuiton.topia.replication;
+
+import java.util.ServiceLoader;
+
+/**
+ * Provider of {@link TopiaReplicationOperation}.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.4.3
+ */
+public interface TopiaReplicationOperationProvider {
+
+ /**
+ * Obtains all {@link TopiaReplicationOperation} available
+ * via {@link ServiceLoader}.
+ *
+ * @return the array of available operations
+ */
+ TopiaReplicationOperation[] getOperations();
+
+ /**
+ * Obtains the instanciated (and initialized) operation of the given type.
+ *
+ * @param operationClass type of searched operation
+ * @return the found operation, or {@code null} if not found.
+ */
+ TopiaReplicationOperation getOperation(
+ Class<? extends TopiaReplicationOperation> operationClass);
+}
Added: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProviderImpl.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProviderImpl.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperationProviderImpl.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,92 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ServiceLoader;
+
+/**
+ * Default implementation of {@link TopiaReplicationOperationProvider}.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.4.3
+ */
+public class TopiaReplicationOperationProviderImpl implements TopiaReplicationOperationProvider {
+
+ /** Logger */
+ private static final Log log =
+ LogFactory.getLog(TopiaReplicationOperationProviderImpl.class);
+
+ /**
+ * la liste des operations disponibles (chargee automatiquement via un
+ * ServiceLoader sur le contract {@link TopiaReplicationOperation})
+ */
+ protected TopiaReplicationOperation[] operations;
+
+ @Override
+ public TopiaReplicationOperation[] getOperations() {
+ if (operations == null) {
+ // chargement des operations disponibles une seule fois
+
+ ServiceLoader<TopiaReplicationOperation> loader =
+ ServiceLoader.load(TopiaReplicationOperation.class);
+
+ List<TopiaReplicationOperation> operations =
+ new ArrayList<TopiaReplicationOperation>();
+
+ for (TopiaReplicationOperation op : loader) {
+ if (log.isDebugEnabled()) {
+ log.debug("detected operation " + op);
+ }
+ operations.add(op);
+ }
+ this.operations = operations.toArray(
+ new TopiaReplicationOperation[operations.size()]);
+ }
+ return operations;
+ }
+
+ @Override
+ public TopiaReplicationOperation getOperation(
+ Class<? extends TopiaReplicationOperation> operationClass) {
+
+ TopiaEntityHelper.checkNotNull("getOperation", "operationClass",
+ operationClass);
+ TopiaReplicationOperation result = null;
+
+ for (TopiaReplicationOperation op : getOperations()) {
+ if (operationClass.isAssignableFrom(op.getClass())) {
+ result = op;
+ break;
+ }
+ }
+ return result;
+ }
+}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -22,18 +22,6 @@
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* #L%
*/
-
-/* *
- * IndexEngin.java
- *
- * Created: 8 oct. 06 17:15:00
- *
- * @author poussin <poussin(a)codelutin.com>
- * @version $Revision$
- *
- * Last update: $Date$
- * by : $Author$
- */
package org.nuiton.topia.replication;
import org.nuiton.topia.TopiaContext;
@@ -72,6 +60,8 @@
/** Nom du service topia */
String TOPIA_SERVICE_NAME = "topia.service.replication";
+ TopiaReplicationModelBuilder getModelBuilder();
+
/**
* Prepare le modele de replication pour les entites dans les topiaIds sont
* donnes.
Copied: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java (from rev 2098, trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java)
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,576 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.framework.TopiaContextImplementor;
+import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
+import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.model.ReplicationNode;
+import org.nuiton.topia.replication.model.ReplicationOperationDef;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implantation du service de replication.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
+public class TopiaReplicationServiceImpl implements TopiaReplicationService {
+
+ /** Logger */
+ private static final Log log = LogFactory.getLog(TopiaReplicationServiceImpl.class);
+
+ /** le contexte sur la base source de la replication */
+ protected TopiaContextImplementor context;
+
+ protected TopiaReplicationModelBuilder modelBuilder;
+
+ //--------------------------------------------------------------------------
+ //-- TopiaService implementation -------------------------------------------
+ //--------------------------------------------------------------------------
+
+ @Override
+ public String getServiceName() {
+ return SERVICE_NAME;
+ }
+
+ @Override
+ public Class<?>[] getPersistenceClasses() {
+ // pas de classes persistentes pour ce service
+ return null;
+ }
+
+ @Override
+ public boolean preInit(TopiaContextImplementor context) {
+ // nothing to init
+ return true;
+ }
+
+ @Override
+ public boolean postInit(TopiaContextImplementor context) {
+ // set the incoming root context from topia
+ this.context = context;
+ //TODO avoir un objet pour lire les contrainte de resolution de cycle
+ //TODO sur les dependances (par exemple, une dependance marquee comme
+ // non nulle : ne peut jamais etre dettache, alors que dans le cas
+ // contraire on peut dettacher la dependance
+ // Cela permet de traiter plus de cas...
+
+ //Properties prop = context.getConfig();
+ return true;
+ }
+
+ //--------------------------------------------------------------------------
+ //-- TopiaReplicationService implementation --------------------------------
+ //--------------------------------------------------------------------------
+
+ @Override
+ public ReplicationModel prepare(TopiaEntityEnum[] contracts,
+ String... entities) throws TopiaException {
+ ReplicationModel model = getModelBuilder().prepare(context, contracts, entities);
+ return model;
+// ReplicationModel model =
+// createModel(contracts, entities);
+//
+// initModel(model, true);
+//
+// return model;
+ }
+
+ @Override
+ public ReplicationModel prepareForAll(TopiaEntityEnum[] contracts) throws TopiaException {
+ ReplicationModel model = getModelBuilder().prepareForAll(contracts);
+ return model;
+// ReplicationModel model = createModelForAll(contracts);
+//
+// initModel(model, true);
+//
+// return model;
+ }
+
+ @Override
+ public ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException {
+ ReplicationModel model = getModelBuilder().prepareWithComputedOrder(contracts);
+ return model;
+// ReplicationModel model = createModelWithComputedOrder(contracts, topiaIds);
+//
+// initModel(model, false);
+//
+// return model;
+ }
+
+ @Override
+ public void addBeforeOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ getModelBuilder().addBeforeOperation(model, type, operationClass, parameters);
+// createOperation(model,
+// type,
+// ReplicationOperationPhase.before,
+// operationClass,
+// parameters
+// );
+ }
+
+ @Override
+ public void addAfterOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ getModelBuilder().addAfterOperation(model, type, operationClass, parameters);
+// createOperation(model,
+// type,
+// ReplicationOperationPhase.after,
+// operationClass,
+// parameters
+// );
+ }
+
+ @Override
+ public void doReplicate(ReplicationModel model,
+ TopiaContext dstCtxt) throws Exception {
+
+ TopiaEntityHelper.checkNotNull("doReplicate", "model", model);
+ TopiaEntityHelper.checkNotNull("doReplicate", "dstCtxt", dstCtxt);
+
+ TopiaContextImplementor srcCtxt = null;
+
+ TopiaEntityIdsMap data = null;
+
+ // keep the list of treated nodes (to roolback them if something
+ // is wrong).
+ List<ReplicationNode> treated = new ArrayList<ReplicationNode>();
+ try {
+
+ srcCtxt = (TopiaContextImplementor) context.beginTransaction();
+
+ data = getIds(model, srcCtxt);
+
+ srcCtxt.closeContext();
+
+ model.adjustOperations(data);
+
+ //FIXME tchemit 2077-07-26, should use next line when
+ // http://nuiton.org/issues/show/779 is closed
+ boolean needTransaction = true;
+// boolean needTransaction = ((TopiaContextImplementor) dstCtxt).getRootContext().equals(dstCtxt);
+
+ TopiaContext tx;
+
+ for (ReplicationNode node : model.getOrder()) {
+
+ srcCtxt = (TopiaContextImplementor) context.beginTransaction();
+
+ if (needTransaction) {
+ tx = dstCtxt.beginTransaction();
+ } else {
+ tx = dstCtxt;
+ }
+ try {
+ doReplicateNode(node, srcCtxt, tx, data, treated);
+ } catch (Exception e) {
+
+ // un erreur est survenu sur le noeud de réplication
+ // on rollback la transaction de ce noeud
+ try {
+ tx.rollbackTransaction();
+ } finally {
+
+ // on revert les noeuds deja commite
+ doRollback(model, data, treated, dstCtxt);
+ }
+
+ throw e;
+ } finally {
+ srcCtxt.closeContext();
+ if (needTransaction) {
+ // on doit fermer la transaction car on l'a ouverte dans
+ // cette méthode, sinon c'est de la responsabilite du
+ // code appellant
+ tx.closeContext();
+ }
+ }
+ }
+// } catch (Exception e) {
+// dstCtxt.rollbackTransaction();
+// throw e;
+ } finally {
+ if (data != null) {
+ data.clear();
+ }
+ if (treated != null) {
+ treated.clear();
+ }
+ // on ne doit jamais commiter sur la base source
+ if (srcCtxt != null && !srcCtxt.isClosed()) {
+ srcCtxt.rollbackTransaction();
+ srcCtxt.closeContext();
+ }
+// dstCtxt.closeContext();
+ }
+ }
+
+ @Override
+ public void doRollback(ReplicationModel model,
+ TopiaEntityIdsMap data,
+ List<ReplicationNode> nodes,
+ TopiaContext dstCtxt) throws Exception {
+ if (nodes.isEmpty()) {
+
+ // aucun noeud de réplication commités
+ return;
+ }
+
+ TopiaContextImplementor srcCtxt;
+
+ TopiaContext tx;
+
+ boolean needTransaction = true;
+
+ log.info("Will rollback " + nodes.size() + " nodes...");
+
+ for (ReplicationNode node : nodes) {
+
+ log.info("Rollback node " + node);
+ srcCtxt = (TopiaContextImplementor) context.beginTransaction();
+
+ if (needTransaction) {
+ tx = dstCtxt.beginTransaction();
+ } else {
+ tx = dstCtxt;
+ }
+ try {
+ doRollbackNode(node, srcCtxt, tx, data);
+ } catch (Exception e) {
+
+ // un erreur est survenu sur le noeud de réplication
+ // on rollback la transaction de ce noeud
+
+ tx.rollbackTransaction();
+
+ } finally {
+ srcCtxt.rollbackTransaction();
+ srcCtxt.closeContext();
+
+ if (needTransaction) {
+ // on doit fermer la transaction car on l'a ouverte dans
+ // cette méthode, sinon c'est de la responsabilite du
+ // code appellant
+ tx.closeContext();
+ }
+ }
+
+ }
+ }
+
+ @Override
+ public TopiaReplicationModelBuilder getModelBuilder() {
+ if (modelBuilder == null) {
+ modelBuilder = new TopiaReplicationModelBuilderImpl();
+ }
+ return modelBuilder;
+ }
+
+ //--------------------------------------------------------------------------
+ //-- TopiaReplicationImplementor implementation ----------------------------
+ //--------------------------------------------------------------------------
+
+// @Override
+// public ReplicationModel createModel(TopiaEntityEnum[] contracts,
+// String... topiaIds)
+// throws TopiaException {
+//
+// Set<Class<? extends TopiaEntity>> detectTypes =
+// detectTypes(contracts, topiaIds);
+// ReplicationModel model =
+// new ReplicationModel(contracts, detectTypes, topiaIds);
+// return model;
+// }
+//
+// @Override
+// public ReplicationModel createModelWithComputedOrder(
+// TopiaEntityEnum[] contracts, String... topiaIds)
+// throws TopiaException {
+// ReplicationModel model =
+// new ReplicationModel(contracts, false, topiaIds);
+// return model;
+// }
+//
+// @Override
+// public ReplicationModel createModelForAll(TopiaEntityEnum[] contracts)
+// throws TopiaException {
+// ReplicationModel model = new ReplicationModel(contracts, true);
+// return model;
+// }
+//
+// @Override
+// public ReplicationModel initModel(ReplicationModel model,
+// boolean computeOrder)
+// throws TopiaException {
+// checkNotNull("initModel", "model", model);
+//
+// model.detectAssociations();
+// model.detectDirectDependencies();
+// if (computeOrder) {
+// model.detectShell();
+// model.detectDependencies();
+// }
+// model.detectObjectsToDettach();
+// model.detectOperations();
+// return model;
+// }
+//
+// @Override
+// public TopiaReplicationOperation getOperation(
+// Class<? extends TopiaReplicationOperation> operationClass) {
+// checkNotNull("getOperation", "operationClass", operationClass);
+//
+// if (operations == null) {
+// throw new IllegalStateException("service was not init!");
+// }
+// TopiaReplicationOperation result = null;
+//
+// for (TopiaReplicationOperation op : operations) {
+// if (operationClass.isAssignableFrom(op.getClass())) {
+// result = op;
+// break;
+// }
+// }
+// return result;
+// }
+//
+// @Override
+// public void createOperation(ReplicationModel model,
+// TopiaEntityEnum type,
+// ReplicationOperationPhase phase,
+// Class<? extends TopiaReplicationOperation> operationClass,
+// Object... parameters) {
+//
+// checkNotNull("createOperation", "model", model);
+// checkNotNull("createOperation", "type", type);
+// checkNotNull("createOperation", "phase", phase);
+// checkNotNull("createOperation", "operationClass", operationClass);
+//
+// TopiaReplicationOperation operation = getOperation(operationClass);
+//
+// if (operation == null) {
+// throw new IllegalArgumentException(
+// _("topia.replication.engine.error.unkown.operation",
+// operationClass.getSimpleName(),
+// Arrays.toString(operations))
+// );
+// }
+//
+// ReplicationNode node = model.getNode(type);
+// if (node == null) {
+// throw new IllegalArgumentException(
+// _("topia.replication.engine.error.unkown.owner.node",
+// type,
+// operationClass.getSimpleName(),
+// model.getNodes())
+// );
+// }
+// operation.register(model, node, phase, parameters);
+// }
+
+// @Override
+
+ public TopiaEntityIdsMap getIds(ReplicationModel model,
+ TopiaContextImplementor srcCtxt)
+ throws TopiaException {
+
+ TopiaEntityIdsMap data;
+
+ // on recupere les objets a repliquer par type
+ if (model.isReplicateAll()) {
+
+ // on recupere pour chaque type tous les ids des entites a repliquer
+ data = new TopiaEntityIdsMap();
+ for (TopiaEntityEnum e : model.getContracts()) {
+ List<String> ids = srcCtxt.getDAO(e.getContract()).findAllIds();
+ data.put(e.getContract(), ids);
+ }
+ } else {
+
+ // on recupere les entites specifies a repliquer
+ TopiaEntity[] entities = TopiaEntityHelper.getEntities(srcCtxt,
+ model.getTopiaIds()
+ );
+
+ // on calcule toutes les ids des entites a repliquer
+ data = TopiaEntityHelper.detectEntityIds(model.getContracts(),
+ model.getTypes(),
+ entities
+ );
+ }
+ return data;
+ }
+
+// protected void checkServiceIsInit() {
+// if (modelBuilder == null) {
+// throw new IllegalStateException("service was not init!");
+// }
+// }
+
+// @Override
+
+ public void doReplicateNode(
+ ReplicationNode node,
+ TopiaContext srcCtxt,
+ TopiaContext dstCtxt,
+ TopiaEntityIdsMap data,
+ List<ReplicationNode> treated) throws Exception {
+
+ // on trie toujours les operations a realiser selon leur phase
+ // (avant ou apres la duplication)
+ node.sortOperations();
+
+ List<ReplicationOperationDef> operationDefs = node.getOperations();
+
+ if (operationDefs.isEmpty()) {
+ log.info("skip node " + node + " - no operation detected.");
+ } else {
+
+ log.info("start for " + node + " : " + operationDefs.size() +
+ " operation(s)");
+
+ List<String> nodeEntityIds =
+ data.get(node.getContract().getContract());
+
+ if (log.isInfoEnabled()) {
+ log.info("will replicate on " + nodeEntityIds.size() +
+ " entity(ies)");
+ }
+ if (log.isDebugEnabled()) {
+ for (String id : nodeEntityIds) {
+ log.debug(id);
+ }
+ }
+
+ List<? extends TopiaEntity> nodeEntities = TopiaEntityHelper.getEntitiesList(
+ srcCtxt,
+ nodeEntityIds.toArray(new String[nodeEntityIds.size()])
+ );
+
+ for (ReplicationOperationDef operationDef : operationDefs) {
+
+ log.info("start " + operationDef);
+
+ TopiaReplicationOperation operation =
+ getModelBuilder().getOperation(operationDef.getOperationClass());
+
+ operation.run(operationDef,
+ (TopiaContextImplementor) srcCtxt,
+ (TopiaContextImplementor) dstCtxt,
+ nodeEntities,
+ data
+ );
+
+ }
+ // on rollback le context source (car on a peut-etre modifie
+ // des associations ou des dependances mais on ne veut rien
+ // retenir au niveau d'hibernate, sinon on s'expose a des erreurs
+ // lorsque l'on veut recharger des objets dans le context...)
+ srcCtxt.rollbackTransaction();
+ }
+
+ treated.add(node);
+ }
+
+
+// @Override
+
+ public void doRollbackNode(
+ ReplicationNode node,
+ TopiaContext srcCtxt,
+ TopiaContext dstCtxt,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // on trie toujours les operations a realiser selon leur phase
+ // (avant ou apres la duplication)
+ node.sortOperations();
+
+ List<ReplicationOperationDef> operationDefs = node.getOperations();
+
+ if (operationDefs.isEmpty()) {
+ log.info("skip node " + node + " - no operation detected.");
+ } else {
+
+ log.info("start for " + node + " : " + operationDefs.size() +
+ " operation(s)");
+
+ List<String> nodeEntityIds =
+ data.get(node.getContract().getContract());
+ if (log.isInfoEnabled()) {
+ log.info("will replicate on " + nodeEntityIds.size() +
+ " entity(ies)");
+ }
+ if (log.isDebugEnabled()) {
+ for (String id : nodeEntityIds) {
+ log.debug(id);
+ }
+ }
+
+ List<? extends TopiaEntity> nodeEntities = TopiaEntityHelper.getEntitiesList(
+ srcCtxt,
+ nodeEntityIds.toArray(new String[nodeEntityIds.size()])
+ );
+
+ for (ReplicationOperationDef operationDef : operationDefs) {
+
+ log.info("start " + operationDef);
+
+ TopiaReplicationOperation operation =
+ getModelBuilder().getOperation(operationDef.getOperationClass());
+
+ operation.rollback(operationDef,
+ (TopiaContextImplementor) srcCtxt,
+ (TopiaContextImplementor) dstCtxt,
+ nodeEntities,
+ data
+ );
+
+ }
+ // on rollback le context source (car on a peut-etre modifie
+ // des associations ou des dependances mais on ne veut rien
+ // retenir au niveau d'hibernate, sinon on s'expose a des erreurs
+ // lorsque l'on veut recharger des objets dans le context...)
+ srcCtxt.rollbackTransaction();
+ }
+ }
+
+}
Property changes on: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationServiceImpl.java
___________________________________________________________________
Added: svn:keywords
+ HeadURL Id Date Revision Author
Deleted: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,116 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication.model;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Pour definir un lien entre deux entites (deux noeuds de replication).
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.2.0
- */
-public class Link {
-
- /** le noeud source du lien */
- protected final ReplicationNode source;
-
- /** le noeud destination du lien */
- protected final ReplicationNode target;
-
- /**
- * liste des noeuds requis.
- * <p/>
- * TODO tchemit 2010-08-14 Expliquer à quoi ça sert vraiment...
- */
- protected final Set<ReplicationNode> requires;
-
- /** nom du lien */
- protected final String name;
-
- /** drapeau positionné à {@code true} lorsque le lien est une association. */
- protected final boolean association;
-
- public Link(ReplicationNode source,
- ReplicationNode target,
- String name,
- boolean association) {
- this.source = source;
- this.target = target;
- this.name = name;
- this.association = association;
- Set<ReplicationNode> tmpSet = new HashSet<ReplicationNode>();
- tmpSet.add(source);
- tmpSet.addAll(source.getAssociations().values());
- tmpSet.addAll(source.getDependencies().values());
- tmpSet.remove(target);
- requires = Collections.unmodifiableSet(tmpSet);
- }
-
- public String getName() {
- return name;
- }
-
- public ReplicationNode getSource() {
- return source;
- }
-
- public ReplicationNode getTarget() {
- return target;
- }
-
- public boolean isAssociation() {
- return association;
- }
-
- /**
- * Teste si on peut reattacher le lien en connaissant l'univers des
- * noeuds disponibles.
- * <p/>
- * On teste si toutes les pre-requis sont disponibles.
- * <p/>
- * Si oui, on peut reattacher.
- *
- * @param universe l'univers des noeuds disponibles
- * @param currentNode le noeud qui vient d'etre replique
- * @return <code>true</code> si on peut reattacher ce lien
- */
- public boolean canReattach(Set<ReplicationNode> universe,
- ReplicationNode currentNode) {
- boolean result = universe.containsAll(requires);
- if (result) {
- result = currentNode.equals(target) || universe.contains(target);
- }
- return result;
- }
-
- @Override
- public String toString() {
- return "<source:" + source + ", target:" + target + ", name:" + name + ", association:" + association + ">";
- }
-}
Copied: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationLink.java (from rev 2098, trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java)
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationLink.java (rev 0)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationLink.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,116 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+
+package org.nuiton.topia.replication.model;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Pour definir un lien entre deux entites (deux noeuds de replication).
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
+public class ReplicationLink {
+
+ /** le noeud source du lien */
+ protected final ReplicationNode source;
+
+ /** le noeud destination du lien */
+ protected final ReplicationNode target;
+
+ /**
+ * liste des noeuds requis.
+ * <p/>
+ * TODO tchemit 2010-08-14 Expliquer à quoi ça sert vraiment...
+ */
+ protected final Set<ReplicationNode> requires;
+
+ /** nom du lien */
+ protected final String name;
+
+ /** drapeau positionné à {@code true} lorsque le lien est une association. */
+ protected final boolean association;
+
+ public ReplicationLink(ReplicationNode source,
+ ReplicationNode target,
+ String name,
+ boolean association) {
+ this.source = source;
+ this.target = target;
+ this.name = name;
+ this.association = association;
+ Set<ReplicationNode> tmpSet = new HashSet<ReplicationNode>();
+ tmpSet.add(source);
+ tmpSet.addAll(source.getAssociations().values());
+ tmpSet.addAll(source.getDependencies().values());
+ tmpSet.remove(target);
+ requires = Collections.unmodifiableSet(tmpSet);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ReplicationNode getSource() {
+ return source;
+ }
+
+ public ReplicationNode getTarget() {
+ return target;
+ }
+
+ public boolean isAssociation() {
+ return association;
+ }
+
+ /**
+ * Teste si on peut reattacher le lien en connaissant l'univers des
+ * noeuds disponibles.
+ * <p/>
+ * On teste si toutes les pre-requis sont disponibles.
+ * <p/>
+ * Si oui, on peut reattacher.
+ *
+ * @param universe l'univers des noeuds disponibles
+ * @param currentNode le noeud qui vient d'etre replique
+ * @return <code>true</code> si on peut reattacher ce lien
+ */
+ public boolean canReattach(Set<ReplicationNode> universe,
+ ReplicationNode currentNode) {
+ boolean result = universe.containsAll(requires);
+ if (result) {
+ result = currentNode.equals(target) || universe.contains(target);
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "<source:" + source + ", target:" + target + ", name:" + name + ", association:" + association + ">";
+ }
+}
Property changes on: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationLink.java
___________________________________________________________________
Added: svn:keywords
+ HeadURL Id Date Revision Author
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -373,8 +373,8 @@
public void detectOperations() {
Set<ReplicationNode> universe = new HashSet<ReplicationNode>();
- Set<Link> links = new HashSet<Link>();
- Set<Link> linksToLoad = new HashSet<Link>();
+ Set<ReplicationLink> links = new HashSet<ReplicationLink>();
+ Set<ReplicationLink> linksToLoad = new HashSet<ReplicationLink>();
// premiere passe pour recuperer toutes les associations
@@ -384,7 +384,7 @@
String name = entry.getKey();
// dans tous les cas, on ajoute un link d'association a reattacher
ReplicationNode target = node.getAssociations().get(name);
- Link link = new Link(node, target, name, true);
+ ReplicationLink link = new ReplicationLink(node, target, name, true);
if (nodes.containsValue(target)) {
// on a trouve une association que l'on doit gerer
links.add(link);
@@ -400,7 +400,7 @@
if (!TopiaEntity.class.isAssignableFrom(associationPropertyType) ||
!nodes.containsKey(associationPropertyType)) {
- Link link = new Link(node, null, name, true);
+ ReplicationLink link = new ReplicationLink(node, null, name, true);
linksToLoad.add(link);
if (log.isDebugEnabled()) {
@@ -425,18 +425,18 @@
addPreOperation(node, node, DettachAssociation.class, name);
}
}
- Set<Link> tmpLinks = new HashSet<Link>();
+ Set<ReplicationLink> tmpLinks = new HashSet<ReplicationLink>();
// recherche des associations a charger avant replication
- for (Link link : linksToLoad) {
+ for (ReplicationLink link : linksToLoad) {
if (node.equals(link.getSource())) {
tmpLinks.add(link);
}
}
if (!tmpLinks.isEmpty()) {
// on a des associations a charger avant replication
- for (Link link : tmpLinks) {
+ for (ReplicationLink link : tmpLinks) {
addPreOperation(node, node, LoadLink.class, link);
// ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.before, LoadLink.class, node, link);
// node.addOperation(op);
@@ -452,7 +452,7 @@
universe.add(node);
// operations de reattachement
- for (Link link : links) {
+ for (ReplicationLink link : links) {
if (link.canReattach(universe, node)) {
// lien reattachable
tmpLinks.add(link);
@@ -460,7 +460,7 @@
}
if (!tmpLinks.isEmpty()) {
// on a trouve des liens a reattacher
- for (Link link : tmpLinks) {
+ for (ReplicationLink link : tmpLinks) {
addPostOperation(node, node, AttachLink.class, link);
// ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.after, AttachLink.class, node, link);
// node.addOperation(op);
@@ -522,9 +522,9 @@
}
protected void addPreOperation(ReplicationNode ownerNode,
- ReplicationNode node,
- Class<? extends TopiaReplicationOperation> operationClass,
- Object... params) {
+ ReplicationNode node,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
addOperation(ownerNode, node, ReplicationOperationPhase.before, operationClass, params);
}
@@ -536,9 +536,9 @@
}
protected void addPostOperation(ReplicationNode ownerNode,
- ReplicationNode node,
- Class<? extends TopiaReplicationOperation> operationClass,
- Object... params) {
+ ReplicationNode node,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
addOperation(ownerNode, node, ReplicationOperationPhase.after, operationClass, params);
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -33,7 +33,6 @@
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
-import org.nuiton.topia.replication.ReplicationEngine;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
@@ -71,13 +70,17 @@
*/
public class AttachAssociation implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(AttachAssociation.class);
@Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
+ public void register(ReplicationModel model,
+ ReplicationNode ownerNode,
+ ReplicationOperationPhase phase,
+ Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
+ throw new UnsupportedOperationException(
+ _("topia.replication.operation.error.uncreatable", getClass()));
}
@Override
@@ -91,7 +94,8 @@
Boolean reverse = (Boolean) operationDef.getParameters()[1];
if (log.isDebugEnabled()) {
- log.debug("currentNode : " + operationDef.getNode() + " , association name : " + name + " reverse ? " + reverse);
+ log.debug("currentNode : " + operationDef.getNode() +
+ " , association name : " + name + " reverse ? " + reverse);
}
ReplicationNode ownerNode;
@@ -137,7 +141,8 @@
if (ownerIds == null || ownerIds.isEmpty()) {
// pas de donnees a traiter
- log.info(_("topia.replication.attachAssociation.nothing.to.do", ownerOperator));
+ log.info(_("topia.replication.attachAssociation.nothing.to.do",
+ ownerOperator));
return;
}
@@ -148,13 +153,17 @@
// modifiees (dettachement d'association ou autres)
// ils nous faut les entites telles qu'elles sont en base source
- ownerEntities = ReplicationEngine.getEntitiesList(srcCtxt, ownerIds.toArray(new String[ownerIds.size()]));
+ ownerEntities = TopiaEntityHelper.getEntitiesList(
+ srcCtxt,
+ ownerIds.toArray(new String[ownerIds.size()])
+ );
boolean shouldCommit = false;
if (log.isInfoEnabled()) {
- log.info("ownerNode : " + ownerNode + " , targetNode : " + cibleNode + ", association : " + name);
+ log.info("ownerNode : " + ownerNode + " , targetNode : " +
+ cibleNode + ", association : " + name);
}
if (log.isDebugEnabled()) {
log.debug("owner ids : " + ownerIds);
@@ -174,7 +183,8 @@
continue;
}
if (log.isDebugEnabled()) {
- log.debug("will try to attach " + targetEntities.size() + " association(s) '" + name + "' to " + src);
+ log.debug("will try to attach " + targetEntities.size() +
+ " association(s) '" + name + "' to " + src);
}
// l'entite repliquee a laquelle on veut attacher l'association
@@ -182,10 +192,16 @@
TopiaEntity dst = dstCtxt.findByTopiaId(src.getTopiaId());
// les association cibles connues pour l'entite sur la base destination
- Collection<?> dstTargetEntities = (Collection<?>) ownerOperator.get(name, dst);
+ Collection<?> dstTargetEntities = (Collection<?>)
+ ownerOperator.get(name, dst);
// les ids des entities deja associees
- List<String> dstTargetAssociationsId = dstTargetEntities == null ? Collections.EMPTY_LIST : TopiaEntityHelper.getTopiaIdList((List<? extends TopiaEntity>) dstTargetEntities);
+ List<String> dstTargetAssociationsId =
+ dstTargetEntities == null ?
+ Collections.<String>emptyList() :
+ TopiaEntityHelper.getTopiaIdList(
+ (List<? extends TopiaEntity>) dstTargetEntities);
+
boolean shouldUpdate = false;
for (Object a : targetEntities) {
@@ -196,7 +212,8 @@
if (dstTargetAssociationsId.contains(assosiationSrc.getTopiaId())) {
// deja attache
if (log.isDebugEnabled()) {
- log.debug("already attached association '" + name + "' : " + assosiationSrc);
+ log.debug("already attached association '" + name +
+ "' : " + assosiationSrc);
}
continue;
@@ -204,10 +221,12 @@
// la donnees doit etre attachee
- TopiaEntity assosiationDst = dstCtxt.findByTopiaId(assosiationSrc.getTopiaId());
+ TopiaEntity assosiationDst =
+ dstCtxt.findByTopiaId(assosiationSrc.getTopiaId());
ownerOperator.addChild(name, dst, assosiationDst);
if (log.isDebugEnabled()) {
- log.debug("will attach association '" + name + "' : " + assosiationDst);
+ log.debug("will attach association '" + name + "' : " +
+ assosiationDst);
}
shouldUpdate = true;
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -33,9 +33,8 @@
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
-import org.nuiton.topia.replication.ReplicationEngine;
import org.nuiton.topia.replication.TopiaReplicationOperation;
-import org.nuiton.topia.replication.model.Link;
+import org.nuiton.topia.replication.model.ReplicationLink;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
@@ -72,13 +71,17 @@
*/
public class AttachLink implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(AttachLink.class);
@Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
+ public void register(ReplicationModel model,
+ ReplicationNode ownerNode,
+ ReplicationOperationPhase phase,
+ Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
+ throw new UnsupportedOperationException(
+ _("topia.replication.operation.error.uncreatable", getClass()));
}
@Override
@@ -88,18 +91,20 @@
List<? extends TopiaEntity> nodeEntities,
TopiaEntityIdsMap data) throws TopiaException {
- Link link = (Link) operationDef.getParameters()[0];
+ ReplicationLink link = (ReplicationLink) operationDef.getParameters()[0];
String name = link.getName();
if (log.isDebugEnabled()) {
- log.debug("currentNode : " + operationDef.getNode() + " , link to attach : " + link);
+ log.debug("currentNode : " + operationDef.getNode() +
+ " , link to attach : " + link);
}
ReplicationNode ownerNode = link.getSource();
ReplicationNode cibleNode = link.getTarget();
- EntityOperator<? super TopiaEntity> ownerOperator = ownerNode.getOperator();
+ EntityOperator<? super TopiaEntity> ownerOperator =
+ ownerNode.getOperator();
// contient la liste des ids d'association autorisees ici
List<String> associationIds = null;
@@ -128,7 +133,8 @@
if (ownerIds == null || ownerIds.isEmpty()) {
// pas de donnees a traiter
- log.info(_("topia.replication.attachAssociation.nothing.to.do", ownerOperator));
+ log.info(_("topia.replication.attachAssociation.nothing.to.do",
+ ownerOperator));
return;
}
@@ -136,13 +142,17 @@
// modifiees (dettachement d'association ou autres)
// ils nous faut les entites telles qu'elles sont en base source
- ownerEntities = ReplicationEngine.getEntitiesList(srcCtxt, ownerIds.toArray(new String[ownerIds.size()]));
+ ownerEntities = TopiaEntityHelper.getEntitiesList(
+ srcCtxt,
+ ownerIds.toArray(new String[ownerIds.size()])
+ );
boolean shouldCommit = false;
if (log.isInfoEnabled()) {
- log.info("ownerNode : " + ownerNode + " , targetNode : " + cibleNode + ", association : " + name);
+ log.info("ownerNode : " + ownerNode + " , targetNode : " +
+ cibleNode + ", association : " + name);
}
if (log.isDebugEnabled()) {
log.debug("owner ids : " + ownerIds);
@@ -152,7 +162,8 @@
for (TopiaEntity src : ownerEntities) {
// les association cibles connues pour l'entite sur la base source
- Collection<?> targetEntities = (Collection<?>) ownerOperator.get(name, src);
+ Collection<?> targetEntities = (Collection<?>)
+ ownerOperator.get(name, src);
if (targetEntities == null || targetEntities.isEmpty()) {
if (log.isDebugEnabled()) {
@@ -162,7 +173,8 @@
continue;
}
if (log.isDebugEnabled()) {
- log.debug("will try to attach " + targetEntities.size() + " association(s) '" + name + "' to " + src);
+ log.debug("will try to attach " + targetEntities.size() +
+ " association(s) '" + name + "' to " + src);
}
// l'entite repliquee a laquelle on veut attacher l'association
@@ -170,10 +182,15 @@
TopiaEntity dst = dstCtxt.findByTopiaId(src.getTopiaId());
// les association cibles connues pour l'entite sur la base destination
- Collection<?> dstTargetEntities = (Collection<?>) ownerOperator.get(name, dst);
+ Collection<?> dstTargetEntities = (Collection<?>)
+ ownerOperator.get(name, dst);
// les ids des entities deja associees
- List<String> dstTargetAssociationsId = dstTargetEntities == null ? Collections.EMPTY_LIST : TopiaEntityHelper.getTopiaIdList((List<? extends TopiaEntity>) dstTargetEntities);
+ List<String> dstTargetAssociationsId =
+ dstTargetEntities == null ?
+ Collections.<String>emptyList() :
+ TopiaEntityHelper.getTopiaIdList(
+ (List<? extends TopiaEntity>) dstTargetEntities);
boolean shouldUpdate = false;
for (Object a : targetEntities) {
@@ -181,10 +198,12 @@
// on verifie que l'association doit etre rattachee
if (associationIds.contains(assosiationSrc.getTopiaId())) {
- if (dstTargetAssociationsId.contains(assosiationSrc.getTopiaId())) {
+ if (dstTargetAssociationsId.contains(
+ assosiationSrc.getTopiaId())) {
// deja attache
if (log.isDebugEnabled()) {
- log.debug("already attached association '" + name + "' : " + assosiationSrc);
+ log.debug("already attached association '" +
+ name + "' : " + assosiationSrc);
}
continue;
@@ -192,10 +211,12 @@
// la donnees doit etre attachee
- TopiaEntity assosiationDst = dstCtxt.findByTopiaId(assosiationSrc.getTopiaId());
+ TopiaEntity assosiationDst =
+ dstCtxt.findByTopiaId(assosiationSrc.getTopiaId());
ownerOperator.addChild(name, dst, assosiationDst);
if (log.isDebugEnabled()) {
- log.debug("will attach association '" + name + "' : " + assosiationDst);
+ log.debug("will attach association '" + name +
+ "' : " + assosiationDst);
}
shouldUpdate = true;
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -54,13 +54,17 @@
*/
public class DettachAssociation implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(DettachAssociation.class);
@Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
+ public void register(ReplicationModel model,
+ ReplicationNode ownerNode,
+ ReplicationOperationPhase phase,
+ Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
+ throw new UnsupportedOperationException(
+ _("topia.replication.operation.error.uncreatable", getClass()));
}
@Override
@@ -72,7 +76,8 @@
String name = (String) operationDef.getParameters()[0];
- EntityOperator<? super TopiaEntity> operator = operationDef.getNode().getOperator();
+ EntityOperator<? super TopiaEntity> operator =
+ operationDef.getNode().getOperator();
// dettach les associations
for (TopiaEntity e : entities) {
@@ -80,7 +85,8 @@
if (size > 0) {
if (log.isDebugEnabled()) {
- log.debug("will dettach " + size + " association(s) '" + name + "' from " + e);
+ log.debug("will dettach " + size + " association(s) '" +
+ name + "' from " + e);
}
operator.setNull(name, e);
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -52,8 +52,12 @@
public class Duplicate implements TopiaReplicationOperation {
@Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
+ public void register(ReplicationModel model,
+ ReplicationNode ownerNode,
+ ReplicationOperationPhase phase,
+ Object... parameters) {
+ throw new UnsupportedOperationException(
+ _("topia.replication.operation.error.uncreatable", getClass()));
}
@Override
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -33,7 +33,7 @@
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
-import org.nuiton.topia.replication.model.Link;
+import org.nuiton.topia.replication.model.ReplicationLink;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
@@ -55,13 +55,17 @@
*/
public class LoadLink implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(LoadLink.class);
@Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
+ public void register(ReplicationModel model,
+ ReplicationNode ownerNode,
+ ReplicationOperationPhase phase,
+ Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
+ throw new UnsupportedOperationException(
+ _("topia.replication.operation.error.uncreatable", getClass()));
}
@Override
@@ -71,28 +75,33 @@
List<? extends TopiaEntity> nodeEntities,
TopiaEntityIdsMap data) throws TopiaException {
- Link link = (Link) operationDef.getParameters()[0];
+ ReplicationLink link = (ReplicationLink) operationDef.getParameters()[0];
String name = link.getName();
ReplicationNode ownerNode = link.getSource();
if (!ownerNode.equals(operationDef.getNode())) {
- throw new IllegalStateException(_("topia.replication.operation.loadLink.illegalSource", operationDef.getNode(), ownerNode));
+ throw new IllegalStateException(
+ _("topia.replication.operation.loadLink.illegalSource",
+ operationDef.getNode(), ownerNode));
}
if (log.isDebugEnabled()) {
- log.debug("currentNode : " + operationDef.getNode() + " , link to load : " + link);
+ log.debug("currentNode : " + operationDef.getNode() +
+ " , link to load : " + link);
}
- EntityOperator<? super TopiaEntity> ownerOperator = ownerNode.getOperator();
+ EntityOperator<? super TopiaEntity> ownerOperator =
+ ownerNode.getOperator();
for (TopiaEntity src : nodeEntities) {
// on se contente de charger l'association
int size = ownerOperator.sizeChild(name, src);
if (log.isDebugEnabled()) {
- log.debug("load association '" + name + "' on " + src + " : " + size);
+ log.debug("load association '" + name + "' on " + src +
+ " : " + size);
}
}
}
Modified: trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
===================================================================
--- trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,6 +1,5 @@
#
-# la liste des operations disponibles pour le moteur de replication
-# voir la classe org.nuiton.topia.replication.ReplicationEngine
+# la liste des operations disponibles pour le moteur de replication.
#
org.nuiton.topia.replication.operation.AttachLink
org.nuiton.topia.replication.operation.LoadLink
Deleted: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,646 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication;
-
-import org.apache.commons.logging.Log;
-import org.junit.Assert;
-import org.nuiton.i18n.I18n;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaDAO;
-import org.nuiton.topia.persistence.TopiaEntity;
-import org.nuiton.topia.persistence.TopiaEntityEnum;
-import org.nuiton.topia.persistence.util.EntityOperator;
-import org.nuiton.topia.persistence.util.EntityOperatorStore;
-import org.nuiton.topia.persistence.util.TopiaEntityHelper;
-import org.nuiton.topia.replication.model.ReplicationModel;
-import org.nuiton.topia.replication.model.ReplicationNode;
-import org.nuiton.topia.replication.model.ReplicationOperationDef;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * ReplicationEngineTest.
- * <p/>
- * Created: 07 jun. 09 17:14:22
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @version $Id$
- * @since 2.2.0
- */
-public abstract class AbstractReplicationEngineTest extends Assert {
-
- static protected TopiaContext context;
-
- static protected TopiaContext ctxt;
-
- protected TopiaContextImplementor dstCtxt;
-
- protected TopiaReplicationImplementor service;
-
- protected ReplicationModel model;
-
- static protected boolean init;
-
- static private Long testsTimeStamp;
-
- static private File testsBasedir;
-
- static private final String TEST_BASEDIR = "target%1$ssurefire-tests%1$s%2$td_%2$tm_%2$tY%1$s%2$tH_%2$tM_%2$tS";
-
- public static void after() throws Exception {
- if (context != null && !context.isClosed()) {
- try {
- context.closeContext();
- } catch (TopiaException e) {
- // cela peut arriver si on demande la fermeture dans un thread
- // ailleurs...
- }
- }
- init = false;
- }
-
- public void setUp() throws Exception {
-
- if (!init) {
-
- I18n.init(Locale.FRANCE);
-
- try {
- context = createDb("source");
- } catch (Exception e) {
- getLog().error("could not create db source.", e);
- throw e;
- }
- init = true;
- }
-
- ctxt = context.beginTransaction();
-
- service = (TopiaReplicationImplementor) context.getService(TopiaReplicationService.class);
- }
-
- public void tearDown() throws Exception {
- if (ctxt != null) {
- ctxt.rollbackTransaction();
- ctxt.closeContext();
- ctxt = null;
- }
- service = null;
- }
-
- protected abstract TopiaContext createDb2(String name) throws Exception;
-
- protected abstract TopiaContext createDb(String name) throws Exception;
-
- protected TopiaContext createReplicateDb(Object contract) throws Exception {
- TopiaContext rootCtxt = createDb2(contract.toString() + dbCounter++);
- return rootCtxt;
- }
-
- protected abstract TopiaEntityEnum[] getContracts();
-
- protected abstract Log getLog();
-
- protected <E extends TopiaEntity> E update(E e) throws TopiaException {
- return (E) ((TopiaContextImplementor) ctxt).findByTopiaId(e.getTopiaId());
- }
-
- /**
- * Test of detectTypes method, of class ReplicationServiceImplementor.
- *
- * @throws Exception if any error
- */
- public void testDetectTypes() throws Exception {
- }
-
- /**
- * Test of getOperation method, of class ReplicationServiceImplementor.
- *
- * @throws Exception if any error
- */
- public void testGetOperation() throws Exception {
- }
-
- /**
- * Test of detectAssociations method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectAssociations() throws Exception {
- }
-
- /**
- * Test of detectDirectDependencies method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectDirectDependencies() throws Exception {
- }
-
- /**
- * Test of detectShell method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectShell() throws Exception {
- }
-
- /**
- * Test of detectDependencies method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectDependencies() throws Exception {
- }
-
- /**
- * Test of detectObjectsToDettach method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectObjectsToDettach() throws Exception {
- }
-
- /**
- * Test of detectOperations method, of class ReplicationModel.
- *
- * @throws Exception if any error
- */
- public void testDetectOperations() throws Exception {
- }
-
- /**
- * Test of doReplicate method, of class ReplicationService.
- *
- * @throws Exception if any error
- */
- public void testDoReplicate() throws Exception {
- }
-
- protected void detectTypes(TopiaEntity entity, Object... expectedCouple) throws TopiaException {
-
- Set<?> detectTypes;
-
- detectTypes = service.detectTypes(getContracts(), entity.getTopiaId());
- assertEquals("expected types : " +
- Arrays.toString(expectedCouple) +
- " but was " + detectTypes,
- expectedCouple.length, detectTypes.size());
- for (Object o : expectedCouple) {
- assertTrue(detectTypes.contains(o));
- }
- }
-
- protected void getOperation(Class<? extends TopiaReplicationOperation> operationClass, boolean shouldExist) throws TopiaException {
- TopiaReplicationOperation operation = service.getOperation(operationClass);
- assertEquals(shouldExist, operation != null);
- }
-
- protected void detectAssociations(TopiaEntity entity,
- Object... expectedCouple)
- throws TopiaException {
-
- createModel(entity);
- model.detectAssociations();
-
- assertEquals(0, expectedCouple.length % 2);
-
- for (int i = 0, j = expectedCouple.length / 2; i < j; i++) {
- TopiaEntityEnum src = (TopiaEntityEnum) expectedCouple[2 * i];
- String name = (String) expectedCouple[2 * i + 1];
- ReplicationNode nodeSrc = model.getNode(src);
- assertNotNull("association " + name + " not found", nodeSrc);
- assertTrue(nodeSrc.hasAssociation());
- assertTrue(nodeSrc.getAssociations().containsKey(name));
- }
- }
-
- protected void detectDirectDependencies(TopiaEntity entity,
- Object... expectedCouple)
- throws TopiaException {
-
- createModel(entity);
- model.detectDirectDependencies();
-
- assertEquals(0, expectedCouple.length % 2);
-
- for (int i = 0, j = expectedCouple.length / 2; i < j; i++) {
- TopiaEntityEnum src = (TopiaEntityEnum) expectedCouple[2 * i];
- String name = (String) expectedCouple[2 * i + 1];
- ReplicationNode nodeSrc = model.getNode(src);
- assertTrue(nodeSrc + " should have dependency but was not!", nodeSrc.hasDependency());
- assertTrue(nodeSrc + " should contain dependency " + name + "but was not! (" + nodeSrc.getDependencies() + ")", nodeSrc.getDependencies().containsKey(name));
- }
- }
-
- protected void detectShell(TopiaEntity entity,
- TopiaEntityEnum... expected) throws
- TopiaException {
- Set<ReplicationNode> shell;
-
- createModel(entity);
- model.detectAssociations();
- model.detectDirectDependencies();
- model.detectShell();
-
- TopiaEntityEnum c = TopiaEntityHelper.getEntityEnum(
- entity.getClass(), getContracts());
- assertNotNull(c);
- shell = model.getNode(c.getContract()).getShell();
- assertEquals(
- "expected shell : " + Arrays.toString(expected) + ", but was " +
- shell, expected.length, shell.size());
-
- for (int i = 0, j = expected.length; i < j; i++) {
- TopiaEntityEnum type = expected[i];
- ReplicationNode node = model.getNode(type.getContract());
- assertTrue(shell.contains(node));
- assertEquals(type, node.getContract());
- }
- }
-
- protected void detectDependencies(
- TopiaEntity entity,
- TopiaEntityEnum[]... expected) throws TopiaException {
-
- createModel(entity);
- model.detectAssociations();
- model.detectDirectDependencies();
- model.detectShell();
- model.detectDependencies();
- List<ReplicationNode> dependencies = model.getOrder();
-
- int i = 0;
- for (ReplicationNode level : dependencies) {
- getLog().info("level " + level + " = " + level);
- }
-
-// assertEquals("expected " + expected.length + " levels but had " + dependencies.size(), expected.length, dependencies.size());
-//
-// Iterator<List<ReplicationNode>> order = dependencies.iterator();
-// if (entity != null) {
-// getLog().info("for " + entity.getTopiaId());
-// }
-// int index = 0;
-// for (TopiaEntityEnum[] expectedLevel : expected) {
-//
-// List<ReplicationNode> next = order.next();
-// getLog().info("level " + (index++) + " : " + next);
-// for (TopiaEntityEnum ee : expectedLevel) {
-// ReplicationNode expectedNode = model.getNode(ee);
-//
-// assertTrue("should have contains node " + expectedNode, next.contains(expectedNode));
-// }
-//
-// }
- }
-
- protected void detectObjectsToDettach(TopiaEntity entity, Object... expected) throws TopiaException {
-
- assertEquals(0, expected.length % 2);
-
- createModel(entity);
- model.detectAssociations();
- model.detectDirectDependencies();
- model.detectShell();
- model.detectDependencies();
- model.detectObjectsToDettach();
- Set<ReplicationNode> nodes = new HashSet<ReplicationNode>();
-
- for (int i = 0, j = expected.length / 2; i < j; i++) {
- TopiaEntityEnum e = (TopiaEntityEnum) expected[2 * i];
- ReplicationNode node = model.getNode(e);
- String[] ids = (String[]) expected[2 * i + 1];
- assertEquals(ids.length > 0, node.hasAssociationsToDettach());
- for (String id : ids) {
- assertTrue(node.getAssociationsToDettach().contains(id));
- }
- nodes.add(node);
- }
-
- for (ReplicationNode node : model.getNodes()) {
- if (!nodes.contains(node)) {
- // on verifie bien qu'il n' y a pas d'associations dettachee
- assertFalse(node.hasAssociationsToDettach());
- }
- }
-
- }
-
- protected void detectOperations(TopiaEntity entity, Object... expected) throws TopiaException {
-
- assertEquals(0, expected.length % 2);
-
- if (entity == null) {
- prepareModel();
- } else {
- prepareModel(entity.getTopiaId());
- }
-// createModel(entity);
-// model.detectAssociations();
-// model.detectDirectDependencies();
-// model.detectShell();
-// model.detectDependencies();
-// model.detectObjectsToDettach();
-// model.detectOperations();
-
- if (getLog().isInfoEnabled()) {
- getLog().info("==========================================================================");
- if (entity == null) {
-
- getLog().info("resume of operations for all ");
- } else {
- getLog().info("resume of operations for entity " + entity.getTopiaId());
- }
-
- for (ReplicationNode node : model.getOrder()) {
- List<ReplicationOperationDef> operations = node.getOperations();
- for (ReplicationOperationDef op : operations) {
- getLog().info("[" + node + "] : operation " + op);
- }
- }
- getLog().info("==========================================================================");
- }
- }
-
- private static int dbCounter;
-
- protected void doReplicate(TopiaEntityEnum contract, TopiaEntity... entity) throws Exception {
-
- TopiaContext rootCtxt = createReplicateDb("doReplicate_" + contract);
-
- List<String> ids = TopiaEntityHelper.getTopiaIdList(Arrays.asList(entity));
- getLog().info("entity " + ids);
-
- prepareModel(ids.toArray(new String[ids.size()]));
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
-
- service.doReplicate(model, dstCtxt);
-
- //dstCtxt.closeContext();
-
- if (entity.length == 0) {
-
- return;
- }
- dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
-
- for (TopiaEntity e : entity) {
- TopiaEntity actual = dstCtxt.findByTopiaId(e.getTopiaId());
- assertNotNull(actual);
- assertEquals(e, actual);
- }
-
- dstCtxt.closeContext();
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
- }
-
- protected void doReplicateAll() throws Exception {
-
- TopiaContext rootCtxt = createReplicateDb("doReplicateAll");
-
- prepareModelAll();
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
-
- service.doReplicate(model, dstCtxt);
-
- TopiaContextImplementor ctxt2 = (TopiaContextImplementor) ctxt;
- dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
-
- assertDbEquals(model.getContracts(), (TopiaContextImplementor) ctxt, ctxt2);
-
- dstCtxt.closeContext();
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
- }
-
- protected void doReplicateWithComputedOrder(TopiaEntity... entity) throws Exception {
-
- TopiaContext rootCtxt = createReplicateDb("doReplicateWithComputedOrder");
-
- List<String> ids = TopiaEntityHelper.getTopiaIdList(Arrays.asList(entity));
-
- prepareModelWithComputedOrder(ids.toArray(new String[ids.size()]));
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
-
- service.doReplicate(model, dstCtxt);
-
- getLog().info("replication is done for " + Arrays.toString(entity) + ", will verify data...");
-
- TopiaContextImplementor ctxt2 = (TopiaContextImplementor) ctxt;
- dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
-
- assertDbEquals(model.getContracts(), (TopiaContextImplementor) ctxt, ctxt2);
-
- dstCtxt.closeContext();
-
- dstCtxt = (TopiaContextImplementor) rootCtxt;
- }
-
- protected void assertDbEquals(TopiaEntityEnum[] contracts, TopiaContextImplementor ctxt, TopiaContextImplementor ctxt2) throws TopiaException {
- Set<String> ids = new HashSet<String>();
-
- if (getLog().isInfoEnabled()) {
- getLog().info("will verify db for contracts " + Arrays.toString(contracts));
- }
- for (TopiaEntityEnum c : contracts) {
- if (getLog().isDebugEnabled()) {
- getLog().debug("verify for contract " + c);
- }
- TopiaDAO<? extends TopiaEntity> daoSrc = ctxt.getDAO(c.getContract());
- TopiaDAO<? extends TopiaEntity> daoDst = ctxt2.getDAO(c.getContract());
- long nbSrc = daoSrc.count();
- long nbDst = daoDst.count();
- assertEquals("le nombres d'entites de type " + c + " devrait etre " + nbSrc + " mais est " + nbDst, nbSrc, nbDst);
- List<String> idsSrc = daoSrc.findAllIds();
- List<String> idsDst = daoDst.findAllIds();
- Collections.sort(idsSrc);
- Collections.sort(idsDst);
- assertEquals(idsSrc, idsDst);
- for (String id : idsSrc) {
- if (getLog().isDebugEnabled()) {
- getLog().debug("verify for entity " + id);
- }
- TopiaEntity eSrc = daoSrc.findByTopiaId(id);
- TopiaEntity eDst = daoDst.findByTopiaId(id);
- assertEquals(eSrc, eDst);
- assertEntityEquals(eSrc, eDst, ids);
- }
- }
- }
-
- protected void assertEntityEquals(TopiaEntity expected, TopiaEntity actual, Set<String> treated) {
- if (treated == null) {
- treated = new HashSet<String>();
- }
- if (treated.contains(actual.getTopiaId())) {
- return;
- }
- if (getLog().isDebugEnabled()) {
- getLog().debug(expected);
- }
- assertEquals(actual.getTopiaId(), expected.getTopiaId());
- treated.add(actual.getTopiaId());
- if (getLog().isDebugEnabled()) {
- getLog().debug("expected : " + expected + " / actual " + actual);
- }
- TopiaEntityEnum contract = TopiaEntityHelper.getEntityEnum(expected.getClass(), getContracts());
- if (contract == null) {
- // this type of entity in not dealed here...
- getLog().debug("untested property type " + expected.getClass());
- return;
- }
- Assert.assertNotNull(
- "contract not found for " + expected.getClass() + " in " +
- Arrays.toString(getContracts()), contract);
- EntityOperator<TopiaEntity> operator = EntityOperatorStore.getOperator(contract);
- List<String> associationProperties = operator.getAssociationProperties();
- for (String name : associationProperties) {
- if (getLog().isDebugEnabled()) {
- getLog().debug("association " + name);
- }
- if (operator.isChildEmpty(name, expected)) {
- assertTrue("l'association " + name + " devrait etre vide mais possede " + operator.sizeChild(name, actual) + " entrees", operator.isChildEmpty(name, actual));
- } else {
- assertFalse("l'association " + name + " devrait posseder " + operator.isChildEmpty(name, expected) + " mais est vide", operator.isChildEmpty(name, actual));
-
- }
- assertEquals(operator.isChildEmpty(name, actual), operator.isChildEmpty(name, expected));
-
- Class<?> type = operator.getAssociationPropertyType(name);
- Collection<?> src = (Collection<?>) operator.get(name, expected);
- Collection<?> dst = (Collection<?>) operator.get(name, actual);
-// assertEquals(src, dst);
- Iterator<?> itrSrc = src.iterator();
- Iterator<?> itrDst = dst.iterator();
- while (itrSrc.hasNext()) {
- if (TopiaEntity.class.isAssignableFrom(type)) {
- assertEntityEquals((TopiaEntity) itrSrc.next(), (TopiaEntity) itrDst.next(), treated);
- } else {
- assertEquals(itrSrc.next(), itrDst.next());
- }
- }
- }
-
- for (String name : operator.getProperties()) {
- if (getLog().isDebugEnabled()) {
- getLog().debug("dependency " + name);
- }
- if (associationProperties.contains(name)) {
- // deja traite au dessus
- continue;
- }
- Class<?> type = operator.getPropertyType(name);
- Object src = operator.get(name, expected);
- Object dst = operator.get(name, actual);
- assertFalse(src == null && dst != null);
- assertFalse(src != null && dst == null);
- if (src == null) {
- continue;
- }
- if (TopiaEntity.class.isAssignableFrom(type)) {
- assertEntityEquals((TopiaEntity) src, (TopiaEntity) dst, treated);
- } else {
- assertEquals(src, dst);
- }
- }
- }
-
- protected void createUnsupportedBeforeOperation(TopiaEntityEnum contract, TopiaEntity entity, Class<? extends TopiaReplicationOperation> operationClass, Object... parameters) throws Exception {
-
- getLog().info("entity " + entity.getTopiaId());
- prepareModel(entity.getTopiaId());
-
- service.addBeforeOperation(model, contract, operationClass, parameters);
- // on ne doit pas avoir le droit de creer cette operation
- fail();
- }
-
- protected void createUnsupportedAfterOperation(TopiaEntityEnum contract, TopiaEntity entity, Class<? extends TopiaReplicationOperation> operationClass, Object... parameters) throws Exception {
-
- getLog().info("entity " + entity.getTopiaId());
- prepareModel(entity.getTopiaId());
-// model = service.createModel(getContracts());
-// model.detectDirectDependencies();
- service.addAfterOperation(model, contract, operationClass, parameters);
- // on ne doit pas avoir le droit de creer cette operation
- fail();
- }
-
- protected Long getTestsTimeStamp() {
- if (testsTimeStamp == null) {
- testsTimeStamp = System.currentTimeMillis();
- getLog().info("tests timestamp : " + testsTimeStamp);
- }
- return testsTimeStamp;
- }
-
- protected File getTestDir(Class<?> testClass) {
- if (testsBasedir == null) {
- String tmp = System.getProperty("basedir");
- if (tmp == null) {
- tmp = new File("").getAbsolutePath();
- }
- String name = String.format(TEST_BASEDIR, File.separator, new Date(getTestsTimeStamp()));
- testsBasedir = new File(new File(tmp), name);
- getLog().info("tests basedir : " + testsBasedir);
- }
- return new File(testsBasedir, testClass.getSimpleName());
- }
-
- protected void createModel(TopiaEntity entity) throws TopiaException {
- model = service.createModel(getContracts(), entity.getTopiaId());
- }
-
- protected void prepareModel(String... ids) throws TopiaException {
- model = service.prepare(getContracts(), ids);
- }
-
- protected void prepareModelAll() throws TopiaException {
- model = service.prepareForAll(getContracts());
- }
-
- protected void prepareModelWithComputedOrder(String... ids) throws TopiaException {
- model = service.prepareWithComputedOrder(getContracts(), ids);
- }
-}
-
-
Copied: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractTopiaReplicationServiceTest.java (from rev 2098, trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java)
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractTopiaReplicationServiceTest.java (rev 0)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractTopiaReplicationServiceTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,654 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.junit.Assert;
+import org.nuiton.i18n.I18n;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.framework.TopiaContextImplementor;
+import org.nuiton.topia.persistence.TopiaDAO;
+import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.EntityOperator;
+import org.nuiton.topia.persistence.util.EntityOperatorStore;
+import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.model.ReplicationNode;
+import org.nuiton.topia.replication.model.ReplicationOperationDef;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+/**
+ * TopiaReplicationServiceImplTest.
+ * <p/>
+ * Created: 07 jun. 09 17:14:22
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @version $Id$
+ * @since 2.2.0
+ */
+public abstract class AbstractTopiaReplicationServiceTest extends Assert {
+
+ static protected TopiaContext context;
+
+ static protected TopiaContext ctxt;
+
+ protected TopiaContextImplementor dstCtxt;
+
+ protected TopiaReplicationService service;
+
+ protected ReplicationModel model;
+
+ static protected boolean init;
+
+ static private Long testsTimeStamp;
+
+ static private File testsBasedir;
+
+ static private final String TEST_BASEDIR = "target%1$ssurefire-tests%1$s%2$td_%2$tm_%2$tY%1$s%2$tH_%2$tM_%2$tS";
+
+ public static void after() throws Exception {
+ if (context != null && !context.isClosed()) {
+ try {
+ context.closeContext();
+ } catch (TopiaException e) {
+ // cela peut arriver si on demande la fermeture dans un thread
+ // ailleurs...
+ }
+ }
+ init = false;
+ }
+
+ public void setUp() throws Exception {
+
+ if (!init) {
+
+ I18n.init(Locale.FRANCE);
+
+ try {
+ context = createDb("source");
+ } catch (Exception e) {
+ getLog().error("could not create db source.", e);
+ throw e;
+ }
+ init = true;
+ }
+
+ ctxt = context.beginTransaction();
+
+ service = context.getService(TopiaReplicationService.class);
+ }
+
+ public void tearDown() throws Exception {
+ if (ctxt != null) {
+ ctxt.rollbackTransaction();
+ ctxt.closeContext();
+ ctxt = null;
+ }
+ service = null;
+ }
+
+ protected abstract TopiaContext createDb2(String name) throws Exception;
+
+ protected abstract TopiaContext createDb(String name) throws Exception;
+
+ protected TopiaContext createReplicateDb(Object contract) throws Exception {
+ TopiaContext rootCtxt = createDb2(contract.toString() + dbCounter++);
+ return rootCtxt;
+ }
+
+ protected abstract TopiaEntityEnum[] getContracts();
+
+ protected abstract Log getLog();
+
+ protected <E extends TopiaEntity> E update(E e) throws TopiaException {
+ return (E) ((TopiaContextImplementor) ctxt).findByTopiaId(e.getTopiaId());
+ }
+
+ /**
+ * Test of detectTypes method, of class ReplicationServiceImplementor.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectTypes() throws Exception {
+ }
+
+ /**
+ * Test of getOperation method, of class ReplicationServiceImplementor.
+ *
+ * @throws Exception if any error
+ */
+ public void testGetOperation() throws Exception {
+ }
+
+ /**
+ * Test of detectAssociations method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectAssociations() throws Exception {
+ }
+
+ /**
+ * Test of detectDirectDependencies method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectDirectDependencies() throws Exception {
+ }
+
+ /**
+ * Test of detectShell method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectShell() throws Exception {
+ }
+
+ /**
+ * Test of detectDependencies method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectDependencies() throws Exception {
+ }
+
+ /**
+ * Test of detectObjectsToDettach method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectObjectsToDettach() throws Exception {
+ }
+
+ /**
+ * Test of detectOperations method, of class ReplicationModel.
+ *
+ * @throws Exception if any error
+ */
+ public void testDetectOperations() throws Exception {
+ }
+
+ /**
+ * Test of doReplicate method, of class ReplicationService.
+ *
+ * @throws Exception if any error
+ */
+ public void testDoReplicate() throws Exception {
+ }
+
+ protected void detectTypes(TopiaEntity entity, Object... expectedCouple) throws TopiaException {
+
+ Set<?> detectTypes;
+
+ detectTypes = service.getModelBuilder().detectTypes(context, getContracts(), entity.getTopiaId());
+ assertEquals("expected types : " +
+ Arrays.toString(expectedCouple) +
+ " but was " + detectTypes,
+ expectedCouple.length, detectTypes.size());
+ for (Object o : expectedCouple) {
+ assertTrue(detectTypes.contains(o));
+ }
+ }
+
+ protected void getOperation(Class<? extends TopiaReplicationOperation> operationClass, boolean shouldExist) throws TopiaException {
+ TopiaReplicationOperation operation = service.getModelBuilder().getOperation(operationClass);
+ assertEquals(shouldExist, operation != null);
+ }
+
+ protected void detectAssociations(TopiaEntity entity,
+ Object... expectedCouple)
+ throws TopiaException {
+
+ createModel(entity);
+ model.detectAssociations();
+
+ assertEquals(0, expectedCouple.length % 2);
+
+ for (int i = 0, j = expectedCouple.length / 2; i < j; i++) {
+ TopiaEntityEnum src = (TopiaEntityEnum) expectedCouple[2 * i];
+ String name = (String) expectedCouple[2 * i + 1];
+ ReplicationNode nodeSrc = model.getNode(src);
+ assertNotNull("association " + name + " not found", nodeSrc);
+ assertTrue(nodeSrc.hasAssociation());
+ assertTrue(nodeSrc.getAssociations().containsKey(name));
+ }
+ }
+
+ protected void detectDirectDependencies(TopiaEntity entity,
+ Object... expectedCouple)
+ throws TopiaException {
+
+ createModel(entity);
+ model.detectDirectDependencies();
+
+ assertEquals(0, expectedCouple.length % 2);
+
+ for (int i = 0, j = expectedCouple.length / 2; i < j; i++) {
+ TopiaEntityEnum src = (TopiaEntityEnum) expectedCouple[2 * i];
+ String name = (String) expectedCouple[2 * i + 1];
+ ReplicationNode nodeSrc = model.getNode(src);
+ assertTrue(nodeSrc + " should have dependency but was not!", nodeSrc.hasDependency());
+ assertTrue(nodeSrc + " should contain dependency " + name + "but was not! (" + nodeSrc.getDependencies() + ")", nodeSrc.getDependencies().containsKey(name));
+ }
+ }
+
+ protected void detectShell(TopiaEntity entity,
+ TopiaEntityEnum... expected) throws
+ TopiaException {
+ Set<ReplicationNode> shell;
+
+ createModel(entity);
+ model.detectAssociations();
+ model.detectDirectDependencies();
+ model.detectShell();
+
+ TopiaEntityEnum c = TopiaEntityHelper.getEntityEnum(
+ entity.getClass(), getContracts());
+ assertNotNull(c);
+ shell = model.getNode(c.getContract()).getShell();
+ assertEquals(
+ "expected shell : " + Arrays.toString(expected) + ", but was " +
+ shell, expected.length, shell.size());
+
+ for (int i = 0, j = expected.length; i < j; i++) {
+ TopiaEntityEnum type = expected[i];
+ ReplicationNode node = model.getNode(type.getContract());
+ assertTrue(shell.contains(node));
+ assertEquals(type, node.getContract());
+ }
+ }
+
+ protected void detectDependencies(
+ TopiaEntity entity,
+ TopiaEntityEnum[]... expected) throws TopiaException {
+
+ createModel(entity);
+ model.detectAssociations();
+ model.detectDirectDependencies();
+ model.detectShell();
+ model.detectDependencies();
+ List<ReplicationNode> dependencies = model.getOrder();
+
+ int i = 0;
+ for (ReplicationNode level : dependencies) {
+ getLog().info("level " + level + " = " + level);
+ }
+
+// assertEquals("expected " + expected.length + " levels but had " + dependencies.size(), expected.length, dependencies.size());
+//
+// Iterator<List<ReplicationNode>> order = dependencies.iterator();
+// if (entity != null) {
+// getLog().info("for " + entity.getTopiaId());
+// }
+// int index = 0;
+// for (TopiaEntityEnum[] expectedLevel : expected) {
+//
+// List<ReplicationNode> next = order.next();
+// getLog().info("level " + (index++) + " : " + next);
+// for (TopiaEntityEnum ee : expectedLevel) {
+// ReplicationNode expectedNode = model.getNode(ee);
+//
+// assertTrue("should have contains node " + expectedNode, next.contains(expectedNode));
+// }
+//
+// }
+ }
+
+ protected void detectObjectsToDettach(TopiaEntity entity, Object... expected) throws TopiaException {
+
+ assertEquals(0, expected.length % 2);
+
+ createModel(entity);
+ model.detectAssociations();
+ model.detectDirectDependencies();
+ model.detectShell();
+ model.detectDependencies();
+ model.detectObjectsToDettach();
+ Set<ReplicationNode> nodes = new HashSet<ReplicationNode>();
+
+ for (int i = 0, j = expected.length / 2; i < j; i++) {
+ TopiaEntityEnum e = (TopiaEntityEnum) expected[2 * i];
+ ReplicationNode node = model.getNode(e);
+ String[] ids = (String[]) expected[2 * i + 1];
+ assertEquals(ids.length > 0, node.hasAssociationsToDettach());
+ for (String id : ids) {
+ assertTrue(node.getAssociationsToDettach().contains(id));
+ }
+ nodes.add(node);
+ }
+
+ for (ReplicationNode node : model.getNodes()) {
+ if (!nodes.contains(node)) {
+ // on verifie bien qu'il n' y a pas d'associations dettachee
+ assertFalse(node.hasAssociationsToDettach());
+ }
+ }
+
+ }
+
+ protected void detectOperations(TopiaEntity entity, Object... expected) throws TopiaException {
+
+ assertEquals(0, expected.length % 2);
+
+ if (entity == null) {
+ prepareModel();
+ } else {
+ prepareModel(entity.getTopiaId());
+ }
+// createModel(entity);
+// model.detectAssociations();
+// model.detectDirectDependencies();
+// model.detectShell();
+// model.detectDependencies();
+// model.detectObjectsToDettach();
+// model.detectOperations();
+
+ if (getLog().isInfoEnabled()) {
+ getLog().info("==========================================================================");
+ if (entity == null) {
+
+ getLog().info("resume of operations for all ");
+ } else {
+ getLog().info("resume of operations for entity " + entity.getTopiaId());
+ }
+
+ for (ReplicationNode node : model.getOrder()) {
+ List<ReplicationOperationDef> operations = node.getOperations();
+ for (ReplicationOperationDef op : operations) {
+ getLog().info("[" + node + "] : operation " + op);
+ }
+ }
+ getLog().info("==========================================================================");
+ }
+ }
+
+ private static int dbCounter;
+
+ protected void doReplicate(TopiaEntityEnum contract, TopiaEntity... entity) throws Exception {
+
+ TopiaContext rootCtxt = createReplicateDb("doReplicate_" + contract);
+
+ List<String> ids = TopiaEntityHelper.getTopiaIdList(Arrays.asList(entity));
+ getLog().info("entity " + ids);
+
+ prepareModel(ids.toArray(new String[ids.size()]));
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+
+ service.doReplicate(model, dstCtxt);
+
+ //dstCtxt.closeContext();
+
+ if (entity.length == 0) {
+
+ return;
+ }
+ dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
+
+ for (TopiaEntity e : entity) {
+ TopiaEntity actual = dstCtxt.findByTopiaId(e.getTopiaId());
+ assertNotNull(actual);
+ assertEquals(e, actual);
+ }
+
+ dstCtxt.closeContext();
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+ }
+
+ protected void doReplicateAll() throws Exception {
+
+ TopiaContext rootCtxt = createReplicateDb("doReplicateAll");
+
+ prepareModelAll();
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+
+ service.doReplicate(model, dstCtxt);
+
+ TopiaContextImplementor ctxt2 = (TopiaContextImplementor) ctxt;
+ dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
+
+ assertDbEquals(model.getContracts(), (TopiaContextImplementor) ctxt, ctxt2);
+
+ dstCtxt.closeContext();
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+ }
+
+ protected void doReplicateWithComputedOrder(TopiaEntity... entity) throws Exception {
+
+ TopiaContext rootCtxt = createReplicateDb("doReplicateWithComputedOrder");
+
+ List<String> ids = TopiaEntityHelper.getTopiaIdList(Arrays.asList(entity));
+
+ prepareModelWithComputedOrder(ids.toArray(new String[ids.size()]));
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+
+ service.doReplicate(model, dstCtxt);
+
+ getLog().info("replication is done for " + Arrays.toString(entity) + ", will verify data...");
+
+ TopiaContextImplementor ctxt2 = (TopiaContextImplementor) ctxt;
+ dstCtxt = (TopiaContextImplementor) rootCtxt.beginTransaction();
+
+ assertDbEquals(model.getContracts(), (TopiaContextImplementor) ctxt, ctxt2);
+
+ dstCtxt.closeContext();
+
+ dstCtxt = (TopiaContextImplementor) rootCtxt;
+ }
+
+ protected void assertDbEquals(TopiaEntityEnum[] contracts,
+ TopiaContextImplementor ctxt,
+ TopiaContextImplementor ctxt2) throws TopiaException {
+ Set<String> ids = new HashSet<String>();
+
+ if (getLog().isInfoEnabled()) {
+ getLog().info("will verify db for contracts " + Arrays.toString(contracts));
+ }
+ for (TopiaEntityEnum c : contracts) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("verify for contract " + c);
+ }
+ TopiaDAO<? extends TopiaEntity> daoSrc = ctxt.getDAO(c.getContract());
+ TopiaDAO<? extends TopiaEntity> daoDst = ctxt2.getDAO(c.getContract());
+ long nbSrc = daoSrc.count();
+ long nbDst = daoDst.count();
+ assertEquals("le nombres d'entites de type " + c + " devrait etre " + nbSrc + " mais est " + nbDst, nbSrc, nbDst);
+ List<String> idsSrc = daoSrc.findAllIds();
+ List<String> idsDst = daoDst.findAllIds();
+ Collections.sort(idsSrc);
+ Collections.sort(idsDst);
+ assertEquals(idsSrc, idsDst);
+ for (String id : idsSrc) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("verify for entity " + id);
+ }
+ TopiaEntity eSrc = daoSrc.findByTopiaId(id);
+ TopiaEntity eDst = daoDst.findByTopiaId(id);
+ assertEquals(eSrc, eDst);
+ assertEntityEquals(eSrc, eDst, ids);
+ }
+ }
+ }
+
+ protected void assertEntityEquals(TopiaEntity expected,
+ TopiaEntity actual,
+ Set<String> treated) {
+ if (treated == null) {
+ treated = new HashSet<String>();
+ }
+ if (treated.contains(actual.getTopiaId())) {
+ return;
+ }
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(expected);
+ }
+ assertEquals(actual.getTopiaId(), expected.getTopiaId());
+ treated.add(actual.getTopiaId());
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("expected : " + expected + " / actual " + actual);
+ }
+ TopiaEntityEnum contract = TopiaEntityHelper.getEntityEnum(expected.getClass(), getContracts());
+ if (contract == null) {
+ // this type of entity in not dealed here...
+ getLog().debug("untested property type " + expected.getClass());
+ return;
+ }
+ Assert.assertNotNull(
+ "contract not found for " + expected.getClass() + " in " +
+ Arrays.toString(getContracts()), contract);
+ EntityOperator<TopiaEntity> operator = EntityOperatorStore.getOperator(contract);
+ List<String> associationProperties = operator.getAssociationProperties();
+ for (String name : associationProperties) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("association " + name);
+ }
+ if (operator.isChildEmpty(name, expected)) {
+ assertTrue("l'association " + name + " devrait etre vide mais possede " + operator.sizeChild(name, actual) + " entrees", operator.isChildEmpty(name, actual));
+ } else {
+ assertFalse("l'association " + name + " devrait posseder " + operator.isChildEmpty(name, expected) + " mais est vide", operator.isChildEmpty(name, actual));
+
+ }
+ assertEquals(operator.isChildEmpty(name, actual), operator.isChildEmpty(name, expected));
+
+ Class<?> type = operator.getAssociationPropertyType(name);
+ Collection<?> src = (Collection<?>) operator.get(name, expected);
+ Collection<?> dst = (Collection<?>) operator.get(name, actual);
+// assertEquals(src, dst);
+ Iterator<?> itrSrc = src.iterator();
+ Iterator<?> itrDst = dst.iterator();
+ while (itrSrc.hasNext()) {
+ if (TopiaEntity.class.isAssignableFrom(type)) {
+ assertEntityEquals((TopiaEntity) itrSrc.next(), (TopiaEntity) itrDst.next(), treated);
+ } else {
+ assertEquals(itrSrc.next(), itrDst.next());
+ }
+ }
+ }
+
+ for (String name : operator.getProperties()) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("dependency " + name);
+ }
+ if (associationProperties.contains(name)) {
+ // deja traite au dessus
+ continue;
+ }
+ Class<?> type = operator.getPropertyType(name);
+ Object src = operator.get(name, expected);
+ Object dst = operator.get(name, actual);
+ assertFalse(src == null && dst != null);
+ assertFalse(src != null && dst == null);
+ if (src == null) {
+ continue;
+ }
+ if (TopiaEntity.class.isAssignableFrom(type)) {
+ assertEntityEquals((TopiaEntity) src, (TopiaEntity) dst, treated);
+ } else {
+ assertEquals(src, dst);
+ }
+ }
+ }
+
+ protected void createUnsupportedBeforeOperation(TopiaEntityEnum contract,
+ TopiaEntity entity,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) throws Exception {
+
+ getLog().info("entity " + entity.getTopiaId());
+ prepareModel(entity.getTopiaId());
+
+ service.addBeforeOperation(model, contract, operationClass, parameters);
+ // on ne doit pas avoir le droit de creer cette operation
+ fail();
+ }
+
+ protected void createUnsupportedAfterOperation(TopiaEntityEnum contract,
+ TopiaEntity entity,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) throws Exception {
+
+ getLog().info("entity " + entity.getTopiaId());
+ prepareModel(entity.getTopiaId());
+// model = service.createModel(getContracts());
+// model.detectDirectDependencies();
+ service.addAfterOperation(model, contract, operationClass, parameters);
+ // on ne doit pas avoir le droit de creer cette operation
+ fail();
+ }
+
+ protected Long getTestsTimeStamp() {
+ if (testsTimeStamp == null) {
+ testsTimeStamp = System.currentTimeMillis();
+ getLog().info("tests timestamp : " + testsTimeStamp);
+ }
+ return testsTimeStamp;
+ }
+
+ protected File getTestDir(Class<?> testClass) {
+ if (testsBasedir == null) {
+ String tmp = System.getProperty("basedir");
+ if (tmp == null) {
+ tmp = new File("").getAbsolutePath();
+ }
+ String name = String.format(TEST_BASEDIR, File.separator, new Date(getTestsTimeStamp()));
+ testsBasedir = new File(new File(tmp), name);
+ getLog().info("tests basedir : " + testsBasedir);
+ }
+ return new File(testsBasedir, testClass.getSimpleName());
+ }
+
+ protected void createModel(TopiaEntity entity) throws TopiaException {
+ model = service.getModelBuilder().createModel(context, getContracts(), entity.getTopiaId());
+ }
+
+ protected void prepareModel(String... ids) throws TopiaException {
+ model = service.prepare(getContracts(), ids);
+ }
+
+ protected void prepareModelAll() throws TopiaException {
+ model = service.prepareForAll(getContracts());
+ }
+
+ protected void prepareModelWithComputedOrder(String... ids) throws TopiaException {
+ model = service.prepareWithComputedOrder(getContracts(), ids);
+ }
+}
Property changes on: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractTopiaReplicationServiceTest.java
___________________________________________________________________
Added: svn:keywords
+ HeadURL Id Date Revision Author
Deleted: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,296 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaContextFactory;
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaEntity;
-import org.nuiton.topia.persistence.TopiaEntityEnum;
-import org.nuiton.topia.test.entities.Person;
-import org.nuiton.topia.test.entities.PersonImpl;
-import org.nuiton.topia.test.entities.Pet;
-import org.nuiton.topia.test.entities.PetImpl;
-import org.nuiton.topia.test.entities.Race;
-import org.nuiton.topia.test.entities.RaceImpl;
-
-import java.io.File;
-import java.util.Properties;
-
-/**
- * ReplicationEngineTest on model TopiaTest
- * <p/>
- * Created: 07 jun. 09 17:14:22
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.2.0
- */
-public class ReplicationEngineAllTest extends AbstractReplicationEngineTest {
-
- /** to use log facility, just put in your code: log.info(\"...\"); */
- private static final Log log = LogFactory.getLog(ReplicationEngineTest.class);
-
- protected static final TopiaEntityEnum[] contracts = {
- TopiaTestEntityEnum.Person,
- TopiaTestEntityEnum.Pet,
- TopiaTestEntityEnum.Race
- };
-
- protected static final String entitiesList =
- PersonImpl.class.getName() + "," +
- PetImpl.class.getName() + "," +
- RaceImpl.class.getName();
-
- static protected Person person, person2;
-
- static protected Pet pet, pet2, pet3;
-
- static protected Race race, race2, race3;
-
- @AfterClass
- public static void after() throws Exception {
- AbstractReplicationEngineTest.after();
- }
-
- @Before
- @Override
- public void setUp() throws Exception {
-
- super.setUp();
-
- person = update(person);
- person2 = update(person2);
- pet = update(pet);
- pet2 = update(pet2);
- race = update(race);
- race2 = update(race2);
- race3 = update(race3);
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- if (dstCtxt != null && !dstCtxt.isClosed()) {
- dstCtxt.closeContext();
- }
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectTypes() throws Exception {
-
- detectTypes(race, Race.class);
- detectTypes(pet, Pet.class, Person.class, Race.class);
- detectTypes(person, Pet.class, Person.class, Race.class);
-
- detectTypes(pet2, Pet.class);
- detectTypes(person2, Person.class);
- detectTypes(race2, Race.class);
-
- detectTypes(race3, Race.class);
- detectTypes(pet3, Pet.class, Race.class);
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testGetOperation() throws Exception {
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectAssociations() throws Exception {
-
- detectAssociations(person, TopiaTestEntityEnum.Person, Person.PROPERTY_PET);
- detectAssociations(race);
- detectAssociations(pet);
-
- detectAssociations(person2);
- detectAssociations(race2);
- detectAssociations(pet2);
-
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectDirectDependencies() throws Exception {
-
- detectDirectDependencies(person);
- detectDirectDependencies(race);
- detectDirectDependencies(pet, TopiaTestEntityEnum.Pet, Pet.PROPERTY_PERSON, TopiaTestEntityEnum.Pet, Pet.PROPERTY_RACE);
-
- detectDirectDependencies(person2);
- detectDirectDependencies(race2);
- detectDirectDependencies(pet2);
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectShell() throws Exception {
-
- detectShell(person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
- detectShell(race);
- detectShell(pet, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
- detectShell(person2, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
- detectShell(race2);
- detectShell(pet2, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectDependencies() throws Exception {
-
- detectDependencies(null,
- new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectObjectsToDettach() throws Exception {
-
- detectObjectsToDettach(null, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDetectOperations() throws Exception {
-
- detectOperations(null);
- }
-
-// @Ignore
-
- @Test
- @Override
- public void testDoReplicate() throws Exception {
-
- doReplicateAll();
-
- }
-
- @Override
- protected TopiaContext createDb(String name) throws Exception {
-
- File localDB = new File(getTestDir(getClass()), "db_" + name);
-
- Properties config = getH2Properties(localDB);
-
- context = TopiaContextFactory.getContext(config);
-
- TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
-
- person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
- race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
- pet = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding", Pet.PROPERTY_PERSON, person, Pet.PROPERTY_RACE, race);
-
- person2 = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding II master");
- pet2 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding II");
- race2 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race II");
-
- race3 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race III");
- pet3 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding III", Pet.PROPERTY_RACE, race3);
-
- tx.commitTransaction();
- tx.closeContext();
- return context;
- }
-
- @Override
- protected TopiaContext createDb2(String name) throws Exception {
-
- File localDB = new File(getTestDir(getClass()), "db_" + name);
-
- Properties config = getH2Properties(localDB);
-
- return TopiaContextFactory.getContext(config);
- }
-
- @Override
- protected TopiaEntityEnum[] getContracts() {
- return contracts;
- }
-
- @Override
- protected Log getLog() {
- return log;
- }
-
- protected Properties getH2Properties(File f) {
-
- Properties config = new Properties();
- config.setProperty("hibernate.show_sql", "false");
- config.setProperty("hibernate.hbm2ddl.auto", "create");
-
- config.setProperty("topia.persistence.classes", entitiesList);
- config.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
- config.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
- config.setProperty("hibernate.connection.url", "jdbc:h2:file:" + f.getAbsolutePath() + ";create=true");
- config.setProperty("hibernate.connection.username", "sa");
- config.setProperty("hibernate.connection.password", "");
-
- config.setProperty("topia.service.replication", ReplicationEngine.class.getName());
-
- return config;
- }
-
-
- @Override
- protected void createModel(TopiaEntity entity) throws TopiaException {
- model = service.createModelForAll(getContracts());
- }
-
- @Override
- protected void prepareModel(String... ids) throws TopiaException {
- model = service.prepareForAll(getContracts());
- }
-
-}
-
-
Deleted: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,445 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.Test;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaContextFactory;
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaEntityEnum;
-import org.nuiton.topia.replication.model.ReplicationModel;
-import org.nuiton.topia.replication.operation.AttachAssociation;
-import org.nuiton.topia.replication.operation.DettachAssociation;
-import org.nuiton.topia.replication.operation.Duplicate;
-import org.nuiton.topia.replication.operation.FakeOperation;
-import org.nuiton.topia.replication.operation.UncreatableOperation;
-import org.nuiton.topia.replication.operation.UnregistredOperation;
-import org.nuiton.topia.test.entities.Person;
-import org.nuiton.topia.test.entities.PersonImpl;
-import org.nuiton.topia.test.entities.Pet;
-import org.nuiton.topia.test.entities.PetImpl;
-import org.nuiton.topia.test.entities.Race;
-import org.nuiton.topia.test.entities.RaceImpl;
-
-import java.io.File;
-import java.util.Properties;
-
-/**
- * ReplicationEngineTest on model TopiaTest
- * <p/>
- * Created: 07 jun. 09 17:14:22
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.2.0
- */
-public class ReplicationEngineTest extends AbstractReplicationEngineTest {
-
- /** to use log facility, just put in your code: log.info(\"...\"); */
- private static final Log log = LogFactory.getLog(ReplicationEngineTest.class);
-
- protected static final TopiaEntityEnum[] contracts = {TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race};
-
- protected static final String entitiesList = PersonImpl.class.getName() + "," + PetImpl.class.getName() + "," + RaceImpl.class.getName();
-
- static protected Person person, person2;
-
- static protected Pet pet, pet2, pet3;
-
- static protected Race race, race2, race3;
-
- @AfterClass
- public static void after() throws Exception {
- AbstractReplicationEngineTest.after();
- }
-
- @Before
- @Override
- public void setUp() throws Exception {
-
- super.setUp();
-
- person = update(person);
- person2 = update(person2);
- pet = update(pet);
- pet2 = update(pet2);
- race = update(race);
- race2 = update(race2);
- race3 = update(race3);
- }
-
- @After
- @Override
- public void tearDown() throws Exception {
- super.tearDown();
- if (dstCtxt != null && !dstCtxt.isClosed()) {
- dstCtxt.closeContext();
- }
- }
-
- @Test
- @Override
- public void testDetectTypes() throws Exception {
-
- detectTypes(race, Race.class);
- detectTypes(pet, Pet.class, Person.class, Race.class);
- detectTypes(person, Pet.class, Person.class, Race.class);
-
- detectTypes(pet2, Pet.class);
- detectTypes(person2, Person.class);
- detectTypes(race2, Race.class);
-
- detectTypes(race3, Race.class);
- detectTypes(pet3, Pet.class, Race.class);
- }
-
- @Test
- @Override
- public void testGetOperation() throws Exception {
-
- getOperation(UnregistredOperation.class, false);
- getOperation(UncreatableOperation.class, true);
- getOperation(FakeOperation.class, true);
- getOperation(Duplicate.class, true);
- getOperation(AttachAssociation.class, true);
- getOperation(DettachAssociation.class, true);
- }
-
- @Test
- @Override
- public void testDetectAssociations() throws Exception {
-
- detectAssociations(person, TopiaTestEntityEnum.Person, Person.PROPERTY_PET);
- detectAssociations(race);
- detectAssociations(pet);
-
- detectAssociations(person2);
- detectAssociations(race2);
- detectAssociations(pet2);
-
- }
-
- @Test
- @Override
- public void testDetectDirectDependencies() throws Exception {
-
- detectDirectDependencies(person);
- detectDirectDependencies(race);
- detectDirectDependencies(pet, TopiaTestEntityEnum.Pet, Pet.PROPERTY_PERSON, TopiaTestEntityEnum.Pet, Pet.PROPERTY_RACE);
-
- detectDirectDependencies(person2);
- detectDirectDependencies(race2);
- detectDirectDependencies(pet2);
- }
-
- @Test
- @Override
- public void testDetectShell() throws Exception {
-
- detectShell(person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
- detectShell(race);
- detectShell(pet, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
- detectShell(person2);
- detectShell(race2);
- detectShell(pet2);
- }
-
- @Test
- @Override
- public void testDetectDependencies() throws Exception {
-
- detectDependencies(person, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
- detectDependencies(race, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
- detectDependencies(pet, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
-
- detectDependencies(person2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person});
- detectDependencies(race2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
- detectDependencies(pet2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
- }
-
- @Test
- @Override
- public void testDetectObjectsToDettach() throws Exception {
-
- detectObjectsToDettach(person, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
- detectObjectsToDettach(race);
- detectObjectsToDettach(pet, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
-
- detectObjectsToDettach(person2);
- detectObjectsToDettach(race2);
- detectObjectsToDettach(pet2);
-
- detectObjectsToDettach(race3);
- detectObjectsToDettach(pet3);
- }
-
- @Test
- @Override
- public void testDetectOperations() throws Exception {
-
- //TODO Make some real test on detected operations...
-
- detectOperations(person);
- detectOperations(pet);
- detectOperations(race);
-
- detectOperations(person2);
- detectOperations(pet2);
- detectOperations(race2);
-
- detectOperations(race3);
- detectOperations(pet3);
- }
-
- @Test
- @Override
- public void testDoReplicate() throws Exception {
-
- doReplicate(TopiaTestEntityEnum.Person, person);
- doReplicate(TopiaTestEntityEnum.Person, person2);
- doReplicate(TopiaTestEntityEnum.Person, person, person2);
-
- doReplicate(TopiaTestEntityEnum.Pet, pet);
- doReplicate(TopiaTestEntityEnum.Pet, pet2);
- doReplicate(TopiaTestEntityEnum.Pet, pet, pet2, pet3);
- doReplicate(TopiaTestEntityEnum.Pet, person2, pet3);
-
- doReplicate(TopiaTestEntityEnum.Race, race);
- doReplicate(TopiaTestEntityEnum.Race, race2);
- doReplicate(TopiaTestEntityEnum.Race, race, race2);
-
- }
-
- /**
- * Cette methode montre pourquoi la simple replication ne peut pas
- * fonctionne :)
- * <p/>
- * Le replicateur ne deplique pas dans le bon ordre et on a donc des
- * violations de clef etrangeres...
- *
- * @throws Exception pour toute erreur
- */
- @Test(expected = TopiaException.class)
- public void testSimpleReplicateFailed() throws Exception {
-
- TopiaContext dstRootCtxt = createDb2("testSimpleReplicateFailed");
-
- //model = service.prepare(contracts, pet.getTopiaId());
-
- TopiaContext srcCtxt = ctxt.beginTransaction();
- dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
-
- try {
-
- srcCtxt.replicateEntity(dstCtxt, pet);
-
- dstCtxt.commitTransaction();
-
- } finally {
- srcCtxt.rollbackTransaction();
- srcCtxt.closeContext();
- dstCtxt.closeContext();
- }
- }
-
- /**
- * Cette methode montre comment manuellement on peut effectuer la
- * replication (en dettachant les dependances qui forment des cycles)
- * <p/>
- * La methode utilisee ici peut ne pas fonctionner : si une clef metier est
- * posee sur une dependance alors cela ne fonctionne pas.
- *
- * @throws Exception pour toute erreur
- */
- @Test
- public void testSimpleReplicateNotSure() throws Exception {
-
- TopiaContext dstRootCtxt = createDb2("testSimpleReplicateNotSure");
-
- //model = service.prepare(contracts, pet.getTopiaId());
-
- TopiaContext srcCtxt = ctxt;
- dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
-
- try {
-
-
- srcCtxt.replicateEntity(dstCtxt, race);
-
- // on dettache l'entite qui pose probleme
-
- pet.setPerson(null);
- srcCtxt.replicateEntity(dstCtxt, pet);
- srcCtxt.rollbackTransaction();
-
- srcCtxt.replicateEntity(dstCtxt, person);
-
- dstCtxt.commitTransaction();
- ((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())).setPerson((Person) dstCtxt.findByTopiaId(person.getTopiaId()));
- dstCtxt.commitTransaction();
-
- srcCtxt.rollbackTransaction();
- person = update(person);
-
- assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
- } finally {
- srcCtxt.rollbackTransaction();
- //srcCtxt.closeContext();
- dstCtxt.closeContext();
- }
- }
-
- /**
- * Cette methode montre comment manuellement on peut effectuer la
- * replication (en dettachant les associations qui forment des cycles)
- * <p/>
- * La methode utilisee ici fonctionne mieux que la precedante : il parrait
- * dificille de pose une une clef metier sur une association :).
- * <p/>
- * On remarque que l'on dettache l'assocation qui forme un cycle et que l'on
- * est pas obligee de la reattachee car elle est bi-directionnelle.
- * <p/>
- * On doit optimiser l'algorithme dans la methode {@link
- * ReplicationModel#adjustOperations(org.nuiton.topia.persistence.util.TopiaEntityIdsMap)}.
- *
- * @throws Exception pour toute erreur
- */
- @Test
- public void testSimpleReplicateSure() throws Exception {
-
- TopiaContext dstRootCtxt = createDb2("testSimpleReplicateSure");
-
- //model = service.prepare(contracts, pet.getTopiaId());
-
- TopiaContext srcCtxt = ctxt;
- dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
-
- try {
-
- srcCtxt.replicateEntity(dstCtxt, race);
- // on dettache l'association qui pose probleme
- person.setPet(null);
- srcCtxt.replicateEntity(dstCtxt, person);
-
- srcCtxt.replicateEntity(dstCtxt, pet);
- srcCtxt.rollbackTransaction();
- dstCtxt.commitTransaction();
-
- //((Person) dstCtxt.findByTopiaId(person.getTopiaId())).addPet(((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())));
- //dstCtxt.commitTransaction();
-
- srcCtxt.rollbackTransaction();
-
- srcCtxt.closeContext();
- dstCtxt.closeContext();
-
- ctxt = context.beginTransaction();
- dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
-
- person = update(person);
-
- assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
-
- } finally {
- dstCtxt.closeContext();
- }
- }
-
- @Override
- protected TopiaContext createDb(String name) throws Exception {
-
- File localDB = new File(getTestDir(getClass()), "db_" + name);
-
- Properties config = getH2Properties(localDB);
-
- context = TopiaContextFactory.getContext(config);
-
- TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
-
- person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
- race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
- pet = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding", Pet.PROPERTY_PERSON, person, Pet.PROPERTY_RACE, race);
-
- person2 = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding II master");
- pet2 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding II");
- race2 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race II");
-
- race3 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race III");
- pet3 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding III", Pet.PROPERTY_RACE, race3);
-
- tx.commitTransaction();
- tx.closeContext();
- return context;
- }
-
- @Override
- protected TopiaContext createDb2(String name) throws Exception {
-
- File localDB = new File(getTestDir(getClass()), "db_" + name);
-
- log.info("db dir :\n" + localDB.getAbsolutePath());
-
- Properties config = getH2Properties(localDB);
-
- return TopiaContextFactory.getContext(config);
- }
-
- @Override
- protected TopiaEntityEnum[] getContracts() {
- return contracts;
- }
-
- @Override
- protected Log getLog() {
- return log;
- }
-
- protected Properties getH2Properties(File f) {
-
- Properties config = new Properties();
- config.setProperty("hibernate.show_sql", "false");
- config.setProperty("hibernate.hbm2ddl.auto", "create");
-
- config.setProperty("topia.persistence.classes", entitiesList);
- config.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
- config.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
- config.setProperty("hibernate.connection.url", "jdbc:h2:file:" + f.getAbsolutePath() + "/db;create=true");
- config.setProperty("hibernate.connection.username", "sa");
- config.setProperty("hibernate.connection.password", "");
-
- config.setProperty("topia.service.replication", ReplicationEngine.class.getName());
-
- return config;
- }
-}
-
-
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -54,17 +54,18 @@
import java.util.Properties;
/**
- * ReplicationEngineTest on model TopiaTest
+ * TopiaReplicationServiceImplTest on model TopiaTest
* <p/>
* Created: 07 jun. 09 17:14:22
*
* @author tchemit <chemit(a)codelutin.com>
* @since 2.2.0
*/
-public class TopiaReplicationOperationTest extends AbstractReplicationEngineTest {
+public class TopiaReplicationOperationTest extends AbstractTopiaReplicationServiceTest {
- /** to use log facility, just put in your code: log.info(\"...\"); */
- private static final Log log = LogFactory.getLog(ReplicationEngineTest.class);
+ /** Logger */
+ private static final Log log =
+ LogFactory.getLog(TopiaReplicationOperationTest.class);
protected static final TopiaEntityEnum[] contracts = {TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race};
@@ -78,7 +79,7 @@
@AfterClass
public static void after() throws Exception {
- AbstractReplicationEngineTest.after();
+ AbstractTopiaReplicationServiceTest.after();
}
@Before
@@ -106,23 +107,11 @@
@Test(expected = NullPointerException.class)
public void testGetOperation_nullOperationClass() throws Exception {
- service.getOperation(null);
+ getModelBuilder().getOperation(null);
}
- @Test(expected = IllegalStateException.class)
- public void testGetOperation_serviceNotInit() throws Exception {
-// ReplicationEngine.operations = null;
- try {
- new ReplicationEngine().getOperation(Duplicate.class);
- } catch (IllegalStateException e) {
- if (log.isErrorEnabled()) {
- log.error(e);
- }
- throw e;
- } finally {
-
- service.preInit((TopiaContextImplementor) context);
- }
+ protected TopiaReplicationModelBuilder getModelBuilder() {
+ return service.getModelBuilder();
}
@Test
@@ -139,34 +128,34 @@
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullModel() throws Exception {
- service.createOperation(null, null, null, null);
+ getModelBuilder().createOperation(null, null, null, null);
}
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullType() throws Exception {
- model = service.createModel(contracts);
- service.createOperation(model, null, null, null);
+ model = getModelBuilder().createModel(context, contracts);
+ getModelBuilder().createOperation(model, null, null, null);
}
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullPhase() throws Exception {
- model = service.createModel(contracts);
- service.createOperation(model, TopiaTestEntityEnum.Pet, null, null);
+ model = getModelBuilder().createModel(context, contracts);
+ getModelBuilder().createOperation(model, TopiaTestEntityEnum.Pet, null, null);
}
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullOperationClass() throws Exception {
- model = service.createModel(contracts);
- service.createOperation(model, TopiaTestEntityEnum.Pet, ReplicationOperationPhase.before, null);
+ model = getModelBuilder().createModel(context, contracts);
+ getModelBuilder().createOperation(model, TopiaTestEntityEnum.Pet, ReplicationOperationPhase.before, null);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_noNode() throws Exception {
- model = service.createModel(contracts);
+ model = getModelBuilder().createModel(context, contracts);
// le noeud Pet n'existe pas
service.addAfterOperation(model, TopiaTestEntityEnum.Pet, Duplicate.class);
}
@@ -174,7 +163,7 @@
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_noOperation() throws Exception {
- model = service.createModel(contracts);
+ model = getModelBuilder().createModel(context, contracts);
// le noeud Pet n'existe pas
service.addAfterOperation(model, TopiaTestEntityEnum.Pet, UnregistredOperation.class);
}
@@ -222,35 +211,35 @@
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterNumber() throws Exception {
- model = service.createModel(contracts, pet.getTopiaId());
+ model = getModelBuilder().createModel(context, contracts, pet.getTopiaId());
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterNumber2() throws Exception {
- model = service.createModel(contracts, pet.getTopiaId());
+ model = getModelBuilder().createModel(context, contracts, pet.getTopiaId());
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, String.class, String.class);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterType() throws Exception {
- model = service.createModel(contracts, pet.getTopiaId());
+ model = getModelBuilder().createModel(context, contracts, pet.getTopiaId());
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, Integer.class);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_nullParameter() throws Exception {
- model = service.createModel(contracts, pet.getTopiaId());
+ model = getModelBuilder().createModel(context, contracts, pet.getTopiaId());
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, (Object) null);
}
@Test
public void testCreateOperation() throws Exception {
- model = service.createModel(contracts, pet.getTopiaId());
+ model = getModelBuilder().createModel(context, contracts, pet.getTopiaId());
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, "before");
service.addAfterOperation(model, TopiaTestEntityEnum.Race, FakeOperation.class, "after");
}
@@ -264,7 +253,7 @@
@Test(expected = NullPointerException.class)
public void testDoReplicate_nullDstCtxt() throws Exception {
- model = service.createModel(contracts);
+ model = getModelBuilder().createModel(context, contracts);
service.doReplicate(model, null);
}
@@ -277,7 +266,8 @@
context = TopiaContextFactory.getContext(config);
- TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
+ TopiaContextImplementor tx =
+ (TopiaContextImplementor) context.beginTransaction();
person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
@@ -315,7 +305,7 @@
config.setProperty("hibernate.connection.username", "sa");
config.setProperty("hibernate.connection.password", "");
- config.setProperty("topia.service.replication", ReplicationEngine.class.getName());
+ config.setProperty("topia.service.replication", TopiaReplicationServiceImpl.class.getName());
return config;
}
Copied: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplAllTest.java (from rev 2098, trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java)
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplAllTest.java (rev 0)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplAllTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,296 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaContextFactory;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
+import org.nuiton.topia.framework.TopiaContextImplementor;
+import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.test.entities.Person;
+import org.nuiton.topia.test.entities.PersonImpl;
+import org.nuiton.topia.test.entities.Pet;
+import org.nuiton.topia.test.entities.PetImpl;
+import org.nuiton.topia.test.entities.Race;
+import org.nuiton.topia.test.entities.RaceImpl;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * TopiaReplicationServiceImplTest on model TopiaTest
+ * <p/>
+ * Created: 07 jun. 09 17:14:22
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
+public class TopiaReplicationServiceImplAllTest extends AbstractTopiaReplicationServiceTest {
+
+ /** Logger */
+ private static final Log log = LogFactory.getLog(TopiaReplicationServiceImplTest.class);
+
+ protected static final TopiaEntityEnum[] contracts = {
+ TopiaTestEntityEnum.Person,
+ TopiaTestEntityEnum.Pet,
+ TopiaTestEntityEnum.Race
+ };
+
+ protected static final String entitiesList =
+ PersonImpl.class.getName() + "," +
+ PetImpl.class.getName() + "," +
+ RaceImpl.class.getName();
+
+ static protected Person person, person2;
+
+ static protected Pet pet, pet2, pet3;
+
+ static protected Race race, race2, race3;
+
+ @AfterClass
+ public static void after() throws Exception {
+ AbstractTopiaReplicationServiceTest.after();
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+
+ super.setUp();
+
+ person = update(person);
+ person2 = update(person2);
+ pet = update(pet);
+ pet2 = update(pet2);
+ race = update(race);
+ race2 = update(race2);
+ race3 = update(race3);
+ }
+
+ @After
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (dstCtxt != null && !dstCtxt.isClosed()) {
+ dstCtxt.closeContext();
+ }
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectTypes() throws Exception {
+
+ detectTypes(race, Race.class);
+ detectTypes(pet, Pet.class, Person.class, Race.class);
+ detectTypes(person, Pet.class, Person.class, Race.class);
+
+ detectTypes(pet2, Pet.class);
+ detectTypes(person2, Person.class);
+ detectTypes(race2, Race.class);
+
+ detectTypes(race3, Race.class);
+ detectTypes(pet3, Pet.class, Race.class);
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testGetOperation() throws Exception {
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectAssociations() throws Exception {
+
+ detectAssociations(person, TopiaTestEntityEnum.Person, Person.PROPERTY_PET);
+ detectAssociations(race);
+ detectAssociations(pet);
+
+ detectAssociations(person2);
+ detectAssociations(race2);
+ detectAssociations(pet2);
+
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectDirectDependencies() throws Exception {
+
+ detectDirectDependencies(person);
+ detectDirectDependencies(race);
+ detectDirectDependencies(pet, TopiaTestEntityEnum.Pet, Pet.PROPERTY_PERSON, TopiaTestEntityEnum.Pet, Pet.PROPERTY_RACE);
+
+ detectDirectDependencies(person2);
+ detectDirectDependencies(race2);
+ detectDirectDependencies(pet2);
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectShell() throws Exception {
+
+ detectShell(person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
+ detectShell(race);
+ detectShell(pet, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
+ detectShell(person2, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
+ detectShell(race2);
+ detectShell(pet2, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectDependencies() throws Exception {
+
+ detectDependencies(null,
+ new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectObjectsToDettach() throws Exception {
+
+ detectObjectsToDettach(null, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDetectOperations() throws Exception {
+
+ detectOperations(null);
+ }
+
+// @Ignore
+
+ @Test
+ @Override
+ public void testDoReplicate() throws Exception {
+
+ doReplicateAll();
+
+ }
+
+ @Override
+ protected TopiaContext createDb(String name) throws Exception {
+
+ File localDB = new File(getTestDir(getClass()), "db_" + name);
+
+ Properties config = getH2Properties(localDB);
+
+ context = TopiaContextFactory.getContext(config);
+
+ TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
+
+ person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
+ race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
+ pet = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding", Pet.PROPERTY_PERSON, person, Pet.PROPERTY_RACE, race);
+
+ person2 = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding II master");
+ pet2 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding II");
+ race2 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race II");
+
+ race3 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race III");
+ pet3 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding III", Pet.PROPERTY_RACE, race3);
+
+ tx.commitTransaction();
+ tx.closeContext();
+ return context;
+ }
+
+ @Override
+ protected TopiaContext createDb2(String name) throws Exception {
+
+ File localDB = new File(getTestDir(getClass()), "db_" + name);
+
+ Properties config = getH2Properties(localDB);
+
+ return TopiaContextFactory.getContext(config);
+ }
+
+ @Override
+ protected TopiaEntityEnum[] getContracts() {
+ return contracts;
+ }
+
+ @Override
+ protected Log getLog() {
+ return log;
+ }
+
+ protected Properties getH2Properties(File f) {
+
+ Properties config = new Properties();
+ config.setProperty("hibernate.show_sql", "false");
+ config.setProperty("hibernate.hbm2ddl.auto", "create");
+
+ config.setProperty("topia.persistence.classes", entitiesList);
+ config.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
+ config.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
+ config.setProperty("hibernate.connection.url", "jdbc:h2:file:" + f.getAbsolutePath() + ";create=true");
+ config.setProperty("hibernate.connection.username", "sa");
+ config.setProperty("hibernate.connection.password", "");
+
+ config.setProperty(TopiaReplicationServiceImpl.TOPIA_SERVICE_NAME, TopiaReplicationServiceImpl.class.getName());
+
+ return config;
+ }
+
+
+ @Override
+ protected void createModel(TopiaEntity entity) throws TopiaException {
+ model = service.getModelBuilder().createModelForAll(getContracts());
+ }
+
+ @Override
+ protected void prepareModel(String... ids) throws TopiaException {
+ model = service.prepareForAll(getContracts());
+ }
+
+}
+
+
Property changes on: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplAllTest.java
___________________________________________________________________
Added: svn:keywords
+ HeadURL Id Date Revision Author
Copied: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplTest.java (from rev 2098, trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java)
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplTest.java (rev 0)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplTest.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -0,0 +1,446 @@
+/*
+ * #%L
+ * ToPIA :: Service Replication
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
+
+package org.nuiton.topia.replication;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaContextFactory;
+import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
+import org.nuiton.topia.framework.TopiaContextImplementor;
+import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
+import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.operation.AttachAssociation;
+import org.nuiton.topia.replication.operation.DettachAssociation;
+import org.nuiton.topia.replication.operation.Duplicate;
+import org.nuiton.topia.replication.operation.FakeOperation;
+import org.nuiton.topia.replication.operation.UncreatableOperation;
+import org.nuiton.topia.replication.operation.UnregistredOperation;
+import org.nuiton.topia.test.entities.Person;
+import org.nuiton.topia.test.entities.PersonImpl;
+import org.nuiton.topia.test.entities.Pet;
+import org.nuiton.topia.test.entities.PetImpl;
+import org.nuiton.topia.test.entities.Race;
+import org.nuiton.topia.test.entities.RaceImpl;
+
+import java.io.File;
+import java.util.Properties;
+
+/**
+ * TopiaReplicationServiceImplTest on model TopiaTest
+ * <p/>
+ * Created: 07 jun. 09 17:14:22
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
+public class TopiaReplicationServiceImplTest extends AbstractTopiaReplicationServiceTest {
+
+ /** Logger */
+ private static final Log log = LogFactory.getLog(TopiaReplicationServiceImplTest.class);
+
+ protected static final TopiaEntityEnum[] contracts = {TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race};
+
+ protected static final String entitiesList = PersonImpl.class.getName() + "," + PetImpl.class.getName() + "," + RaceImpl.class.getName();
+
+ static protected Person person, person2;
+
+ static protected Pet pet, pet2, pet3;
+
+ static protected Race race, race2, race3;
+
+ @AfterClass
+ public static void after() throws Exception {
+ AbstractTopiaReplicationServiceTest.after();
+ }
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+
+ super.setUp();
+
+ person = update(person);
+ person2 = update(person2);
+ pet = update(pet);
+ pet2 = update(pet2);
+ race = update(race);
+ race2 = update(race2);
+ race3 = update(race3);
+ }
+
+ @After
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (dstCtxt != null && !dstCtxt.isClosed()) {
+ dstCtxt.closeContext();
+ }
+ }
+
+ @Test
+ @Override
+ public void testDetectTypes() throws Exception {
+
+ detectTypes(race, Race.class);
+ detectTypes(pet, Pet.class, Person.class, Race.class);
+ detectTypes(person, Pet.class, Person.class, Race.class);
+
+ detectTypes(pet2, Pet.class);
+ detectTypes(person2, Person.class);
+ detectTypes(race2, Race.class);
+
+ detectTypes(race3, Race.class);
+ detectTypes(pet3, Pet.class, Race.class);
+ }
+
+ @Test
+ @Override
+ public void testGetOperation() throws Exception {
+
+ getOperation(UnregistredOperation.class, false);
+ getOperation(UncreatableOperation.class, true);
+ getOperation(FakeOperation.class, true);
+ getOperation(Duplicate.class, true);
+ getOperation(AttachAssociation.class, true);
+ getOperation(DettachAssociation.class, true);
+ }
+
+ @Test
+ @Override
+ public void testDetectAssociations() throws Exception {
+
+ detectAssociations(person, TopiaTestEntityEnum.Person, Person.PROPERTY_PET);
+ detectAssociations(race);
+ detectAssociations(pet);
+
+ detectAssociations(person2);
+ detectAssociations(race2);
+ detectAssociations(pet2);
+
+ }
+
+ @Test
+ @Override
+ public void testDetectDirectDependencies() throws Exception {
+
+ detectDirectDependencies(person);
+ detectDirectDependencies(race);
+ detectDirectDependencies(pet, TopiaTestEntityEnum.Pet, Pet.PROPERTY_PERSON, TopiaTestEntityEnum.Pet, Pet.PROPERTY_RACE);
+
+ detectDirectDependencies(person2);
+ detectDirectDependencies(race2);
+ detectDirectDependencies(pet2);
+ }
+
+ @Test
+ @Override
+ public void testDetectShell() throws Exception {
+
+ detectShell(person, TopiaTestEntityEnum.Pet, TopiaTestEntityEnum.Race);
+ detectShell(race);
+ detectShell(pet, TopiaTestEntityEnum.Person, TopiaTestEntityEnum.Race);
+ detectShell(person2);
+ detectShell(race2);
+ detectShell(pet2);
+ }
+
+ @Test
+ @Override
+ public void testDetectDependencies() throws Exception {
+
+ detectDependencies(person, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
+ detectDependencies(race, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
+ detectDependencies(pet, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
+
+ detectDependencies(person2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person});
+ detectDependencies(race2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race});
+ detectDependencies(pet2, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
+ }
+
+ @Test
+ @Override
+ public void testDetectObjectsToDettach() throws Exception {
+
+ detectObjectsToDettach(person, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
+ detectObjectsToDettach(race);
+ detectObjectsToDettach(pet, TopiaTestEntityEnum.Person, new String[]{Person.PROPERTY_PET});
+
+ detectObjectsToDettach(person2);
+ detectObjectsToDettach(race2);
+ detectObjectsToDettach(pet2);
+
+ detectObjectsToDettach(race3);
+ detectObjectsToDettach(pet3);
+ }
+
+ @Test
+ @Override
+ public void testDetectOperations() throws Exception {
+
+ //TODO Make some real test on detected operations...
+
+ detectOperations(person);
+ detectOperations(pet);
+ detectOperations(race);
+
+ detectOperations(person2);
+ detectOperations(pet2);
+ detectOperations(race2);
+
+ detectOperations(race3);
+ detectOperations(pet3);
+ }
+
+ @Test
+ @Override
+ public void testDoReplicate() throws Exception {
+
+ doReplicate(TopiaTestEntityEnum.Person, person);
+ doReplicate(TopiaTestEntityEnum.Person, person2);
+ doReplicate(TopiaTestEntityEnum.Person, person, person2);
+
+ doReplicate(TopiaTestEntityEnum.Pet, pet);
+ doReplicate(TopiaTestEntityEnum.Pet, pet2);
+ doReplicate(TopiaTestEntityEnum.Pet, pet, pet2, pet3);
+ doReplicate(TopiaTestEntityEnum.Pet, person2, pet3);
+
+ doReplicate(TopiaTestEntityEnum.Race, race);
+ doReplicate(TopiaTestEntityEnum.Race, race2);
+ doReplicate(TopiaTestEntityEnum.Race, race, race2);
+
+ }
+
+ /**
+ * Cette methode montre pourquoi la simple replication ne peut pas
+ * fonctionne :)
+ * <p/>
+ * Le replicateur ne deplique pas dans le bon ordre et on a donc des
+ * violations de clef etrangeres...
+ *
+ * @throws Exception pour toute erreur
+ */
+ @Test(expected = TopiaException.class)
+ public void testSimpleReplicateFailed() throws Exception {
+
+ TopiaContext dstRootCtxt = createDb2("testSimpleReplicateFailed");
+
+ //model = service.prepare(contracts, pet.getTopiaId());
+
+ TopiaContext srcCtxt = ctxt.beginTransaction();
+ dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
+
+ try {
+
+ srcCtxt.replicateEntity(dstCtxt, pet);
+
+ dstCtxt.commitTransaction();
+
+ } finally {
+ srcCtxt.rollbackTransaction();
+ srcCtxt.closeContext();
+ dstCtxt.closeContext();
+ }
+ }
+
+ /**
+ * Cette methode montre comment manuellement on peut effectuer la
+ * replication (en dettachant les dependances qui forment des cycles)
+ * <p/>
+ * La methode utilisee ici peut ne pas fonctionner : si une clef metier est
+ * posee sur une dependance alors cela ne fonctionne pas.
+ *
+ * @throws Exception pour toute erreur
+ */
+ @Test
+ public void testSimpleReplicateNotSure() throws Exception {
+
+ TopiaContext dstRootCtxt = createDb2("testSimpleReplicateNotSure");
+
+ //model = service.prepare(contracts, pet.getTopiaId());
+
+ TopiaContext srcCtxt = ctxt;
+ dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
+
+ try {
+
+
+ srcCtxt.replicateEntity(dstCtxt, race);
+
+ // on dettache l'entite qui pose probleme
+
+ pet.setPerson(null);
+ srcCtxt.replicateEntity(dstCtxt, pet);
+ srcCtxt.rollbackTransaction();
+
+ srcCtxt.replicateEntity(dstCtxt, person);
+
+ dstCtxt.commitTransaction();
+ ((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())).setPerson((Person) dstCtxt.findByTopiaId(person.getTopiaId()));
+ dstCtxt.commitTransaction();
+
+ srcCtxt.rollbackTransaction();
+ person = update(person);
+
+ assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
+ } finally {
+ srcCtxt.rollbackTransaction();
+ //srcCtxt.closeContext();
+ dstCtxt.closeContext();
+ }
+ }
+
+ /**
+ * Cette methode montre comment manuellement on peut effectuer la
+ * replication (en dettachant les associations qui forment des cycles)
+ * <p/>
+ * La methode utilisee ici fonctionne mieux que la precedante : il parrait
+ * dificille de pose une une clef metier sur une association :).
+ * <p/>
+ * On remarque que l'on dettache l'assocation qui forme un cycle et que l'on
+ * est pas obligee de la reattachee car elle est bi-directionnelle.
+ * <p/>
+ * On doit optimiser l'algorithme dans la methode {@link
+ * ReplicationModel#adjustOperations(TopiaEntityIdsMap)}.
+ *
+ * @throws Exception pour toute erreur
+ */
+ @Test
+ public void testSimpleReplicateSure() throws Exception {
+
+ TopiaContext dstRootCtxt = createDb2("testSimpleReplicateSure");
+
+ //model = service.prepare(contracts, pet.getTopiaId());
+
+ TopiaContext srcCtxt = ctxt;
+ dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
+
+ try {
+
+ srcCtxt.replicateEntity(dstCtxt, race);
+ // on dettache l'association qui pose probleme
+ person.setPet(null);
+ srcCtxt.replicateEntity(dstCtxt, person);
+
+ srcCtxt.replicateEntity(dstCtxt, pet);
+ srcCtxt.rollbackTransaction();
+ dstCtxt.commitTransaction();
+
+ //((Person) dstCtxt.findByTopiaId(person.getTopiaId())).addPet(((Pet) dstCtxt.findByTopiaId(pet.getTopiaId())));
+ //dstCtxt.commitTransaction();
+
+ srcCtxt.rollbackTransaction();
+
+ srcCtxt.closeContext();
+ dstCtxt.closeContext();
+
+ ctxt = context.beginTransaction();
+ dstCtxt = (TopiaContextImplementor) dstRootCtxt.beginTransaction();
+
+ person = update(person);
+
+ assertEntityEquals(person, dstCtxt.findByTopiaId(person.getTopiaId()), null);
+
+ } finally {
+ dstCtxt.closeContext();
+ }
+ }
+
+ @Override
+ protected TopiaContext createDb(String name) throws Exception {
+
+ File localDB = new File(getTestDir(getClass()), "db_" + name);
+
+ Properties config = getH2Properties(localDB);
+
+ context = TopiaContextFactory.getContext(config);
+
+ TopiaContextImplementor tx = (TopiaContextImplementor) context.beginTransaction();
+
+ person = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding master");
+ race = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race I");
+ pet = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding", Pet.PROPERTY_PERSON, person, Pet.PROPERTY_RACE, race);
+
+ person2 = tx.getDAO(Person.class).create(Person.PROPERTY_NAME, "pudding II master");
+ pet2 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding II");
+ race2 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race II");
+
+ race3 = tx.getDAO(Race.class).create(Race.PROPERTY_NAME, "race III");
+ pet3 = tx.getDAO(Pet.class).create(Pet.PROPERTY_NAME, "pudding III", Pet.PROPERTY_RACE, race3);
+
+ tx.commitTransaction();
+ tx.closeContext();
+ return context;
+ }
+
+ @Override
+ protected TopiaContext createDb2(String name) throws Exception {
+
+ File localDB = new File(getTestDir(getClass()), "db_" + name);
+
+ log.info("db dir :\n" + localDB.getAbsolutePath());
+
+ Properties config = getH2Properties(localDB);
+
+ return TopiaContextFactory.getContext(config);
+ }
+
+ @Override
+ protected TopiaEntityEnum[] getContracts() {
+ return contracts;
+ }
+
+ @Override
+ protected Log getLog() {
+ return log;
+ }
+
+ protected Properties getH2Properties(File f) {
+
+ Properties config = new Properties();
+ config.setProperty("hibernate.show_sql", "false");
+ config.setProperty("hibernate.hbm2ddl.auto", "create");
+
+ config.setProperty("topia.persistence.classes", entitiesList);
+ config.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
+ config.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
+ config.setProperty("hibernate.connection.url", "jdbc:h2:file:" + f.getAbsolutePath() + "/db;create=true");
+ config.setProperty("hibernate.connection.username", "sa");
+ config.setProperty("hibernate.connection.password", "");
+
+ config.setProperty(TopiaReplicationServiceImpl.TOPIA_SERVICE_NAME, TopiaReplicationServiceImpl.class.getName());
+
+ return config;
+ }
+}
+
+
Property changes on: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationServiceImplTest.java
___________________________________________________________________
Added: svn:keywords
+ HeadURL Id Date Revision Author
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -30,8 +30,8 @@
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.util.TopiaEntityHelper;
import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
-import org.nuiton.topia.replication.ReplicationEngine;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
@@ -46,7 +46,7 @@
*/
public class FakeOperation implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(FakeOperation.class);
public static final Class<?>[] PARAMETERS_CLASSES = new Class<?>[]{String.class};
@@ -57,7 +57,7 @@
ReplicationOperationPhase phase,
Object... parameters) {
- ReplicationEngine.checkParameters(PARAMETERS_CLASSES, parameters);
+ TopiaEntityHelper.checkParameters(PARAMETERS_CLASSES, parameters);
ReplicationOperationDef op = new ReplicationOperationDef(
phase,
getClass(),
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -47,7 +47,7 @@
*/
public class UncreatableOperation implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log =
LogFactory.getLog(UncreatableOperation.class);
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java 2010-08-15 11:58:21 UTC (rev 2101)
@@ -45,7 +45,7 @@
*/
public class UnregistredOperation implements TopiaReplicationOperation {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(UnregistredOperation.class);
@Override
Modified: trunk/topia-service-replication/src/test/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
===================================================================
--- trunk/topia-service-replication/src/test/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-15 11:51:20 UTC (rev 2100)
+++ trunk/topia-service-replication/src/test/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-15 11:58:21 UTC (rev 2101)
@@ -1,6 +1,6 @@
#
# la liste des operations disponibles pour le moteur de replication
-# voir la classe org.nuiton.topia.replication.ReplicationEngine
+# voir la classe org.nuiton.topia.replication.TopiaReplicationServiceImpl
#
org.nuiton.topia.replication.operation.FakeOperation
org.nuiton.topia.replication.operation.UncreatableOperation
\ No newline at end of file
1
0
r2100 - trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util
by tchemit@users.nuiton.org 15 Aug '10
by tchemit@users.nuiton.org 15 Aug '10
15 Aug '10
Author: tchemit
Date: 2010-08-15 13:51:20 +0200 (Sun, 15 Aug 2010)
New Revision: 2100
Url: http://nuiton.org/repositories/revision/topia/2100
Log:
add header
Modified:
trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java
Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java 2010-08-14 19:56:03 UTC (rev 2099)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java 2010-08-15 11:51:20 UTC (rev 2100)
@@ -1,3 +1,27 @@
+/*
+ * #%L
+ * ToPIA :: Persistence
+ *
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2004 - 2010 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>.
+ * #L%
+ */
package org.nuiton.topia.persistence.util;
import org.nuiton.topia.persistence.TopiaEntity;
1
0
r2099 - trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util
by tchemit@users.nuiton.org 14 Aug '10
by tchemit@users.nuiton.org 14 Aug '10
14 Aug '10
Author: tchemit
Date: 2010-08-14 21:56:03 +0200 (Sat, 14 Aug 2010)
New Revision: 2099
Url: http://nuiton.org/repositories/revision/topia/2099
Log:
transfer usefull methods from replication service (must do javadoc + i18n)
Modified:
trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java
Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java 2010-08-14 13:54:40 UTC (rev 2098)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java 2010-08-14 19:56:03 UTC (rev 2099)
@@ -29,6 +29,7 @@
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.TopiaContext;
import org.nuiton.topia.TopiaException;
+import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaDAO;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
@@ -55,6 +56,8 @@
import java.util.SortedMap;
import java.util.TreeMap;
+import static org.nuiton.i18n.I18n._;
+
/**
* Une classe avec des méthodes utiles sur les entités.
*
@@ -1077,4 +1080,92 @@
}
interfaces.add(klass);
}
+
+ @SuppressWarnings({"unchecked"})
+ public static <E extends TopiaEntity> List<E> getEntities(
+ TopiaContextImplementor srcCtxt,
+ List<E> entityList,
+ boolean canBeNull) throws TopiaException {
+ List<E> srcList = new ArrayList<E>(entityList.size());
+ for (E e : entityList) {
+ E e2 = (E) srcCtxt.findByTopiaId(e.getTopiaId());
+ if (e2 == null && !canBeNull) {
+// if (!canBeNull) {
+// throw new IllegalStateException(
+// "topia.replication.engine.error.entity.must.exists");
+// }
+ continue;
+ }
+ srcList.add(e2);
+ }
+ return srcList;
+ }
+
+ public static TopiaEntity[] getEntities(TopiaContext srcCtxt,
+ String... entityList)
+ throws TopiaException {
+ TopiaEntity[] srcList = new TopiaEntity[entityList.length];
+ int index = 0;
+ for (String id : entityList) {
+ TopiaEntity e2 = srcCtxt.findByTopiaId(id);
+ srcList[index++] = e2;
+ }
+ return srcList;
+ }
+
+ public static List<? extends TopiaEntity> getEntitiesList(
+ TopiaContext srcCtxt,
+ String... entityList) throws TopiaException {
+ List<TopiaEntity> srcList = new ArrayList<TopiaEntity>(entityList.length);
+ for (String id : entityList) {
+ TopiaEntity e2 = srcCtxt.findByTopiaId(id);
+ srcList.add(e2);
+ }
+ return srcList;
+ }
+
+ public static void checkNotNull(String methodName,
+ String parameterName,
+ Object value) {
+ if (value == null) {
+ throw new NullPointerException(
+ _("topia.replication.engine.error.null.param",
+ parameterName, methodName));
+ }
+ }
+
+ public static void checkParameters(Class<?>[] paramsType,
+ Object... params) {
+ checkSize(paramsType.length, params);
+ for (int i = 0, j = paramsType.length; i < j; i++) {
+ checkType(paramsType, i, params);
+ }
+ }
+
+ public static void checkSize(int size, Object[] params) {
+ if (params.length != size) {
+ throw new IllegalArgumentException(
+ "l'operation requiere " + size + " parametres mais en a " +
+ params.length);
+ }
+ }
+
+ public static void checkType(Class<?>[] paramsType,
+ int index,
+ Object[] params) {
+ Class<?> requiredType = paramsType[index];
+ Object value = params[index];
+ if (value == null) {
+ throw new IllegalArgumentException(
+ "le parametre de positiion" + index + " est null!");
+ }
+ Class<?> foundType = value.getClass();
+
+ if (!requiredType.isAssignableFrom(foundType)) {
+ throw new IllegalArgumentException(
+ "le paremetre de position " + index +
+ " requiere un parametre de type " + requiredType +
+ " mais est de type " + foundType);
+ }
+ }
}
1
0
r2098 - in trunk/topia-service-replication/src: main/java/org/nuiton/topia/replication main/java/org/nuiton/topia/replication/model main/java/org/nuiton/topia/replication/operation main/resources/META-INF/services test/java/org/nuiton/topia/replication test/java/org/nuiton/topia/replication/operation
by tchemit@users.nuiton.org 14 Aug '10
by tchemit@users.nuiton.org 14 Aug '10
14 Aug '10
Author: tchemit
Date: 2010-08-14 15:54:40 +0200 (Sat, 14 Aug 2010)
New Revision: 2098
Url: http://nuiton.org/repositories/revision/topia/2098
Log:
clean code
reformat code
add javadoc + project informations (author, since,...)
remove Dependencies-like operation
improve Engine code
use TopiaEntityIdsMap
Removed:
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachDependency.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachDependency.java
Modified:
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperation.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationNode.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationDef.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationPhase.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java
trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java
trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java
trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/ReplicationEngine.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -33,6 +33,7 @@
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
@@ -40,9 +41,7 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
@@ -51,11 +50,12 @@
/**
* Implantation du service de replication.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class ReplicationEngine implements TopiaReplicationImplementor {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(ReplicationEngine.class);
/** le contexte sur la base source de la replication */
@@ -67,7 +67,7 @@
*
* @see #preInit(TopiaContextImplementor)
*/
- protected static TopiaReplicationOperation[] operations;
+ protected TopiaReplicationOperation[] operations;
//--------------------------------------------------------------------------
//-- TopiaService implementation -------------------------------------------
@@ -87,24 +87,22 @@
@Override
public boolean preInit(TopiaContextImplementor context) {
if (operations == null) {
+ // chargement des operations disponibles une seule fois
- // on effectue cette rechercher une seule fois par jvm
- synchronized (this) {
- // chargement des operations disponibles une seule fois
+ ServiceLoader<TopiaReplicationOperation> loader =
+ ServiceLoader.load(TopiaReplicationOperation.class);
- ServiceLoader<TopiaReplicationOperation> loader = ServiceLoader.load(TopiaReplicationOperation.class);
+ List<TopiaReplicationOperation> operations =
+ new ArrayList<TopiaReplicationOperation>();
- List<TopiaReplicationOperation> discoveredOperations = new ArrayList<TopiaReplicationOperation>();
-
- for (TopiaReplicationOperation op : loader) {
- if (log.isDebugEnabled()) {
- log.debug("detected operation " + op);
- }
- discoveredOperations.add(op);
-
+ for (TopiaReplicationOperation op : loader) {
+ if (log.isDebugEnabled()) {
+ log.debug("detected operation " + op);
}
- operations = discoveredOperations.toArray(new TopiaReplicationOperation[discoveredOperations.size()]);
+ operations.add(op);
}
+ this.operations = operations.toArray(
+ new TopiaReplicationOperation[operations.size()]);
}
return true;
}
@@ -127,7 +125,8 @@
//--------------------------------------------------------------------------
@Override
- public ReplicationModel prepare(TopiaEntityEnum[] contracts, String... entities) throws TopiaException {
+ public ReplicationModel prepare(TopiaEntityEnum[] contracts,
+ String... entities) throws TopiaException {
ReplicationModel model = createModel(contracts, entities);
initModel(model, true);
@@ -145,7 +144,8 @@
}
@Override
- public ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts, String... topiaIds) throws TopiaException {
+ public ReplicationModel prepareWithComputedOrder(TopiaEntityEnum[] contracts,
+ String... topiaIds) throws TopiaException {
ReplicationModel model = createModelWithComputedOrder(contracts, topiaIds);
initModel(model, false);
@@ -154,24 +154,41 @@
}
@Override
- public void addBeforeOperation(ReplicationModel model, TopiaEntityEnum type, Class<? extends TopiaReplicationOperation> operationClass, Object... parameters) {
- createOperation(model, type, ReplicationOperationPhase.before, operationClass, parameters);
+ public void addBeforeOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ createOperation(model,
+ type,
+ ReplicationOperationPhase.before,
+ operationClass,
+ parameters
+ );
}
@Override
- public void addAfterOperation(ReplicationModel model, TopiaEntityEnum type, Class<? extends TopiaReplicationOperation> operationClass, Object... parameters) {
- createOperation(model, type, ReplicationOperationPhase.after, operationClass, parameters);
+ public void addAfterOperation(ReplicationModel model,
+ TopiaEntityEnum type,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... parameters) {
+ createOperation(model,
+ type,
+ ReplicationOperationPhase.after,
+ operationClass,
+ parameters
+ );
}
@Override
- public void doReplicate(ReplicationModel model, TopiaContext dstCtxt) throws Exception {
+ public void doReplicate(ReplicationModel model,
+ TopiaContext dstCtxt) throws Exception {
checkNotNull("doReplicate", "model", model);
checkNotNull("doReplicate", "dstCtxt", dstCtxt);
TopiaContextImplementor srcCtxt = null;
- Map<Class<? extends TopiaEntity>, List<String>> data = null;
+ TopiaEntityIdsMap data = null;
// keep the list of treated nodes (to roolback them if something
// is wrong).
@@ -205,7 +222,17 @@
try {
doReplicateNode(node, srcCtxt, tx, data, treated);
} catch (Exception e) {
- tx.rollbackTransaction();
+
+ // un erreur est survenu sur le noeud de réplication
+ // on rollback la transaction de ce noeud
+ try {
+ tx.rollbackTransaction();
+ } finally {
+
+ // on revert les noeuds deja commite
+ doRollback(model, data, treated, dstCtxt);
+ }
+
throw e;
} finally {
srcCtxt.closeContext();
@@ -236,34 +263,95 @@
}
}
+ @Override
+ public void doRollback(ReplicationModel model,
+ TopiaEntityIdsMap data,
+ List<ReplicationNode> nodes,
+ TopiaContext dstCtxt) throws Exception {
+ if (nodes.isEmpty()) {
+
+ // aucun noeud de réplication commités
+ return;
+ }
+
+ TopiaContextImplementor srcCtxt;
+
+ TopiaContext tx;
+
+ boolean needTransaction = true;
+
+ log.info("Will rollback " + nodes.size() + " nodes...");
+
+ for (ReplicationNode node : nodes) {
+
+ log.info("Rollback node " + node);
+ srcCtxt = (TopiaContextImplementor) context.beginTransaction();
+
+ if (needTransaction) {
+ tx = dstCtxt.beginTransaction();
+ } else {
+ tx = dstCtxt;
+ }
+ try {
+ doRollbackNode(node, srcCtxt, tx, data);
+ } catch (Exception e) {
+
+ // un erreur est survenu sur le noeud de réplication
+ // on rollback la transaction de ce noeud
+
+ tx.rollbackTransaction();
+
+ } finally {
+ srcCtxt.rollbackTransaction();
+ srcCtxt.closeContext();
+
+ if (needTransaction) {
+ // on doit fermer la transaction car on l'a ouverte dans
+ // cette méthode, sinon c'est de la responsabilite du
+ // code appellant
+ tx.closeContext();
+ }
+ }
+
+ }
+ }
+
//--------------------------------------------------------------------------
//-- TopiaReplicationImplementor implementation ----------------------------
//--------------------------------------------------------------------------
@Override
public ReplicationModel createModel(TopiaEntityEnum[] contracts,
- String... topiaIds) throws TopiaException {
- Set<Class<? extends TopiaEntity>> detectTypes = detectTypes(contracts, topiaIds);
- ReplicationModel model = new ReplicationModel(contracts, detectTypes, topiaIds);
+ String... topiaIds)
+ throws TopiaException {
+
+ Set<Class<? extends TopiaEntity>> detectTypes =
+ detectTypes(contracts, topiaIds);
+ ReplicationModel model =
+ new ReplicationModel(contracts, detectTypes, topiaIds);
return model;
}
@Override
- public ReplicationModel createModelWithComputedOrder(TopiaEntityEnum[] contracts,
- String... topiaIds) throws TopiaException {
- ReplicationModel model = new ReplicationModel(contracts, false, topiaIds);
+ public ReplicationModel createModelWithComputedOrder(
+ TopiaEntityEnum[] contracts, String... topiaIds)
+ throws TopiaException {
+ ReplicationModel model =
+ new ReplicationModel(contracts, false, topiaIds);
return model;
}
@Override
- public ReplicationModel createModelForAll(TopiaEntityEnum[] contracts) throws TopiaException {
+ public ReplicationModel createModelForAll(TopiaEntityEnum[] contracts)
+ throws TopiaException {
ReplicationModel model = new ReplicationModel(contracts, true);
return model;
}
@Override
public ReplicationModel initModel(ReplicationModel model,
- boolean computeOrder) throws TopiaException {
+ boolean computeOrder)
+ throws TopiaException {
checkNotNull("initModel", "model", model);
model.detectAssociations();
@@ -278,7 +366,8 @@
}
@Override
- public TopiaReplicationOperation getOperation(Class<? extends TopiaReplicationOperation> operationClass) {
+ public TopiaReplicationOperation getOperation(
+ Class<? extends TopiaReplicationOperation> operationClass) {
checkNotNull("getOperation", "operationClass", operationClass);
if (operations == null) {
@@ -310,24 +399,35 @@
TopiaReplicationOperation operation = getOperation(operationClass);
if (operation == null) {
- throw new IllegalArgumentException(_("topia.replication.engine.error.unkown.operation", operationClass.getSimpleName(), Arrays.toString(operations)));
+ throw new IllegalArgumentException(
+ _("topia.replication.engine.error.unkown.operation",
+ operationClass.getSimpleName(),
+ Arrays.toString(operations))
+ );
}
ReplicationNode node = model.getNode(type);
if (node == null) {
- throw new IllegalArgumentException(_("topia.replication.engine.error.unkown.owner.node", type, operationClass.getSimpleName(), model.getNodes()));
+ throw new IllegalArgumentException(
+ _("topia.replication.engine.error.unkown.owner.node",
+ type,
+ operationClass.getSimpleName(),
+ model.getNodes())
+ );
}
operation.register(model, node, phase, parameters);
}
@Override
- public Set<Class<? extends TopiaEntity>> detectTypes(TopiaEntityEnum[] contracts, String... ids) throws TopiaException {
+ public Set<Class<? extends TopiaEntity>> detectTypes(
+ TopiaEntityEnum[] contracts, String... ids) throws TopiaException {
TopiaContext ctxt = context.beginTransaction();
try {
TopiaEntity[] entities = getEntities(ctxt, ids);
// on detecte tous les types connus pour les entites données
- Set<Class<? extends TopiaEntity>> types = TopiaEntityHelper.detectTypes(contracts, entities);
+ Set<Class<? extends TopiaEntity>> types =
+ TopiaEntityHelper.detectTypes(contracts, entities);
if (log.isDebugEnabled()) {
log.debug("for type : " + entities.getClass());
@@ -342,21 +442,33 @@
}
@Override
- public Map<Class<? extends TopiaEntity>, List<String>> getIds(ReplicationModel model, TopiaContextImplementor srcCtxt) throws TopiaException {
- Map<Class<? extends TopiaEntity>, List<String>> data;
+ public TopiaEntityIdsMap getIds(ReplicationModel model,
+ TopiaContextImplementor srcCtxt)
+ throws TopiaException {
+
+ TopiaEntityIdsMap data;
+
// on recupere les objets a repliquer par type
if (model.isReplicateAll()) {
+
// on recupere pour chaque type tous les ids des entites a repliquer
- data = new HashMap<Class<? extends TopiaEntity>, List<String>>();
+ data = new TopiaEntityIdsMap();
for (TopiaEntityEnum e : model.getContracts()) {
List<String> ids = srcCtxt.getDAO(e.getContract()).findAllIds();
data.put(e.getContract(), ids);
}
} else {
+
// on recupere les entites specifies a repliquer
- TopiaEntity[] entities = getEntities(srcCtxt, model.getTopiaIds());
+ TopiaEntity[] entities = getEntities(srcCtxt,
+ model.getTopiaIds()
+ );
+
// on calcule toutes les ids des entites a repliquer
- data = TopiaEntityHelper.detectEntityIds(model.getContracts(), model.getTypes(), entities);
+ data = TopiaEntityHelper.detectEntityIds(model.getContracts(),
+ model.getTypes(),
+ entities
+ );
}
return data;
}
@@ -366,10 +478,11 @@
ReplicationNode node,
TopiaContext srcCtxt,
TopiaContext dstCtxt,
- Map<Class<? extends TopiaEntity>, List<String>> data,
+ TopiaEntityIdsMap data,
List<ReplicationNode> treated) throws Exception {
- // on trie toujours les operations a realiser selon leur phase (avant ou apres la duplication)
+ // on trie toujours les operations a realiser selon leur phase
+ // (avant ou apres la duplication)
node.sortOperations();
List<ReplicationOperationDef> operationDefs = node.getOperations();
@@ -378,11 +491,15 @@
log.info("skip node " + node + " - no operation detected.");
} else {
- log.info("start for " + node + " : " + operationDefs.size() + " operation(s)");
+ log.info("start for " + node + " : " + operationDefs.size() +
+ " operation(s)");
- List<String> nodeEntityIds = data.get(node.getContract().getContract());
+ List<String> nodeEntityIds =
+ data.get(node.getContract().getContract());
+
if (log.isInfoEnabled()) {
- log.info("will replicate on " + nodeEntityIds.size() + " entity(ies)");
+ log.info("will replicate on " + nodeEntityIds.size() +
+ " entity(ies)");
}
if (log.isDebugEnabled()) {
for (String id : nodeEntityIds) {
@@ -390,7 +507,10 @@
}
}
- List<? extends TopiaEntity> nodeEntities = getEntitiesList(srcCtxt, nodeEntityIds.toArray(new String[nodeEntityIds.size()]));
+ List<? extends TopiaEntity> nodeEntities = getEntitiesList(
+ srcCtxt,
+ nodeEntityIds.toArray(new String[nodeEntityIds.size()])
+ );
for (ReplicationOperationDef operationDef : operationDefs) {
@@ -417,14 +537,80 @@
treated.add(node);
}
- public static <E extends TopiaEntity> List<E> getEntities(TopiaContextImplementor srcCtxt, List<E> entityList, boolean canBeNull) throws TopiaException {
+
+ @Override
+ public void doRollbackNode(
+ ReplicationNode node,
+ TopiaContext srcCtxt,
+ TopiaContext dstCtxt,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // on trie toujours les operations a realiser selon leur phase
+ // (avant ou apres la duplication)
+ node.sortOperations();
+
+ List<ReplicationOperationDef> operationDefs = node.getOperations();
+
+ if (operationDefs.isEmpty()) {
+ log.info("skip node " + node + " - no operation detected.");
+ } else {
+
+ log.info("start for " + node + " : " + operationDefs.size() +
+ " operation(s)");
+
+ List<String> nodeEntityIds =
+ data.get(node.getContract().getContract());
+ if (log.isInfoEnabled()) {
+ log.info("will replicate on " + nodeEntityIds.size() +
+ " entity(ies)");
+ }
+ if (log.isDebugEnabled()) {
+ for (String id : nodeEntityIds) {
+ log.debug(id);
+ }
+ }
+
+ List<? extends TopiaEntity> nodeEntities = getEntitiesList(
+ srcCtxt,
+ nodeEntityIds.toArray(new String[nodeEntityIds.size()])
+ );
+
+ for (ReplicationOperationDef operationDef : operationDefs) {
+
+ log.info("start " + operationDef);
+
+ TopiaReplicationOperation operation =
+ getOperation(operationDef.getOperationClass());
+
+ operation.rollback(operationDef,
+ (TopiaContextImplementor) srcCtxt,
+ (TopiaContextImplementor) dstCtxt,
+ nodeEntities,
+ data
+ );
+
+ }
+ // on rollback le context source (car on a peut-etre modifie
+ // des associations ou des dependances mais on ne veut rien
+ // retenir au niveau d'hibernate, sinon on s'expose a des erreurs
+ // lorsque l'on veut recharger des objets dans le context...)
+ srcCtxt.rollbackTransaction();
+ }
+ }
+
+ @SuppressWarnings({"unchecked"})
+ public static <E extends TopiaEntity> List<E> getEntities(
+ TopiaContextImplementor srcCtxt,
+ List<E> entityList,
+ boolean canBeNull) throws TopiaException {
List<E> srcList = new ArrayList<E>(entityList.size());
for (E e : entityList) {
E e2 = (E) srcCtxt.findByTopiaId(e.getTopiaId());
if (e2 == null && !canBeNull) {
- if (!canBeNull) {
- throw new IllegalStateException("topia.replication.engine.error.entity.must.exists");
- }
+// if (!canBeNull) {
+// throw new IllegalStateException(
+// "topia.replication.engine.error.entity.must.exists");
+// }
continue;
}
srcList.add(e2);
@@ -432,7 +618,9 @@
return srcList;
}
- public static TopiaEntity[] getEntities(TopiaContext srcCtxt, String... entityList) throws TopiaException {
+ public static TopiaEntity[] getEntities(TopiaContext srcCtxt,
+ String... entityList)
+ throws TopiaException {
TopiaEntity[] srcList = new TopiaEntity[entityList.length];
int index = 0;
for (String id : entityList) {
@@ -442,7 +630,9 @@
return srcList;
}
- public static List<? extends TopiaEntity> getEntitiesList(TopiaContext srcCtxt, String... entityList) throws TopiaException {
+ public static List<? extends TopiaEntity> getEntitiesList(
+ TopiaContext srcCtxt,
+ String... entityList) throws TopiaException {
List<TopiaEntity> srcList = new ArrayList<TopiaEntity>(entityList.length);
for (String id : entityList) {
TopiaEntity e2 = srcCtxt.findByTopiaId(id);
@@ -451,13 +641,18 @@
return srcList;
}
- public static void checkNotNull(String methodName, String parameterName, Object value) {
+ public static void checkNotNull(String methodName,
+ String parameterName,
+ Object value) {
if (value == null) {
- throw new NullPointerException(_("topia.replication.engine.error.null.param", parameterName, methodName));
+ throw new NullPointerException(
+ _("topia.replication.engine.error.null.param",
+ parameterName, methodName));
}
}
- public static void checkParameters(Class<?>[] paramsType, Object... params) {
+ public static void checkParameters(Class<?>[] paramsType,
+ Object... params) {
checkSize(paramsType.length, params);
for (int i = 0, j = paramsType.length; i < j; i++) {
checkType(paramsType, i, params);
@@ -466,20 +661,28 @@
public static void checkSize(int size, Object[] params) {
if (params.length != size) {
- throw new IllegalArgumentException("l'operation requiere " + size + " parametres mais en a " + params.length);
+ throw new IllegalArgumentException(
+ "l'operation requiere " + size + " parametres mais en a " +
+ params.length);
}
}
- public static void checkType(Class<?>[] paramsType, int index, Object[] params) {
+ public static void checkType(Class<?>[] paramsType,
+ int index,
+ Object[] params) {
Class<?> requiredType = paramsType[index];
Object value = params[index];
if (value == null) {
- throw new IllegalArgumentException("le parametre de positiion" + index + " est null!");
+ throw new IllegalArgumentException(
+ "le parametre de positiion" + index + " est null!");
}
Class<?> foundType = value.getClass();
if (!requiredType.isAssignableFrom(foundType)) {
- throw new IllegalArgumentException("le paremetre de position " + index + " requiere un parametre de type " + requiredType + " mais est de type " + foundType);
+ throw new IllegalArgumentException(
+ "le paremetre de position " + index +
+ " requiere un parametre de type " + requiredType +
+ " mais est de type " + foundType);
}
}
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationImplementor.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -41,19 +41,19 @@
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
import java.util.Set;
/**
* Class used internaly in framework, when you want implement new replication
* engin, you must used this interface
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
* @since 2.2.0
*/
public interface TopiaReplicationImplementor extends TopiaReplicationService {
@@ -136,11 +136,13 @@
* @return les ids des donnes a repliquer.
* @throws TopiaException pour toute erreur de recuperation d'ids en base
*/
- Map<Class<? extends TopiaEntity>, List<String>> getIds(
+ TopiaEntityIdsMap getIds(
ReplicationModel model,
TopiaContextImplementor srcCtxt) throws TopiaException;
/**
+ * Lance la replication d'un noeud.
+ *
* @param node le noeud de replication
* @param srcCtxt la base source
* @param dstCtxt la base destination
@@ -152,6 +154,22 @@
ReplicationNode node,
TopiaContext srcCtxt,
TopiaContext dstCtxt,
- Map<Class<? extends TopiaEntity>, List<String>> data,
+ TopiaEntityIdsMap data,
List<ReplicationNode> treated) throws Exception;
+
+ /**
+ * Annule la replication d'un noeud.
+ *
+ * @param node le noeud de replication
+ * @param srcCtxt la base source
+ * @param dstCtxt la base destination
+ * @param data le dictionnaire des ids a repliquer
+ * @throws Exception pour toute erreur
+ * @since 2.4.3
+ */
+ void doRollbackNode(
+ ReplicationNode node,
+ TopiaContext srcCtxt,
+ TopiaContext dstCtxt,
+ TopiaEntityIdsMap data) throws Exception;
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperation.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationOperation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -28,13 +28,13 @@
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
import java.util.ServiceLoader;
/**
@@ -53,7 +53,7 @@
* <p/>
* Lors du chargement du service, on detecte toutes les operations disponibles.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
* @since 2.2.0
*/
public interface TopiaReplicationOperation {
@@ -92,5 +92,24 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> entities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws Exception;
+ TopiaEntityIdsMap data) throws Exception;
+
+ /**
+ * Execute l'operation inverse avec le parametrage donnee
+ * (pour annuler l'opération).
+ * <p/>
+ * Note : le commit sur le context cible doit etre geree dans la methode.
+ *
+ * @param operationDef la definition de l'operation a realiser
+ * @param srcCtxt le context source
+ * @param dstCtxt le context destination
+ * @param entities la liste des
+ * @param data le dictionnaire de toutes les donnees a repliquer
+ * @throws Exception pour toute erreur
+ */
+ void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception;
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/TopiaReplicationService.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -40,8 +40,12 @@
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaService;
import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.model.ReplicationModel;
+import org.nuiton.topia.replication.model.ReplicationNode;
+import java.util.List;
+
/**
* User visible interface for replication engin
* <p/>
@@ -57,7 +61,7 @@
* <li> - lanch replication {@link #doReplicate(ReplicationModel,
* TopiaContext)}
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
* @since 2.2.0
*/
public interface TopiaReplicationService extends TopiaService {
@@ -148,7 +152,22 @@
* @param dstCtxt le context sur la source de donnees ou repliquer
* @throws Exception pour toute erreur pendant la replication
*/
- void doReplicate(ReplicationModel model, TopiaContext dstCtxt) throws Exception;
+ void doReplicate(ReplicationModel model,
+ TopiaContext dstCtxt) throws Exception;
+
+ /**
+ * Pour revenir en arrière lorsque la réplication a échouée .
+ *
+ * @param model le modele de replication
+ * @param data le dictionnaire des données à repliquer par type d'entités
+ * @param nodes les nodes déjà traités que l'on doit reverter
+ * @param dstCtxt le context sur la source de donnees ou repliquer
+ * @throws Exception pour toute erreur pendant la replication
+ */
+ void doRollback(ReplicationModel model,
+ TopiaEntityIdsMap data,
+ List<ReplicationNode> nodes,
+ TopiaContext dstCtxt) throws Exception;
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/Link.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -32,21 +32,34 @@
/**
* Pour definir un lien entre deux entites (deux noeuds de replication).
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class Link {
+ /** le noeud source du lien */
protected final ReplicationNode source;
+ /** le noeud destination du lien */
+ protected final ReplicationNode target;
+
+ /**
+ * liste des noeuds requis.
+ * <p/>
+ * TODO tchemit 2010-08-14 Expliquer à quoi ça sert vraiment...
+ */
protected final Set<ReplicationNode> requires;
- protected final ReplicationNode target;
-
+ /** nom du lien */
protected final String name;
+ /** drapeau positionné à {@code true} lorsque le lien est une association. */
protected final boolean association;
- public Link(ReplicationNode source, ReplicationNode target, String name, boolean association) {
+ public Link(ReplicationNode source,
+ ReplicationNode target,
+ String name,
+ boolean association) {
this.source = source;
this.target = target;
this.name = name;
@@ -87,7 +100,8 @@
* @param currentNode le noeud qui vient d'etre replique
* @return <code>true</code> si on peut reattacher ce lien
*/
- public boolean canReattach(Set<ReplicationNode> universe, ReplicationNode currentNode) {
+ public boolean canReattach(Set<ReplicationNode> universe,
+ ReplicationNode currentNode) {
boolean result = universe.containsAll(requires);
if (result) {
result = currentNode.equals(target) || universe.contains(target);
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationModel.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -32,6 +32,7 @@
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.operation.AttachLink;
import org.nuiton.topia.replication.operation.DettachAssociation;
@@ -49,9 +50,15 @@
import java.util.Map.Entry;
import java.util.Set;
+/**
+ * Model of a replication operation.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
public class ReplicationModel {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(ReplicationModel.class);
/** l'ensemble des contrats d'entites a repliquer */
@@ -159,7 +166,7 @@
public void detectAssociations(TopiaEntityEnum... filter) throws TopiaException {
for (Class<? extends TopiaEntity> type : nodes.keySet()) {
ReplicationNode node = getNode(type);
- EntityOperator<? extends TopiaEntity> operator = node.getOperator();
+ EntityOperator<? super TopiaEntity> operator = node.getOperator();
List<String> associationProperties = operator.getAssociationProperties();
if (!associationProperties.isEmpty()) {
@@ -179,7 +186,7 @@
public void detectDirectDependencies() throws TopiaException {
for (Class<? extends TopiaEntity> type : nodes.keySet()) {
ReplicationNode node = getNode(type);
- EntityOperator<? extends TopiaEntity> operator = node.getOperator();
+ EntityOperator<? super TopiaEntity> operator = node.getOperator();
List<String> properties = operator.getProperties();
if (!properties.isEmpty()) {
for (String p : properties) {
@@ -258,13 +265,16 @@
}
}
- public void detectDependenciesOrder(Set<ReplicationNode> safeLevel, Set<ReplicationNode> doned) {
+ public void detectDependenciesOrder(Set<ReplicationNode> safeLevel,
+ Set<ReplicationNode> doned) {
if (log.isDebugEnabled()) {
log.debug("will detect " + safeLevel);
}
- Map<ReplicationNode, Set<ReplicationNode>> dico = new HashMap<ReplicationNode, Set<ReplicationNode>>();
+ Map<ReplicationNode, Set<ReplicationNode>> dico =
+ new HashMap<ReplicationNode, Set<ReplicationNode>>();
for (ReplicationNode n : safeLevel) {
- Set<ReplicationNode> shell = new HashSet<ReplicationNode>(n.getShell());
+ Set<ReplicationNode> shell =
+ new HashSet<ReplicationNode>(n.getShell());
shell.retainAll(safeLevel);
if (log.isDebugEnabled()) {
log.debug("shell to use for " + n + " : " + shell);
@@ -411,7 +421,8 @@
Set<String> names = node.getAssociationsToDettach();
// operations de dettachement d'association
for (String name : names) {
- addOperation(node, node, ReplicationOperationPhase.before, DettachAssociation.class, name);
+// addOperation(node, node, ReplicationOperationPhase.before, DettachAssociation.class, name);
+ addPreOperation(node, node, DettachAssociation.class, name);
}
}
Set<Link> tmpLinks = new HashSet<Link>();
@@ -426,26 +437,17 @@
if (!tmpLinks.isEmpty()) {
// on a des associations a charger avant replication
for (Link link : tmpLinks) {
- ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.before, LoadLink.class, node, link);
- node.addOperation(op);
+ addPreOperation(node, node, LoadLink.class, link);
+// ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.before, LoadLink.class, node, link);
+// node.addOperation(op);
}
linksToLoad.removeAll(links);
tmpLinks.clear();
}
- // on fait de meme pour les dependences directes
- //TODO la resolution des conflits sur dependences n'est pas encore
- //TODO en place (mais cela ne devrait pas etre necessaire... pour le moment)
-
-// if (node.hasDependenciesToDettach()) {
-// Set<String> names = node.getDependenciesToDettach();
-// // operations de dettachement d'association
-// for (String name : names) {
-// addOperation(node, node, ReplicationOperationPhase.before, DettachDependency.class, name);
-// }
-// }
// operation de duplication
- addOperation(node, node, ReplicationOperationPhase.duplicate, Duplicate.class);
+// addOperation(node, node, ReplicationOperationPhase.duplicate, Duplicate.class);
+ addDuplicateOperation(node, node, Duplicate.class);
universe.add(node);
@@ -459,8 +461,9 @@
if (!tmpLinks.isEmpty()) {
// on a trouve des liens a reattacher
for (Link link : tmpLinks) {
- ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.after, AttachLink.class, node, link);
- node.addOperation(op);
+ addPostOperation(node, node, AttachLink.class, link);
+// ReplicationOperationDef op = new ReplicationOperationDef(ReplicationOperationPhase.after, AttachLink.class, node, link);
+// node.addOperation(op);
}
// ces liens ne sont plus a traiter
links.removeAll(tmpLinks);
@@ -468,7 +471,7 @@
}
}
- public void adjustOperations(Map<Class<? extends TopiaEntity>, List<String>> data) {
+ public void adjustOperations(TopiaEntityIdsMap data) {
for (TopiaEntityEnum e : getContracts()) {
Class<? extends TopiaEntity> contract = e.getContract();
List<String> ids = data.get(contract);
@@ -518,7 +521,32 @@
}
}
- protected void addOperation(ReplicationNode ownerNode, ReplicationNode node, ReplicationOperationPhase phase, Class<? extends TopiaReplicationOperation> operationClass, Object... params) {
+ protected void addPreOperation(ReplicationNode ownerNode,
+ ReplicationNode node,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
+ addOperation(ownerNode, node, ReplicationOperationPhase.before, operationClass, params);
+ }
+
+ protected void addDuplicateOperation(ReplicationNode ownerNode,
+ ReplicationNode node,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
+ addOperation(ownerNode, node, ReplicationOperationPhase.duplicate, operationClass, params);
+ }
+
+ protected void addPostOperation(ReplicationNode ownerNode,
+ ReplicationNode node,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
+ addOperation(ownerNode, node, ReplicationOperationPhase.after, operationClass, params);
+ }
+
+ protected void addOperation(ReplicationNode ownerNode,
+ ReplicationNode node,
+ ReplicationOperationPhase phase,
+ Class<? extends TopiaReplicationOperation> operationClass,
+ Object... params) {
ReplicationOperationDef op = new ReplicationOperationDef(phase, operationClass, node, params);
ownerNode.addOperation(op);
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationNode.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationNode.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationNode.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -42,42 +42,52 @@
import java.util.Set;
/**
- * Le modele d'un noeud de replication.
+ * Model of a replication's node.
* <p/>
- * Un noeud represente exactement un type d'entite a repliquer
+ * The invariant of a replication's node is his {@link #contract}, means the
+ * type of entity to replicate.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class ReplicationNode {
- /** to use log facility, just put in your code: log.info(\"...\"); */
+ /** Logger */
private static final Log log = LogFactory.getLog(ReplicationNode.class);
+ /** contract of entity of the node. */
final TopiaEntityEnum contract;
+ /** entity operator. */
final EntityOperator<? super TopiaEntity> operator;
- /** les couples d'association a partir de ce noeud */
+ /** shell of the node. */
+ Set<ReplicationNode> shell;
+
+ /**
+ * dictionnary of associations defined on the node (keys are association
+ * name, and values are target node).
+ */
Map<String, ReplicationNode> associations;
- /** les couples de composition a partir de ce noeud */
+ /** names of association to dettach while replication. */
+ Set<String> associationsToDettach;
+
+ /**
+ * compositions defined on the node (keys are association name,
+ * and values are target node).
+ */
Map<String, ReplicationNode> dependencies;
- /** l'ensemble des associations a dettacher pendant la replication */
- Set<String> associationsToDettach;
-
- /** l'ensemble des dependences a dettacher pendant la replication */
+ /** names of dependency to dettach while replication. */
Set<String> dependenciesToDettach;
- /** la couverture de ce noeud */
- Set<ReplicationNode> shell;
-
- /** la sequences d'operations a realiser lors de la replication de ce node */
+ /** operations to fire when replication pass on this node. */
List<ReplicationOperationDef> operations;
public ReplicationNode(TopiaEntityEnum contract) {
this.contract = contract;
- operator = EntityOperatorStore.getOperator(contract);
+ operator = EntityOperatorStore.<TopiaEntity>getOperator(contract);
associations = new HashMap<String, ReplicationNode>();
dependencies = new HashMap<String, ReplicationNode>();
shell = new HashSet<ReplicationNode>();
@@ -123,7 +133,7 @@
Set<String> result = new HashSet<String>();
for (String name : associationsToDettach) {
ReplicationNode get = associations.get(name);
- if (get == node) {
+ if (node.equals(get)) {
result.add(name);
}
}
@@ -134,7 +144,7 @@
Set<String> result = new HashSet<String>();
for (String name : dependenciesToDettach) {
ReplicationNode get = dependencies.get(name);
- if (get == node) {
+ if (node.equals(get)) {
result.add(name);
}
}
@@ -227,6 +237,11 @@
return contract.toString();
}
+ /**
+ * {@link ReplicationOperationDef} comparator based on operation's phase.
+ *
+ * @see ReplicationOperationDef#getPhase()
+ */
public static final Comparator<ReplicationOperationDef>
OPERATION_COMPARATOR = new Comparator<ReplicationOperationDef>() {
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationDef.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationDef.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationDef.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -29,6 +29,25 @@
import java.util.Arrays;
+/**
+ * Definition of a concrete operation to execute.
+ * <p/>
+ * A such operation involves :
+ * <ul>
+ * <li>the replication node</li>
+ * <li>the replication phase</li>
+ * <li>the replication operation type</li>
+ * <li>the replication operation arguments</li>
+ * </ul>
+ * <p/>
+ * This definition is detected when building replication model.
+ * <p/>
+ * Then when starting replication, base on this definition, we can build the
+ * operation to fire.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
public class ReplicationOperationDef {
final ReplicationOperationPhase phase;
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationPhase.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationPhase.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/model/ReplicationOperationPhase.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -30,10 +30,11 @@
/**
* Une enumeration pour definir quand appliquer une operation.
* <p/>
- * L'ordre induit par cette enumeration sera utiliser pour trier les operations
+ * L'ordre induit par cette enumeration sera utilisé pour trier les operations
* a realiser sur chaque noeud de replication.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public enum ReplicationOperationPhase {
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachAssociation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -32,6 +32,7 @@
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.ReplicationEngine;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
@@ -42,7 +43,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import static org.nuiton.i18n.I18n._;
@@ -66,7 +66,8 @@
* via la methode {@link #register(ReplicationModel, ReplicationNode,
* ReplicationOperationPhase, Object...)}.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class AttachAssociation implements TopiaReplicationOperation {
@@ -84,7 +85,7 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
+ TopiaEntityIdsMap data) throws TopiaException {
String name = (String) operationDef.getParameters()[0];
Boolean reverse = (Boolean) operationDef.getParameters()[1];
@@ -229,4 +230,14 @@
dstCtxt.commitTransaction();
}
}
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // il faut dettacher les associations
+ }
}
Deleted: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachDependency.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachDependency.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachDependency.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -1,125 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication.operation;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaEntity;
-import org.nuiton.topia.replication.TopiaReplicationOperation;
-import org.nuiton.topia.replication.model.ReplicationModel;
-import org.nuiton.topia.replication.model.ReplicationNode;
-import org.nuiton.topia.replication.model.ReplicationOperationDef;
-import org.nuiton.topia.replication.model.ReplicationOperationPhase;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.nuiton.i18n.I18n._;
-
-/**
- * Pour attacher une dependance.
- * <p/>
- * TODO non implante pour le moment
- * <p/>
- * Note : cette operation est interne, et n'est pas creable par l'utilisateur
- * via la methode {@link #register(ReplicationModel, ReplicationNode,
- * ReplicationOperationPhase, Object...)}.
- *
- * @author chemit
- */
-public class AttachDependency implements TopiaReplicationOperation {
-
- private static final Log log = LogFactory.getLog(AttachDependency.class);
-
- @Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
- }
-
- @Override
- public void run(ReplicationOperationDef operationDef,
- TopiaContextImplementor srcCtxt,
- TopiaContextImplementor dstCtxt,
- List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
-
- throw new UnsupportedOperationException(_("topia.replication.operation.error.notImplemented", getClass()));
-
- //TODO non implante pour le moment
-// ReplicationNode ownerNode = operationDef.getNode();
-//
-// String[] names = (String[]) operationDef.getParameters();
-//
-// EntityOperator<? super TopiaEntity> ownerOperator = ownerNode.getOperator();
-//
-// List<? extends TopiaEntity> ownerEntities = data.get(ownerOperator.getClazz());
-//
-// if (ownerEntities == null || ownerEntities.isEmpty()) {
-// // pas de donnees a traiter
-// log.info(_("topia.replication.attachAssociation.nothing.to.do", ownerOperator));
-// return;
-// }
-//
-// boolean shouldCommit = false;
-// for (String name : names) {
-//
-// // le noeud de l'entite dont on veut reattacher des associations
-// ReplicationNode targetNode = ownerNode.getAssociations().get(name);
-//
-// List<TopiaEntity> targets = data.get(targetNode.getContract().getContract());
-// List<String> targetIds = TopiaEntityHelper.getTopiaIdList(targets);
-// targets.clear();
-//
-//
-// for (TopiaEntity src : ownerEntities) {
-//
-// // les association connues
-// TopiaEntity target = (TopiaEntity) ownerOperator.get(name, src);
-//
-// if (target == null || !targetIds.contains(target.getTopiaId())) {
-// // pas de donnees a attacher, ou pas pour ce src
-// continue;
-// }
-//
-// // l'entite cible
-// TopiaEntity dst = dstCtxt.findByTopiaId(src.getTopiaId());
-//
-// target = dstCtxt.findByTopiaId(target.getTopiaId());
-//
-// ownerOperator.set(name, dst, target);
-//
-// dst.update();
-// shouldCommit = true;
-//
-// }
-// }
-// if (shouldCommit) {
-// dstCtxt.commitTransaction();
-// }
- }
-}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/AttachLink.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -32,6 +32,7 @@
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.ReplicationEngine;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.Link;
@@ -43,7 +44,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import static org.nuiton.i18n.I18n._;
@@ -67,7 +67,8 @@
* via la methode {@link #register(ReplicationModel, ReplicationNode,
* ReplicationOperationPhase, Object...)}.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class AttachLink implements TopiaReplicationOperation {
@@ -85,7 +86,7 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
+ TopiaEntityIdsMap data) throws TopiaException {
Link link = (Link) operationDef.getParameters()[0];
@@ -217,4 +218,14 @@
dstCtxt.commitTransaction();
}
}
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // il faut dettacher les liens
+ }
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachAssociation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -31,6 +31,7 @@
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.util.EntityOperator;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
@@ -38,7 +39,6 @@
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
import static org.nuiton.i18n.I18n._;
@@ -49,7 +49,8 @@
* l'utilisateur via la methode
* {@link #register(ReplicationModel, ReplicationNode, ReplicationOperationPhase, Object...)}.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class DettachAssociation implements TopiaReplicationOperation {
@@ -67,7 +68,7 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> entities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
+ TopiaEntityIdsMap data) throws TopiaException {
String name = (String) operationDef.getParameters()[0];
@@ -84,6 +85,16 @@
operator.setNull(name, e);
}
}
+ }
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // il faut attacher les associations ? ou bien ne rien faire ?
}
}
Deleted: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachDependency.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachDependency.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/DettachDependency.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -1,90 +0,0 @@
-/*
- * #%L
- * ToPIA :: Service Replication
- *
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2004 - 2010 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>.
- * #L%
- */
-
-package org.nuiton.topia.replication.operation;
-
-import org.nuiton.topia.TopiaException;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.persistence.TopiaEntity;
-import org.nuiton.topia.replication.TopiaReplicationOperation;
-import org.nuiton.topia.replication.model.ReplicationModel;
-import org.nuiton.topia.replication.model.ReplicationNode;
-import org.nuiton.topia.replication.model.ReplicationOperationDef;
-import org.nuiton.topia.replication.model.ReplicationOperationPhase;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.nuiton.i18n.I18n._;
-
-/**
- * Pour dettacher une dependance.
- * <p/>
- * TODO Pas implante pour le moment
- * <p/>
- * Note : cette operation est interne, et n'est pas creable par
- * l'utilisateur via la methode
- * {@link #register(ReplicationModel, ReplicationNode, ReplicationOperationPhase, Object...)}.
- *
- * @author chemit
- */
-public class DettachDependency implements TopiaReplicationOperation {
-
- @Override
- public void register(ReplicationModel model, ReplicationNode ownerNode, ReplicationOperationPhase phase, Object... parameters) {
-
- throw new UnsupportedOperationException(_("topia.replication.operation.error.uncreatable", getClass()));
- }
-
- @Override
- public void run(ReplicationOperationDef operationDef,
- TopiaContextImplementor srcCtxt,
- TopiaContextImplementor dstCtxt,
- List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
-
- throw new UnsupportedOperationException(_("topia.replication.operation.error.notImplemented", getClass()));
- //TODO non implante pour le moment
-//
-// ReplicationNode node = operationDef.getNode();
-//
-// String[] names = (String[]) operationDef.getParameters();
-//
-// EntityOperator<? super TopiaEntity> operator = node.getOperator();
-//
-//// // recuperation des donnees a traiter
-//// List<TopiaEntity> entities = data.get(operator.getClazz());
-////
-//// // recuperation de la liste sur le context actuel
-//// entities = ReplicationEngine.getEntities(srcCtxt, entities, false);
-//
-// // dettach les attributs
-// for (TopiaEntity e : nodeEntities) {
-// for (String name : names) {
-// operator.setNull(name, e);
-// }
-// }
- }
-}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/Duplicate.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -28,6 +28,7 @@
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
@@ -35,7 +36,6 @@
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
import static org.nuiton.i18n.I18n._;
@@ -46,7 +46,8 @@
* l'utilisateur via la methode
* {@link #register(ReplicationModel, ReplicationNode, ReplicationOperationPhase, Object...)}.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class Duplicate implements TopiaReplicationOperation {
@@ -60,7 +61,7 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> entities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
+ TopiaEntityIdsMap data) throws TopiaException {
// replication des donnees vers la destination
srcCtxt.replicateEntities(dstCtxt, entities);
@@ -69,4 +70,15 @@
dstCtxt.commitTransaction();
}
+
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // il faut supprimer les entities
+ }
}
Modified: trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java
===================================================================
--- trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/java/org/nuiton/topia/replication/operation/LoadLink.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -31,6 +31,7 @@
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.util.EntityOperator;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.Link;
import org.nuiton.topia.replication.model.ReplicationModel;
@@ -39,7 +40,6 @@
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
import static org.nuiton.i18n.I18n._;
@@ -50,7 +50,8 @@
* l'utilisateur via la methode
* {@link #register(ReplicationModel, ReplicationNode, ReplicationOperationPhase, Object...)}.
*
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class LoadLink implements TopiaReplicationOperation {
@@ -68,7 +69,7 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data) throws TopiaException {
+ TopiaEntityIdsMap data) throws TopiaException {
Link link = (Link) operationDef.getParameters()[0];
@@ -95,4 +96,15 @@
}
}
}
+
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef,
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> entities,
+ TopiaEntityIdsMap data) throws Exception {
+
+ // rien a faire ici
+ }
}
Modified: trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation
===================================================================
--- trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/main/resources/META-INF/services/org.nuiton.topia.replication.TopiaReplicationOperation 2010-08-14 13:54:40 UTC (rev 2098)
@@ -6,6 +6,4 @@
org.nuiton.topia.replication.operation.LoadLink
org.nuiton.topia.replication.operation.AttachAssociation
org.nuiton.topia.replication.operation.DettachAssociation
-org.nuiton.topia.replication.operation.AttachDependency
-org.nuiton.topia.replication.operation.DettachDependency
org.nuiton.topia.replication.operation.Duplicate
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/AbstractReplicationEngineTest.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -57,11 +57,9 @@
* <p/>
* Created: 07 jun. 09 17:14:22
*
- * @author tchemit
- * @version $Revision$
- * <p/>
- * Last update: $Date$
- * by :
+ * @author tchemit <chemit(a)codelutin.com>
+ * @version $Id$
+ * @since 2.2.0
*/
public abstract class AbstractReplicationEngineTest extends Assert {
@@ -219,9 +217,9 @@
detectTypes = service.detectTypes(getContracts(), entity.getTopiaId());
assertEquals("expected types : " +
- Arrays.toString(expectedCouple) +
- " but was " + detectTypes,
- expectedCouple.length, detectTypes.size());
+ Arrays.toString(expectedCouple) +
+ " but was " + detectTypes,
+ expectedCouple.length, detectTypes.size());
for (Object o : expectedCouple) {
assertTrue(detectTypes.contains(o));
}
@@ -285,7 +283,7 @@
shell = model.getNode(c.getContract()).getShell();
assertEquals(
"expected shell : " + Arrays.toString(expected) + ", but was " +
- shell, expected.length, shell.size());
+ shell, expected.length, shell.size());
for (int i = 0, j = expected.length; i < j; i++) {
TopiaEntityEnum type = expected[i];
@@ -532,7 +530,7 @@
}
Assert.assertNotNull(
"contract not found for " + expected.getClass() + " in " +
- Arrays.toString(getContracts()), contract);
+ Arrays.toString(getContracts()), contract);
EntityOperator<TopiaEntity> operator = EntityOperatorStore.getOperator(contract);
List<String> associationProperties = operator.getAssociationProperties();
for (String name : associationProperties) {
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineAllTest.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -25,50 +25,57 @@
package org.nuiton.topia.replication;
-import java.io.File;
-import org.nuiton.topia.TopiaContext;
-import org.nuiton.topia.TopiaContextFactory;
-import org.nuiton.topia.framework.TopiaContextImplementor;
-import org.nuiton.topia.test.entities.*;
-import org.junit.Test;
-
-import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.Test;
+import org.nuiton.topia.TopiaContext;
+import org.nuiton.topia.TopiaContextFactory;
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.TopiaTestDAOHelper.TopiaTestEntityEnum;
+import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.TopiaEntityEnum;
+import org.nuiton.topia.test.entities.Person;
+import org.nuiton.topia.test.entities.PersonImpl;
+import org.nuiton.topia.test.entities.Pet;
+import org.nuiton.topia.test.entities.PetImpl;
+import org.nuiton.topia.test.entities.Race;
+import org.nuiton.topia.test.entities.RaceImpl;
+import java.io.File;
+import java.util.Properties;
+
/**
* ReplicationEngineTest on model TopiaTest
- *
+ * <p/>
* Created: 07 jun. 09 17:14:22
*
- * @author tchemit
- * @version $Revision$
- *
- * Last update: $Date$
- * by : */
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
public class ReplicationEngineAllTest extends AbstractReplicationEngineTest {
/** to use log facility, just put in your code: log.info(\"...\"); */
private static final Log log = LogFactory.getLog(ReplicationEngineTest.class);
+
protected static final TopiaEntityEnum[] contracts = {
TopiaTestEntityEnum.Person,
TopiaTestEntityEnum.Pet,
TopiaTestEntityEnum.Race
};
+
protected static final String entitiesList =
PersonImpl.class.getName() + "," +
PetImpl.class.getName() + "," +
RaceImpl.class.getName();
-
+
static protected Person person, person2;
+
static protected Pet pet, pet2, pet3;
+
static protected Race race, race2, race3;
@AfterClass
@@ -101,6 +108,7 @@
}
// @Ignore
+
@Test
@Override
public void testDetectTypes() throws Exception {
@@ -118,12 +126,14 @@
}
// @Ignore
+
@Test
@Override
public void testGetOperation() throws Exception {
}
// @Ignore
+
@Test
@Override
public void testDetectAssociations() throws Exception {
@@ -139,6 +149,7 @@
}
// @Ignore
+
@Test
@Override
public void testDetectDirectDependencies() throws Exception {
@@ -153,6 +164,7 @@
}
// @Ignore
+
@Test
@Override
public void testDetectShell() throws Exception {
@@ -166,15 +178,17 @@
}
// @Ignore
+
@Test
@Override
public void testDetectDependencies() throws Exception {
detectDependencies(null,
- new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
+ new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Race}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Person}, new TopiaTestEntityEnum[]{TopiaTestEntityEnum.Pet});
}
// @Ignore
+
@Test
@Override
public void testDetectObjectsToDettach() throws Exception {
@@ -183,6 +197,7 @@
}
// @Ignore
+
@Test
@Override
public void testDetectOperations() throws Exception {
@@ -191,6 +206,7 @@
}
// @Ignore
+
@Test
@Override
public void testDoReplicate() throws Exception {
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/ReplicationEngineTest.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -39,9 +39,7 @@
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.operation.AttachAssociation;
-import org.nuiton.topia.replication.operation.AttachDependency;
import org.nuiton.topia.replication.operation.DettachAssociation;
-import org.nuiton.topia.replication.operation.DettachDependency;
import org.nuiton.topia.replication.operation.Duplicate;
import org.nuiton.topia.replication.operation.FakeOperation;
import org.nuiton.topia.replication.operation.UncreatableOperation;
@@ -54,7 +52,6 @@
import org.nuiton.topia.test.entities.RaceImpl;
import java.io.File;
-import java.util.Map;
import java.util.Properties;
/**
@@ -62,11 +59,8 @@
* <p/>
* Created: 07 jun. 09 17:14:22
*
- * @author tchemit
- * @version $Revision$
- * <p/>
- * Last update: $Date$
- * by :
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class ReplicationEngineTest extends AbstractReplicationEngineTest {
@@ -138,8 +132,6 @@
getOperation(Duplicate.class, true);
getOperation(AttachAssociation.class, true);
getOperation(DettachAssociation.class, true);
- getOperation(AttachDependency.class, true);
- getOperation(DettachDependency.class, true);
}
@Test
@@ -281,7 +273,7 @@
/**
* Cette methode montre comment manuellement on peut effectuer la
- * replication (en dettachant les dependances qui forment des cyles)
+ * replication (en dettachant les dependances qui forment des cycles)
* <p/>
* La methode utilisee ici peut ne pas fonctionner : si une clef metier est
* posee sur une dependance alors cela ne fonctionne pas.
@@ -328,7 +320,7 @@
/**
* Cette methode montre comment manuellement on peut effectuer la
- * replication (en dettachant les associations qui forment des cyles)
+ * replication (en dettachant les associations qui forment des cycles)
* <p/>
* La methode utilisee ici fonctionne mieux que la precedante : il parrait
* dificille de pose une une clef metier sur une association :).
@@ -337,7 +329,7 @@
* est pas obligee de la reattachee car elle est bi-directionnelle.
* <p/>
* On doit optimiser l'algorithme dans la methode {@link
- * ReplicationModel#adjustOperations(Map)}.
+ * ReplicationModel#adjustOperations(org.nuiton.topia.persistence.util.TopiaEntityIdsMap)}.
*
* @throws Exception pour toute erreur
*/
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/TopiaReplicationOperationTest.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -38,9 +38,7 @@
import org.nuiton.topia.persistence.TopiaEntityEnum;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import org.nuiton.topia.replication.operation.AttachAssociation;
-import org.nuiton.topia.replication.operation.AttachDependency;
import org.nuiton.topia.replication.operation.DettachAssociation;
-import org.nuiton.topia.replication.operation.DettachDependency;
import org.nuiton.topia.replication.operation.Duplicate;
import org.nuiton.topia.replication.operation.FakeOperation;
import org.nuiton.topia.replication.operation.UncreatableOperation;
@@ -60,11 +58,8 @@
* <p/>
* Created: 07 jun. 09 17:14:22
*
- * @author tchemit
- * @version $Revision$
- * <p/>
- * Last update: $Date$
- * by : $Author$
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class TopiaReplicationOperationTest extends AbstractReplicationEngineTest {
@@ -109,18 +104,14 @@
}
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testGetOperation_nullOperationClass() throws Exception {
service.getOperation(null);
}
-// @Ignore
-
@Test(expected = IllegalStateException.class)
public void testGetOperation_serviceNotInit() throws Exception {
- ReplicationEngine.operations = null;
+// ReplicationEngine.operations = null;
try {
new ReplicationEngine().getOperation(Duplicate.class);
} catch (IllegalStateException e) {
@@ -134,8 +125,6 @@
}
}
-// @Ignore
-
@Test
@Override
public void testGetOperation() throws Exception {
@@ -146,19 +135,13 @@
getOperation(Duplicate.class, true);
getOperation(AttachAssociation.class, true);
getOperation(DettachAssociation.class, true);
- getOperation(AttachDependency.class, true);
- getOperation(DettachDependency.class, true);
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullModel() throws Exception {
service.createOperation(null, null, null, null);
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullType() throws Exception {
@@ -166,8 +149,6 @@
service.createOperation(model, null, null, null);
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullPhase() throws Exception {
@@ -175,8 +156,6 @@
service.createOperation(model, TopiaTestEntityEnum.Pet, null, null);
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testCreateOperation_nullOperationClass() throws Exception {
@@ -184,8 +163,6 @@
service.createOperation(model, TopiaTestEntityEnum.Pet, ReplicationOperationPhase.before, null);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_noNode() throws Exception {
@@ -194,8 +171,6 @@
service.addAfterOperation(model, TopiaTestEntityEnum.Pet, Duplicate.class);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_noOperation() throws Exception {
@@ -204,92 +179,46 @@
service.addAfterOperation(model, TopiaTestEntityEnum.Pet, UnregistredOperation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedBeforeOperation_Duplicate() throws Exception {
createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, Duplicate.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedBeforeOperation_AttachAssociation() throws Exception {
createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, AttachAssociation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedBeforeOperation_DetachAssociation() throws Exception {
createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, DettachAssociation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
- public void testCreateUnsupportedBeforeOperation_AttachDependency() throws Exception {
- createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, AttachDependency.class);
- }
-
-// @Ignore
-
- @Test(expected = UnsupportedOperationException.class)
- public void testCreateUnsupportedBeforeOperation_DetachDependency() throws Exception {
- createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, DettachDependency.class);
- }
-
-// @Ignore
-
- @Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedAfterOperation_Duplicate() throws Exception {
createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, Duplicate.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedAfterOperation_AttachAssociation() throws Exception {
createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, AttachAssociation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedAfterOperation_DetachAssociation() throws Exception {
createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, DettachAssociation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
- public void testCreateUnsupportedAfterOperation_AttachDependency() throws Exception {
- createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, AttachDependency.class);
- }
-
-// @Ignore
-
- @Test(expected = UnsupportedOperationException.class)
- public void testCreateUnsupportedAfterOperation_DetachDependency() throws Exception {
- createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, DettachDependency.class);
- }
-
-// @Ignore
-
- @Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedBeforeOperation_UncreatableOperation() throws Exception {
createUnsupportedBeforeOperation(TopiaTestEntityEnum.Person, person, UncreatableOperation.class);
}
-// @Ignore
-
@Test(expected = UnsupportedOperationException.class)
public void testCreateUnsupportedAfterOperation_UncreatableOperation() throws Exception {
createUnsupportedAfterOperation(TopiaTestEntityEnum.Person, person, UncreatableOperation.class);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterNumber() throws Exception {
@@ -297,8 +226,6 @@
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterNumber2() throws Exception {
@@ -306,8 +233,6 @@
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, String.class, String.class);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_wrongParameterType() throws Exception {
@@ -315,8 +240,6 @@
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, Integer.class);
}
-// @Ignore
-
@Test(expected = IllegalArgumentException.class)
public void testCreateOperation_nullParameter() throws Exception {
@@ -324,8 +247,6 @@
service.addBeforeOperation(model, TopiaTestEntityEnum.Pet, FakeOperation.class, (Object) null);
}
-// @Ignore
-
@Test
public void testCreateOperation() throws Exception {
@@ -334,16 +255,12 @@
service.addAfterOperation(model, TopiaTestEntityEnum.Race, FakeOperation.class, "after");
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testDoReplicate_nullModel() throws Exception {
service.doReplicate(null, null);
}
-// @Ignore
-
@Test(expected = NullPointerException.class)
public void testDoReplicate_nullDstCtxt() throws Exception {
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/FakeOperation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -25,22 +25,24 @@
package org.nuiton.topia.replication.operation;
-import org.nuiton.topia.replication.*;
-import java.util.List;
-import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
+import org.nuiton.topia.replication.ReplicationEngine;
+import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
+import java.util.List;
+
/**
- *
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class FakeOperation implements TopiaReplicationOperation {
@@ -48,7 +50,7 @@
private static final Log log = LogFactory.getLog(FakeOperation.class);
public static final Class<?>[] PARAMETERS_CLASSES = new Class<?>[]{String.class};
-
+
@Override
public void register(ReplicationModel model,
ReplicationNode ownerNode,
@@ -67,11 +69,16 @@
@Override
public void run(ReplicationOperationDef operationDef,
- TopiaContextImplementor srcCtxt,
- TopiaContextImplementor dstCtxt,
- List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data)
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> nodeEntities,
+ TopiaEntityIdsMap data)
throws TopiaException {
}
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef, TopiaContextImplementor srcCtxt, TopiaContextImplementor dstCtxt, List<? extends TopiaEntity> entities, TopiaEntityIdsMap data) throws Exception {
+ // rien a faire
+ }
}
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UncreatableOperation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -25,23 +25,25 @@
package org.nuiton.topia.replication.operation;
-import org.nuiton.topia.replication.*;
-import java.util.List;
-import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
+import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
import org.nuiton.topia.replication.model.ReplicationOperationDef;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
+
+import java.util.List;
+
import static org.nuiton.i18n.I18n._;
/**
- *
- * @author chemit
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
*/
public class UncreatableOperation implements TopiaReplicationOperation {
@@ -61,10 +63,15 @@
@Override
public void run(ReplicationOperationDef operationDef,
- TopiaContextImplementor srcCtxt,
- TopiaContextImplementor dstCtxt,
- List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data)
+ TopiaContextImplementor srcCtxt,
+ TopiaContextImplementor dstCtxt,
+ List<? extends TopiaEntity> nodeEntities,
+ TopiaEntityIdsMap data)
throws TopiaException {
}
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef, TopiaContextImplementor srcCtxt, TopiaContextImplementor dstCtxt, List<? extends TopiaEntity> entities, TopiaEntityIdsMap data) throws Exception {
+ // rien a faire
+ }
}
Modified: trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java
===================================================================
--- trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java 2010-08-14 13:53:11 UTC (rev 2097)
+++ trunk/topia-service-replication/src/test/java/org/nuiton/topia/replication/operation/UnregistredOperation.java 2010-08-14 13:54:40 UTC (rev 2098)
@@ -30,6 +30,7 @@
import org.nuiton.topia.TopiaException;
import org.nuiton.topia.framework.TopiaContextImplementor;
import org.nuiton.topia.persistence.TopiaEntity;
+import org.nuiton.topia.persistence.util.TopiaEntityIdsMap;
import org.nuiton.topia.replication.TopiaReplicationOperation;
import org.nuiton.topia.replication.model.ReplicationModel;
import org.nuiton.topia.replication.model.ReplicationNode;
@@ -37,9 +38,11 @@
import org.nuiton.topia.replication.model.ReplicationOperationPhase;
import java.util.List;
-import java.util.Map;
-/** @author chemit */
+/**
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.2.0
+ */
public class UnregistredOperation implements TopiaReplicationOperation {
/** to use log facility, just put in your code: log.info(\"...\"); */
@@ -59,7 +62,12 @@
TopiaContextImplementor srcCtxt,
TopiaContextImplementor dstCtxt,
List<? extends TopiaEntity> nodeEntities,
- Map<Class<? extends TopiaEntity>, List<String>> data)
+ TopiaEntityIdsMap data)
throws TopiaException {
}
+
+ @Override
+ public void rollback(ReplicationOperationDef operationDef, TopiaContextImplementor srcCtxt, TopiaContextImplementor dstCtxt, List<? extends TopiaEntity> entities, TopiaEntityIdsMap data) throws Exception {
+ // rien a faire
+ }
}
1
0
r2097 - trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util
by tchemit@users.nuiton.org 14 Aug '10
by tchemit@users.nuiton.org 14 Aug '10
14 Aug '10
Author: tchemit
Date: 2010-08-14 15:53:11 +0200 (Sat, 14 Aug 2010)
New Revision: 2097
Url: http://nuiton.org/repositories/revision/topia/2097
Log:
introduce a TopiaEntityIdsMap + use it + reformat code
Added:
trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java
Modified:
trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java
Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java 2010-08-11 14:47:08 UTC (rev 2096)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityHelper.java 2010-08-14 13:53:11 UTC (rev 2097)
@@ -233,7 +233,7 @@
}
log.info("create database from [" + databaseDump + "] at [" +
- dbDirectory + "]");
+ dbDirectory + "]");
TopiaContext ctxt = topiaContext.beginTransaction();
@@ -270,7 +270,7 @@
if (!gzipFile.getParentFile().exists()) {
if (!gzipFile.getParentFile().mkdirs()) {
throw new IOException("could not create directory " +
- gzipFile.getParentFile());
+ gzipFile.getParentFile());
}
}
log.info("store database to [" + gzipFile + "]");
@@ -577,19 +577,20 @@
* les entites dont le contract est dans l'ensemble voulu).
* @throws TopiaException if a pb while visiting entities
*/
- public static Map<Class<? extends TopiaEntity>, List<String>>
+ public static TopiaEntityIdsMap
detectEntityIds(final TopiaEntityEnum[] contracts,
final Set<Class<? extends TopiaEntity>> types,
TopiaEntity... entities) throws TopiaException {
- Collector<Map<Class<? extends TopiaEntity>, List<String>>> collector;
- collector = new Collector<Map<Class<? extends TopiaEntity>, List<String>>>(contracts) {
+ Collector<TopiaEntityIdsMap> collector;
+ collector = new Collector<TopiaEntityIdsMap>(contracts) {
+
/**
* le dictionnaire des références détectées indexées par leur type
*/
- protected Map<Class<? extends TopiaEntity>, List<String>> detectedRefs =
- new HashMap<Class<? extends TopiaEntity>, List<String>>();
+ protected TopiaEntityIdsMap detectedRefs =
+ new TopiaEntityIdsMap();
@Override
protected void onStarted(TopiaEntity e, boolean enter) {
@@ -614,14 +615,13 @@
}
@Override
- protected Map<Class<? extends TopiaEntity>, List<String>>
+ protected TopiaEntityIdsMap
afterAll(CollectorVisitor visitor, TopiaEntity... entities) {
return detectedRefs;
}
};
- Map<Class<? extends TopiaEntity>, List<String>> result =
- collector.detect(entities);
+ TopiaEntityIdsMap result = collector.detect(entities);
return result;
}
@@ -641,7 +641,7 @@
String[] expressions,
TopiaEntity entities) throws TopiaException {
return detectReferences(contracts, expressions,
- Collections.singleton(entities));
+ Collections.singleton(entities));
}
/**
@@ -735,7 +735,7 @@
boolean contains = visitor.getStack().contains(e1);
if (log.isDebugEnabled()) {
log.debug("already enter " + e1.getTopiaId() +
- ", can reenter ? " + !contains);
+ ", can reenter ? " + !contains);
}
if (!contains) {
try {
@@ -787,7 +787,7 @@
boolean contains = visitor.getStack().contains(e1);
if (log.isDebugEnabled()) {
log.debug("already enter " + e1.getTopiaId() +
- ", can reenter ? " + !contains);
+ ", can reenter ? " + !contains);
}
if (!contains) {
try {
@@ -815,7 +815,7 @@
Class<?> type,
int index, Object value, boolean enter) {
super.onVisited(e, name, collectionType, type, index, value,
- enter);
+ enter);
if (enter) {
removePath();
}
@@ -860,8 +860,8 @@
// }
if (log.isTraceEnabled()) {
log.trace("add to stack : " + e.getTopiaId() +
- ", new size : " + path.size() + ", path : " +
- accessorExpression.toString());
+ ", new size : " + path.size() + ", path : " +
+ accessorExpression.toString());
}
}
@@ -874,13 +874,13 @@
TopiaEntityRef.SEPARATOR);
if (index > -1) {
accessorExpression.delete(index,
- accessorExpression.length());
+ accessorExpression.length());
}
}
if (log.isTraceEnabled()) {
log.trace("remove from stack : " + e.getTopiaId() +
- ", new size : " + path.size() + ", path : " +
- accessorExpression.toString());
+ ", new size : " + path.size() + ", path : " +
+ accessorExpression.toString());
}
}
@@ -905,11 +905,11 @@
if (log.isDebugEnabled()) {
log.debug(expression + " (" + e.getTopiaId() + ") - " +
- list.size() + " , root:" + root.getTopiaId());
+ list.size() + " , root:" + root.getTopiaId());
}
if (log.isTraceEnabled()) {
log.trace(e.getTopiaId() + " : new size " + list.size() +
- ", path : " + expression);
+ ", path : " + expression);
}
}
};
@@ -995,7 +995,7 @@
}
}
boolean wasModified = referentielEntity.getTopiaVersion() >
- localeEntity.getTopiaVersion();
+ localeEntity.getTopiaVersion();
if (wasModified) {
result.get(DiffState.MODIFIED).add(refId);
@@ -1047,7 +1047,7 @@
}
if (klass.getSuperclass() != null &&
- TopiaEntity.class.isAssignableFrom(klass.getSuperclass())) {
+ TopiaEntity.class.isAssignableFrom(klass.getSuperclass())) {
getInterfaces(
(Class<? extends TopiaEntity>) klass.getSuperclass(),
klassInterfaces
Added: trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java (rev 0)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/persistence/util/TopiaEntityIdsMap.java 2010-08-14 13:53:11 UTC (rev 2097)
@@ -0,0 +1,30 @@
+package org.nuiton.topia.persistence.util;
+
+import org.nuiton.topia.persistence.TopiaEntity;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * A map of ids of entities grouped by their type.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.4.3
+ */
+public class TopiaEntityIdsMap extends HashMap<Class<? extends TopiaEntity>, List<String>> {
+ private static final long serialVersionUID = 1L;
+
+ public void addIds(Class<? extends TopiaEntity> type, Iterable<String> ids) {
+ List<String> list = get(type);
+ if (list == null) {
+ list = new ArrayList<String>();
+ put(type, list);
+ }
+ for (String id : ids) {
+ if (!list.contains(id)) {
+ list.add(id);
+ }
+ }
+ }
+}
1
0
Author: tchemit
Date: 2010-08-11 16:47:08 +0200 (Wed, 11 Aug 2010)
New Revision: 2096
Url: http://nuiton.org/repositories/revision/topia/2096
Log:
Utilisation de mavenpom4redmine 2.2.3
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2010-08-07 16:21:52 UTC (rev 2095)
+++ trunk/pom.xml 2010-08-11 14:47:08 UTC (rev 2096)
@@ -33,7 +33,7 @@
<parent>
<groupId>org.nuiton</groupId>
<artifactId>mavenpom4redmine</artifactId>
- <version>2.2.2.1</version>
+ <version>2.2.3</version>
</parent>
<artifactId>topia</artifactId>
1
0
r2095 - trunk/topia-persistence/src/main/java/org/nuiton/topia/generator
by tchemit@users.nuiton.org 07 Aug '10
by tchemit@users.nuiton.org 07 Aug '10
07 Aug '10
Author: tchemit
Date: 2010-08-07 18:21:52 +0200 (Sat, 07 Aug 2010)
New Revision: 2095
Url: http://nuiton.org/repositories/revision/topia/2095
Log:
do NOT generate BinderHelper if no entity in model
Modified:
trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java
Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java 2010-08-07 14:14:28 UTC (rev 2094)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java 2010-08-07 16:21:52 UTC (rev 2095)
@@ -25,6 +25,7 @@
package org.nuiton.topia.generator;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -58,9 +59,20 @@
private static final Log log =
LogFactory.getLog(BinderHelperTransformer.class);
+
@Override
public void transformFromModel(ObjectModel model) {
ObjectModelClass resultClass;
+
+ List<ObjectModelClass> classes = TopiaGeneratorUtil.getEntityClasses(model, true);
+
+ if (CollectionUtils.isEmpty(classes)) {
+
+ // no entity classes, so no generation
+ log.warn("No entity to generate, " + getClass().getName() + " is skipped");
+ return;
+ }
+
String packageName = getOutputProperties().getProperty(PROP_DEFAULT_PACKAGE);
String modelName = model.getName();
String binderHelperClazzName = modelName + "BinderHelper";
@@ -70,7 +82,6 @@
setSuperClass(resultClass, BinderProvider.class);
- List<ObjectModelClass> classes = TopiaGeneratorUtil.getEntityClasses(model, true);
addImport(resultClass, TopiaEntityBinder.class);
addImport(resultClass, TopiaEntityHelper.class);
1
0
r2094 - trunk/topia-persistence/src/main/java/org/nuiton/topia/generator
by tchemit@users.nuiton.org 07 Aug '10
by tchemit@users.nuiton.org 07 Aug '10
07 Aug '10
Author: tchemit
Date: 2010-08-07 16:14:28 +0200 (Sat, 07 Aug 2010)
New Revision: 2094
Url: http://nuiton.org/repositories/revision/topia/2094
Log:
format code
Modified:
trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java
Modified: trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java
===================================================================
--- trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java 2010-08-07 14:14:18 UTC (rev 2093)
+++ trunk/topia-persistence/src/main/java/org/nuiton/topia/generator/BinderHelperTransformer.java 2010-08-07 14:14:28 UTC (rev 2094)
@@ -43,7 +43,6 @@
/*{generator option: parentheses = false}*/
-
/*{generator option: writeString = +}*/
/**
1
0
Author: tchemit
Date: 2010-08-07 16:14:18 +0200 (Sat, 07 Aug 2010)
New Revision: 2093
Url: http://nuiton.org/repositories/revision/topia/2093
Log:
Evolution #802: Use eugene 2.1.2
Modified:
trunk/pom.xml
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2010-07-26 14:35:54 UTC (rev 2092)
+++ trunk/pom.xml 2010-08-07 14:14:18 UTC (rev 2093)
@@ -230,7 +230,7 @@
<projectId>topia</projectId>
<!-- libs version -->
- <eugene.version>2.1.1</eugene.version>
+ <eugene.version>2.1.2-SNAPSHOT</eugene.version>
<lutinutil.version>1.4</lutinutil.version>
<processor.version>1.0.3</processor.version>
<i18n.version>1.2.2</i18n.version>
1
0