/********************************************************************** * This file is part of Adempiere ERP Bazaar * * http://www.adempiere.org * * * * Copyright (C) Trifon Trifonov. * * Copyright (C) Contributors * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * 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 Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * * Contributors: * * - Trifon Trifonov (trifonnt@users.sourceforge.net) * * * * Sponsors: * * - e-Evolution (http://www.e-evolution.com) * **********************************************************************/ package org.adempiere.model; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.logging.Level; import org.adempiere.process.rpl.exp.ExportHelper; import org.compiere.model.MClient; import org.compiere.model.MOrg; import org.compiere.model.MReplicationStrategy; import org.compiere.model.MTable; import org.compiere.model.ModelValidationEngine; import org.compiere.model.ModelValidator; import org.compiere.model.PO; import org.compiere.model.Query; import org.compiere.model.X_AD_ReplicationDocument; import org.compiere.model.X_AD_ReplicationTable; import org.compiere.util.CLogger; import org.compiere.util.Env; /** * Export Validator which is responsible to create XML document. * * @author Trifon Trifonov * @author victor.perez@e-evolution.com, www.e-evolution.com *
  • BF2875989 Deactivate replication records are include to replication *
  • https://sourceforge.net/p/adempiere/bugs/2167/ *
  • [ 2195090 ] Stabilization of replication *
  • https://sourceforge.net/p/adempiere/bugs/2294/ *
  • BF2947615 The document recplicacion not working *
  • https://sourceforge.net/p/adempiere/bugs/2307/ *
  • The Replication should can use the Strategy from the org *
  • https://sourceforge.net/p/adempiere/feature-requests/979/ * * @version $Id$ */ public class ExportModelValidator implements ModelValidator { /** Context variable which says if replication is enabled */ public static final String CTX_IsReplicationEnabled = "#IsReplicationEnabled"; /** Logger */ private static final CLogger log = CLogger.getCLogger(ExportModelValidator.class); /** Client */ private int m_AD_Client_ID = -1; /** ModelValidationEngine engine **/ List modelTables = new ArrayList(); List docTables = new ArrayList(); /* The Export Helpers per each replication strategy */ Hashtable helpers = new Hashtable(); /** * Constructor. * The class is instantiated when logging in and client is selected/known */ public ExportModelValidator () { super (); } /** * Initialize Validation * @param engine validation engine * @param client client */ public void initialize (ModelValidationEngine engine, MClient client) { if (client != null) { m_AD_Client_ID = client.getAD_Client_ID(); if (log.isLoggable(Level.INFO)) log.info(client.toString()); loadReplicationStrategy(engine); } else { log.warning("Export Model Validator cannot be used as a global validator, it needs to be defined in a per-tenant basis"); return; } } public void loadReplicationStrategy(ModelValidationEngine engine) { MClient client = MClient.get(Env.getCtx(), m_AD_Client_ID); String where = "AD_ReplicationStrategy_ID IN (" + "SELECT AD_ReplicationStrategy_ID FROM AD_Client WHERE AD_Client_ID=? " + "UNION " + "SELECT AD_ReplicationStrategy_ID FROM AD_Org WHERE AD_Client_ID=?)"; List rss = new Query(Env.getCtx(), MReplicationStrategy.Table_Name, where, null) .setOnlyActiveRecords(true) .setParameters(m_AD_Client_ID, m_AD_Client_ID) .list(); for (MReplicationStrategy rplStrategy : rss) { ExportHelper expClientHelper = new ExportHelper(client, rplStrategy); helpers.put(rplStrategy.getAD_ReplicationStrategy_ID(), expClientHelper); // Add Tables // We want to be informed when records in Replication tables are created/updated/deleted! for (X_AD_ReplicationTable rplTable : rplStrategy.getReplicationTables()) { if ( X_AD_ReplicationTable.REPLICATIONTYPE_Merge.equals(rplTable.getReplicationType()) || X_AD_ReplicationTable.REPLICATIONTYPE_Broadcast.equals(rplTable.getReplicationType()) || X_AD_ReplicationTable.REPLICATIONTYPE_Reference.equals(rplTable.getReplicationType())) { String tableName = MTable.getTableName(client.getCtx(), rplTable.getAD_Table_ID()); if (! modelTables.contains(tableName)) { engine.addModelChange(tableName, this); modelTables.add(tableName); } } } // Add Documents // We want to be informed when Replication documents are created/updated/deleted! for (X_AD_ReplicationDocument rplDocument : rplStrategy.getReplicationDocuments()) { if ( X_AD_ReplicationDocument.REPLICATIONTYPE_Merge.equals(rplDocument.getReplicationType()) || X_AD_ReplicationDocument.REPLICATIONTYPE_Reference.equals(rplDocument.getReplicationType())) { String tableName = MTable.getTableName(client.getCtx(), rplDocument.getAD_Table_ID()); if (! docTables.contains(tableName)) { engine.addDocValidate(tableName, this); docTables.add(tableName); } } } } } /** * Model Change of a monitored Table. * Called after PO.beforeSave/PO.beforeDelete * @param po persistent object * @param type TYPE_ * @return error message or null * @exception Exception if the recipient wishes the change to be not accept. */ public String modelChange (PO po, int type) throws Exception { if (log.isLoggable(Level.INFO)) log.info("po.get_TableName() = " + po.get_TableName()); int rsID = getReplicationStrategy(po); if (rsID > 0) { ExportHelper expHelper = helpers.get(rsID); if (expHelper != null) { if ( type == TYPE_AFTER_CHANGE || type == TYPE_AFTER_NEW || type == TYPE_BEFORE_DELETE) { X_AD_ReplicationTable replicationTable = MReplicationStrategy.getReplicationTable( po.getCtx(), rsID, po.get_Table_ID()); if (replicationTable != null) { expHelper.exportRecord( po, MReplicationStrategy.REPLICATION_TABLE, replicationTable.getReplicationType(), type); } } } } return null; } /** * Validate Document. * Called as first step of DocAction.prepareIt * when you called addDocValidate for the table. * @param po persistent object * @param type see TIMING_ constants * @return error message or null * @throws Exception */ public String docValidate (PO po, int type) { if (log.isLoggable(Level.INFO)) log.info("Replicate the Document = " + po.get_TableName() + " with Type = " + type); String result = null; int rsID = getReplicationStrategy(po); if (rsID > 0) { ExportHelper expHelper = helpers.get(rsID); if (expHelper != null) { try { if ( type == TIMING_AFTER_COMPLETE || type == TIMING_AFTER_CLOSE || type == TIMING_AFTER_REVERSECORRECT || type == TIMING_AFTER_VOID || type == TIMING_AFTER_REACTIVATE //|| type == TIMING_AFTER_PREPARE ) { X_AD_ReplicationDocument replicationDocument = null; int C_DocType_ID = po.get_ValueAsInt("C_DocType_ID"); if (C_DocType_ID > 0) { replicationDocument = MReplicationStrategy.getReplicationDocument( po.getCtx(), rsID, po.get_Table_ID(), C_DocType_ID); } else { replicationDocument = MReplicationStrategy.getReplicationDocument( po.getCtx(), rsID, po.get_Table_ID()); } if (replicationDocument != null) { expHelper.exportRecord( po, MReplicationStrategy.REPLICATION_DOCUMENT, replicationDocument.getReplicationType(), type); } } } catch (Exception e) { e.printStackTrace(); result = e.toString(); } } } return result; } private int getReplicationStrategy(PO po) { int rsID = -1; int orgID = po.getAD_Org_ID(); if (orgID > 0) { rsID = MOrg.get(po.getCtx(), orgID).getAD_ReplicationStrategy_ID(); } if (rsID <= 0) { int clientID = po.getAD_Client_ID(); rsID = MClient.get(Env.getCtx(), clientID).getAD_ReplicationStrategy_ID(); } return rsID; } /** * User Login. * Called when preferences are set * @param AD_Org_ID org * @param AD_Role_ID role * @param AD_User_ID user * @return error message or null */ public String login (int AD_Org_ID, int AD_Role_ID, int AD_User_ID) { Env.setContext(Env.getCtx(), CTX_IsReplicationEnabled, true); return null; } /** * Get Client to be monitored * @return AD_Client_ID client */ public int getAD_Client_ID() { return m_AD_Client_ID; } /** * String Representation * @return info */ public String toString () { StringBuilder sb = new StringBuilder (ExportModelValidator.class.getName()); return sb.toString(); } }