All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.topia.replication.operation.AttachLink Maven / Gradle / Ivy

There is a newer version: 4.0
Show newest version
package org.nuiton.topia.replication.operation;

/*
 * #%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 java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.topia.persistence.TopiaException;
import org.nuiton.topia.persistence.TopiaPersistenceContext;
import org.nuiton.topia.persistence.TopiaEntity;
import org.nuiton.topia.persistence.util.EntityOperator;
import org.nuiton.topia.persistence.util.TopiaEntityHelper;
import org.nuiton.topia.replication.TopiaReplicationContext;
import org.nuiton.topia.replication.TopiaReplicationOperation;
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;
import org.nuiton.topia.replication.model.ReplicationOperationPhase;

/**
 * Pour attacher une association.
 *
 * Deux cas peuvent se produire :
 *
 * - le noeud de l'operation est la source de l'association, dans ce cas la
 * {@code nodeEntities} contient les entites sources de l'association et on
 * retrouve les entites associes a partir du type de l'association
 *
 * Ce premier cas est verifie quand reverse (le econd parametre) est a false
 *
 * - le noeud de l'operation est la cible de l'association, dans ce cas la
 * {@code nodeEntities} contient les entities associes (cibles) de
 * l'assocation et on retrouve les entities a partir d'un troisieme parametre
 * qui donne le node source des entities sources.
 *
 * Note : cette operation est interne, et n'est pas creable par l'utilisateur
 * via la methode {@link #register(ReplicationModel, ReplicationNode,
 * ReplicationOperationPhase, Object...)}.
 *
 * @author Tony Chemit - [email protected]
 * @since 2.2.0
 */
public class AttachLink implements TopiaReplicationOperation {

    /** Logger */
    private static final Log log = LogFactory.getLog(AttachLink.class);

    @Override
    public void register(ReplicationModel model,
                         ReplicationNode ownerNode,
                         ReplicationOperationPhase phase,
                         Object... parameters) {

//        throw new UnsupportedOperationException(
//                _("topia.replication.error.operation.uncreatable", getClass()));
    }

    @Override
    public void run(TopiaReplicationContext replicationContext,
                    ReplicationOperationDef operationDef,
                    TopiaPersistenceContext srcCtxt,
                    TopiaPersistenceContext dstCtxt,
                    List nodeEntities
    ) throws TopiaException {

        ReplicationLink link =
                (ReplicationLink) operationDef.getParameters()[0];

        String name = link.getName();

        if (log.isDebugEnabled()) {
            log.debug("currentNode : " + operationDef.getNode() +
                      " , link to attach : " + link);
        }

        ReplicationNode ownerNode = link.getSource();
        ReplicationNode cibleNode = link.getTarget();

        EntityOperator ownerOperator =
                ownerNode.getOperator();

        // contient la liste des ids d'association autorisees ici
        List associationIds = null;

        // contient la liste des ids des entite source de l'association
        List ownerIds = null;

        if (ownerNode.equals(operationDef.getNode())) {
            ownerIds = TopiaEntityHelper.getTopiaIdList(nodeEntities);
        }

        if (cibleNode.equals(operationDef.getNode())) {
            associationIds = TopiaEntityHelper.getTopiaIdList(nodeEntities);
        }

        if (ownerIds == null) {
            ownerIds = replicationContext.getEntityIds(ownerNode);
        }

        if (associationIds == null) {
            associationIds = replicationContext.getEntityIds(cibleNode);
        }

        if (ownerIds == null || ownerIds.isEmpty()) {
            // pas de donnees a traiter
            log.info("Nothing to attach...");
            return;
        }

        // on recharge obligatoirement les donnees sources car elles ont pu etre
        // modifiees (dettachement d'association ou autres)
        // ils nous faut les entites telles qu'elles sont en base source

        // contient la liste des entites sources de l'association
        List ownerEntities =
                TopiaEntityHelper.getEntitiesList(
                        srcCtxt,
                        ownerIds.toArray(new String[ownerIds.size()])
                );

        boolean shouldCommit = false;


        if (log.isInfoEnabled()) {
            log.info("ownerNode : " + ownerNode + " , targetNode : " +
                     cibleNode + ", association : " + name);
        }
        if (log.isDebugEnabled()) {
            log.debug("owner ids : " + ownerIds);
            log.debug("association ids : " + associationIds);
        }

        for (TopiaEntity src : ownerEntities) {

            // les association cibles connues pour l'entite sur la base source
            Collection targetEntities = (Collection)
                    ownerOperator.get(name, src);

            if (targetEntities == null || targetEntities.isEmpty()) {
                if (log.isDebugEnabled()) {
                    log.debug("no association '" + name + "' attached to  " +
                              src);
                }
                // pas de donnees dans l'association
                continue;
            }
            if (log.isDebugEnabled()) {
                log.debug("will try to attach " + targetEntities.size() +
                          " association(s) '" + name + "' to " + src);
            }

            // l'entite repliquee a laquelle on veut attacher l'association

            TopiaEntity dst = dstCtxt.findByTopiaId(src.getTopiaId());

            // les association cibles connues pour l'entite sur la base
            // destination
            Collection dstTargetEntities = (Collection)
                    ownerOperator.get(name, dst);

            // les ids des entities deja associees
            List dstTargetAssociationsId =
                    dstTargetEntities == null ?
                    Collections.emptyList() :
                    TopiaEntityHelper.getTopiaIdList(
                            (Collection) dstTargetEntities);
            boolean shouldUpdate = false;
            for (Object a : targetEntities) {

                TopiaEntity assosiationSrc = (TopiaEntity) a;

                // on verifie que l'association doit etre rattachee
                if (associationIds.contains(assosiationSrc.getTopiaId())) {
                    if (dstTargetAssociationsId.contains(
                            assosiationSrc.getTopiaId())) {
                        // deja attache
                        if (log.isDebugEnabled()) {
                            log.debug("already attached association '" +
                                      name + "' : " + assosiationSrc);
                        }
                        continue;

                    }

                    // la donnees doit etre attachee

                    TopiaEntity assosiationDst =
                            dstCtxt.findByTopiaId(assosiationSrc.getTopiaId());
                    ownerOperator.addChild(name, dst, assosiationDst);
                    if (log.isDebugEnabled()) {
                        log.debug("will attach association '" + name +
                                  "' : " + assosiationDst);
                    }
                    shouldUpdate = true;
                }

            }

            if (shouldUpdate) {
                if (log.isTraceEnabled()) {
                    log.trace("will update " + dst.getTopiaId());
                }
                //FIXME: on ne peut pas updater l'objet car l'objet peut rentre
                // en conflit dans la session hibernate
                // cela fonctionne sans faire d'update (heureusement...)
                //dst.update();
                shouldCommit = true;
            }
        }

        if (shouldCommit) {
            dstCtxt.commit();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy