org.nuiton.topia.replication.TopiaReplicationContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of topia-service-replication Show documentation
Show all versions of topia-service-replication Show documentation
Hibernate based replication service
package org.nuiton.topia.replication;
/*
* #%L
* ToPIA :: Service Replication
* $Id$
* $HeadURL$
* %%
* Copyright (C) 2004 - 2014 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
* .
* #L%
*/
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.persistence.TopiaApplicationContext;
import org.nuiton.topia.persistence.TopiaException;
import org.nuiton.topia.persistence.TopiaPersistenceContext;
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.Collections;
import java.util.List;
/**
* Defines the context used to replicate.
*
* It contains :
*
* - the {@link #replicationModel}
* - data sources involved ([@link #sourceTx}, {@link #targetTx})
* - universe of data to replicate {@link #data}
* - nodes that has been treated successfully {@link #treated}
*
*
* @author Tony Chemit - [email protected]
* @since 2.4.3
*/
public class TopiaReplicationContext {
/** Logger */
private static final Log log =
LogFactory.getLog(TopiaReplicationContext.class);
/** Replication model. */
protected final ReplicationModel replicationModel;
/**
* root context of incoming data source (says where to obtain entities
* to replicate).
*/
protected final TopiaApplicationContext sourceTx;
/**
* root context of outcmoing data source (says where to replicate
* entities).
*/
protected final TopiaApplicationContext targetTx;
/** dictionnary of data to replicate. */
protected TopiaEntityIdsMap data;
/**
* List of nodes that has been replicated with success (used to
* rollback them if something was wrong).
*/
protected List treated;
protected TopiaReplicationOperationProvider operationProvider;
public TopiaReplicationContext(TopiaReplicationOperationProvider operationProvider,
ReplicationModel replicationModel,
TopiaApplicationContext sourceTx,
TopiaApplicationContext targetTx) {
this.operationProvider = operationProvider;
this.replicationModel = replicationModel;
this.sourceTx = sourceTx;
this.targetTx = targetTx;
}
public TopiaReplicationOperation getOperation(ReplicationOperationDef operationDef) {
TopiaReplicationOperation operation =
operationProvider.getOperation(operationDef);
return operation;
}
public TopiaReplicationOperationUndoable getUndoableOperation(ReplicationOperationDef operationDef) throws IllegalArgumentException {
TopiaReplicationOperationUndoable operation =
operationProvider.getUndoableOperation(operationDef);
return operation;
}
public ReplicationModel getReplicationModel() {
return replicationModel;
}
public void addTreatedNode(ReplicationNode node) {
getTreated().add(node);
}
public ReplicationNode[] getReverseTreated() {
List result =
new ArrayList(getTreated());
// reverse nodes treated
Collections.reverse(result);
return result.toArray(new ReplicationNode[result.size()]);
}
/**
* Init the replication context.
*
* Comptute the universe to replicate and store it in {@link #data}.
*
* @throws TopiaException for any error when initializing the replication context
*/
public void init() throws TopiaException {
TopiaPersistenceContext srcCtxt = newSourceTx();
try {
// obtain all data to replicate
data = getIds(srcCtxt);
// adjust operation according to this data (some operations can be
// skipped if no data is associated to the given nodes)
// will also sort for each node his operations (according to
// their respective phase)
getReplicationModel().adjustOperations(data);
} finally {
close(srcCtxt, true);
}
}
public List getEntityIds(Class extends TopiaEntity> type) throws TopiaException {
List nodeEntityIds = data.get(type);
return nodeEntityIds;
}
public List getEntityIds(ReplicationNode node) throws TopiaException {
List nodeEntityIds = getEntityIds(node.getEntityType());
return nodeEntityIds;
}
public List extends TopiaEntity> getEntities(TopiaPersistenceContext tx,
ReplicationNode node) throws TopiaException {
List nodeEntityIds = getEntityIds(node);
if (nodeEntityIds == null) {
// no ids found for this node
return Collections.emptyList();
}
if (log.isDebugEnabled()) {
log.debug("Will load " + nodeEntityIds.size() + " entities");
}
List extends TopiaEntity> nodeEntities =
TopiaEntityHelper.getEntitiesList(
tx,
nodeEntityIds.toArray(new String[nodeEntityIds.size()])
);
return nodeEntities;
}
public TopiaPersistenceContext newSourceTx() throws TopiaException {
return sourceTx.newPersistenceContext();
}
public TopiaPersistenceContext newTargetTx() throws TopiaException {
return targetTx.newPersistenceContext();
}
public static void close(TopiaPersistenceContext tx, boolean rollback) throws TopiaException {
try {
if (rollback) {
tx.rollback();
}
} finally {
tx.close();
}
}
public void clear() {
if (data != null) {
data.clear();
}
if (treated != null) {
treated.clear();
}
}
protected TopiaEntityIdsMap getIds(TopiaPersistenceContext srcCtxt) throws TopiaException {
TopiaEntityIdsMap data;
// on recupere les objets a repliquer par type
if (replicationModel.isReplicateAll()) {
// on recupere pour chaque type tous les ids des entites a repliquer
data = new TopiaEntityIdsMap();
for (TopiaEntityEnum e : replicationModel.getContracts()) {
List ids = srcCtxt.getDao(e.getContract()).findAllIds();
data.put(e.getContract(), ids);
}
} else {
// on recupere les entites specifies a repliquer
TopiaEntity[] entities = TopiaEntityHelper.getEntities(
srcCtxt,
replicationModel.getTopiaIds()
);
// on calcule toutes les ids des entites a repliquer
data = TopiaEntityHelper.detectEntityIds(
replicationModel.getContracts(),
replicationModel.getTypes(),
entities
);
}
return data;
}
protected List getTreated() {
if (treated == null) {
treated = new ArrayList();
}
return treated;
}
protected TopiaApplicationContext getSourceTx() {
return sourceTx;
}
protected TopiaApplicationContext getTargetTx() {
return targetTx;
}
protected TopiaEntityIdsMap getData() {
return data;
}
@Override
protected void finalize() throws Throwable {
clear();
super.finalize();
}
}