org.spinsuite.sync.SyncDataTask.java Source code

Java tutorial

Introduction

Here is the source code for org.spinsuite.sync.SyncDataTask.java

Source

/*************************************************************************************
 * Product: Spin-Suite (Making your Business Spin)                                   *
 * This program is free software; you can redistribute it and/or modify it           *
 * under the terms version 2 of the GNU General Public License as published          *
 * by the Free Software Foundation. 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.,           *
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.                            *
 * For the text or an alternative of this public license, you may reach us           *
 * Copyright (C) 2012-2015 E.R.P. Consultores y Asociados, S.A. All Rights Reserved. *
 * Contributor(s): Carlos Parada www.erpcya.com                                 *
 *************************************************************************************/
package org.spinsuite.sync;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;

import org.ksoap2.serialization.SoapObject;
import org.spinsuite.base.DB;
import org.spinsuite.base.R;
import org.spinsuite.conn.CommunicationSoap;
import org.spinsuite.interfaces.BackGroundProcess;
import org.spinsuite.model.MSPSSyncMenu;
import org.spinsuite.model.MSPSSyncTable;
import org.spinsuite.model.MSPSTable;
import org.spinsuite.model.MWSWebServiceType;
import org.spinsuite.model.PO;
import org.spinsuite.model.POInfo;
import org.spinsuite.model.Query;
import org.spinsuite.model.X_AD_Rule;
import org.spinsuite.model.X_SPS_SyncTable;
import org.spinsuite.model.X_WS_WebService;
import org.spinsuite.model.X_WS_WebServiceMethod;
import org.spinsuite.util.BackGroundTask;
import org.spinsuite.util.DisplayType;
import org.spinsuite.util.Env;
import org.spinsuite.util.LogM;
import org.spinsuite.util.SyncValues;
import org.xmlpull.v1.XmlPullParserException;

import com._3e.ADInterface.WSModelCRUDRequest;

import android.app.NotificationManager;
import android.content.Context;
import android.database.sqlite.SQLiteException;
import android.os.StrictMode;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;

/**
 * 
 * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
 * @contributor Yamel Senih, ysenih@erpcya.com, ERPCyA http://www.erpcya.com
 * <li> Add Delete Before Pull option
 * @see <li>https://adempiere.atlassian.net/browse/SPIN-20
 *
 */
public class SyncDataTask implements BackGroundProcess {
    /** Sync Menu ID               */
    private int m_SPS_SyncMenu_ID = 0;
    /** Connection Database          */
    private DB conn = null;
    /** Context                   */
    private Context m_ctx;
    /**   Main URL                  */
    private String m_URL;
    /** Current URL Web Service         */
    private String m_Current_URL;
    /**   Web Service Value            */
    private String m_Value;
    /** Web Service NameSpace          */
    private String m_NameSpace;
    /** Web Service Method            */
    private String m_MethodValue;
    /** Soap Object Call            */
    private CommunicationSoap soapObject;
    /** Timeout for Response Web Service*/
    private int m_TimeOut = 0;
    /** Soap Object Response         */
    private SoapObject soapResponse = null;
    /** Notification Manager         */
    private NotificationManager m_NFManager = null;
    /** Max Value Progress Bar         */
    private int m_MaxPB = 0;
    /** Builder                     */
    private Builder m_Builder = null;
    /** Progress Indicator            */
    private int m_Progress = -1;
    /** Public Message               */
    private String m_PublicMsg = "";
    /** Public Title               */
    private String m_PublicTittle = "";
    /** Background Task               */
    private BackGroundTask bgTask = null;
    /**Define if is Root Node          */
    private boolean m_IsRootNode = true;
    /**   Is Forced                  */
    private boolean m_IsForced = false;
    /**   Delete Before               */
    private boolean m_IsDeleteBefore = false;

    /**
     * 
     * *** Constructor ***
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @contributor Yamel Senih, ysenih@erpcya.com, ERPCyA http://www.erpcya.com
     * <li>Get URL SOAP from Context
     * @param p_ctx
     * @param p_SPS_SyncMenu_ID
     * @param p_IsForced
     * @param p_IsDeleteBefore
     */
    public SyncDataTask(Context p_ctx, int p_SPS_SyncMenu_ID, boolean p_IsForced, boolean p_IsDeleteBefore) {
        m_ctx = p_ctx;
        m_SPS_SyncMenu_ID = p_SPS_SyncMenu_ID;
        m_IsForced = p_IsForced;
        m_IsDeleteBefore = p_IsDeleteBefore;
        if (m_IsDeleteBefore) {
            m_IsForced = m_IsDeleteBefore;
        }
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        m_NFManager = (NotificationManager) m_ctx.getSystemService(Context.NOTIFICATION_SERVICE);
        m_Builder = new NotificationCompat.Builder(m_ctx);
        //   Set URL
        m_URL = Env.getContext("#SUrlSoap");
        //   
        bgTask = new BackGroundTask(this, m_ctx);
        bgTask.runTask();
    }

    @Override
    public void publishBeforeInit() {
        m_Builder.setContentTitle(m_PublicTittle).setContentText(m_PublicMsg)
                .setProgress(m_MaxPB, m_Progress, m_Progress == -1)
                .setSmallIcon(android.R.drawable.stat_sys_download);
        m_NFManager.notify(0, m_Builder.build());
    }

    @Override
    public void publishOnRunning() {
        m_Builder.setContentTitle(m_PublicTittle).setContentText(m_PublicMsg)
                .setProgress(m_MaxPB, m_Progress, m_Progress == -1)
                .setSmallIcon(android.R.drawable.stat_sys_download);

        m_NFManager.notify(0, m_Builder.build());
    }

    @Override
    public void publishAfterEnd() {
        m_Builder.setContentTitle(m_PublicTittle).setContentText(m_PublicMsg).setProgress(0, 0, false)
                .setSmallIcon(android.R.drawable.stat_sys_download_done);
        m_NFManager.notify(0, m_Builder.build());
    }

    @Override
    public Object run() {
        //   Get Previous Milliseconds
        long previousMillis = System.currentTimeMillis();
        boolean m_Error = false;
        try {
            conn = new DB(m_ctx);
            conn.openDB(DB.READ_WRITE);
            syncData(m_SPS_SyncMenu_ID, 0);
        } catch (Exception e) {
            m_Error = true;
            LogM.log(m_ctx, getClass(), Level.SEVERE, e.getLocalizedMessage());
            e.printStackTrace();
        }
        //   
        finally {
            conn.close();
            conn = null;
            //   Last Message
            if (!m_Error) {
                long afterMillis = System.currentTimeMillis();
                long duration = afterMillis - previousMillis;
                m_PublicMsg = (m_PublicMsg == null ? "" : m_PublicMsg + " ")
                        + m_ctx.getString(R.string.SynchronizingEnding) + " "
                        + m_ctx.getString(R.string.Sync_Duration) + ": " + SyncValues.getDifferenceValue(duration);
            }
        }
        //   
        return null;
    }

    /**
     * Synchronize data method
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param p_SPS_SyncMenu_ID
     * @return void
     * @throws XmlPullParserException 
     * @throws IOException 
     */
    private void syncData(int p_SPS_SyncMenu_ID, int PageNo) {
        MSPSSyncMenu syncm = new MSPSSyncMenu(m_ctx, p_SPS_SyncMenu_ID, conn);
        SoapObject param = null;
        int qtyPages = 1;
        int currentPage = PageNo + 1;
        //Run Script Before Call Web Service 
        if (syncm.getAD_RuleBefore_ID() != 0) {
            X_AD_Rule rule = new X_AD_Rule(m_ctx, syncm.getAD_RuleBefore_ID(), conn);
            runQuery(rule.getScript(), null);
        }

        //Call Web Services
        if (syncm.getWS_WebServiceType_ID() != 0) {
            setSyncValues(syncm);

            //Run Query Data Web Service
            if (m_MethodValue.equals(SyncValues.WSMQueryData)) {
                param = getSoapParam(syncm, PageNo);
                callWebService(param, syncm);

                if (soapResponse != null && soapResponse.hasAttribute(SyncValues.WSQtyPages))
                    qtyPages = Integer.parseInt(soapResponse.getAttributeAsString(SyncValues.WSQtyPages));

                //   Delete All Records
                if (soapResponse != null && !soapResponse.hasProperty(SyncValues.WSRespError) && m_IsDeleteBefore) {
                    //   Delete Old Data
                    if (syncm.getSPS_Table_ID() != 0) {
                        MSPSTable m_Table = new MSPSTable(m_ctx, syncm.getSPS_Table_ID(), conn);
                        //   Execute
                        DB.executeUpdate(m_ctx, "DELETE FROM " + m_Table.getTableName() + " WHERE AD_Client_ID = ?",
                                Env.getAD_Client_ID(m_ctx), conn);
                    }
                }
                //   Write Data
                while (currentPage <= qtyPages) {
                    writeDB(syncm, 0);
                    if (currentPage != qtyPages) {
                        param = getSoapParam(syncm, currentPage);
                        callWebService(param, syncm);
                    }
                    currentPage++;
                }
            } //End Query Data Web Service

            //Run Create Data Web Service
            else if (m_MethodValue.equals(SyncValues.WSMCreateData)) {
                if (syncm.getSPS_Table_ID() != 0) {
                    MSPSTable table = new MSPSTable(m_ctx, syncm.getSPS_Table_ID(), conn);
                    String whereClause = "";
                    Object[] parameters = null;
                    if (syncm.getWhereClause() != null)
                        whereClause += syncm.getWhereClause();
                    if (!syncm.isForced() && !m_IsForced) {
                        whereClause = " AND EXISTS (SELECT 1 " + "FROM " + "SPS_SyncTable "
                                + "WHERE SPS_SyncTable.SPS_Table_ID = ? AND " + "SPS_SyncTable.Record_ID = "
                                + table.getTableName() + "." + table.getTableName() + "_ID AND "
                                //                                       + "SPS_SyncTable.EventChangeLog IN (?,?) AND "
                                + "SPS_SyncTable.EventChangeLog = ? AND " + "SPS_SyncTable.IsSynchronized='N' )";
                        parameters = new Object[] { table.getSPS_Table_ID(),
                                X_SPS_SyncTable.EVENTCHANGELOG_Insert };
                    } else {
                        parameters = new Object[] {};
                    }

                    List<PO> rows = new Query(m_ctx, table.getTableName(), whereClause, conn)
                            .setParameters(parameters).list();
                    for (PO row : rows) {
                        param = getSoapParam(syncm, PageNo, row);
                        callWebService(param, syncm);
                        writeDB(syncm, row.get_ID());
                    }
                    if (rows.size() == 0) {
                        m_PublicTittle = syncm.getName();
                        m_PublicMsg = m_ctx.getString(R.string.msg_NoRecordsPendingtoSync);
                    }
                }
            } //End Create Data Web Service

            else if (m_MethodValue.equals(SyncValues.WSMUpdateData)) {
                if (syncm.getSPS_Table_ID() != 0) {
                    MSPSTable table = new MSPSTable(m_ctx, syncm.getSPS_Table_ID(), conn);
                    String whereClause = "";
                    Object[] parameters = null;
                    if (syncm.getWhereClause() != null)
                        whereClause += syncm.getWhereClause();
                    if (!syncm.isForced() && !m_IsForced) {
                        whereClause = " AND EXISTS (SELECT 1 " + "FROM " + "SPS_SyncTable "
                                + "WHERE SPS_SyncTable.SPS_Table_ID = ? AND " + "SPS_SyncTable.Record_ID = "
                                + table.getTableName() + "." + table.getTableName() + "_ID AND "
                                + "SPS_SyncTable.EventChangeLog IN (?,?) AND "
                                //                                    + "SPS_SyncTable.EventChangeLog = ? AND "
                                + "SPS_SyncTable.IsSynchronized='N' )";
                        parameters = new Object[] { table.getSPS_Table_ID(), X_SPS_SyncTable.EVENTCHANGELOG_Insert,
                                X_SPS_SyncTable.EVENTCHANGELOG_Update };
                        //               parameters = new Object[]{table.getSPS_Table_ID(),X_SPS_SyncTable.EVENTCHANGELOG_Update};
                    } else {
                        parameters = new Object[] {};
                    }

                    whereClause = Env.parseContext(whereClause, true);

                    List<PO> rows = new Query(m_ctx, table.getTableName(), whereClause, conn)
                            .setParameters(parameters).list();
                    for (PO row : rows) {
                        param = getSoapParam(syncm, PageNo, row);
                        callWebService(param, syncm);
                        writeDB(syncm, row.get_ID());
                    }
                    if (rows.size() == 0) {
                        m_PublicTittle = syncm.getName();
                        m_PublicMsg = m_ctx.getString(R.string.msg_NoRecordsPendingtoSync);
                    }
                }
            } //End Create Data Web Service

        }

        //Run Script After Call Web Service 
        if (syncm.getAD_RuleAfter_ID() != 0) {
            X_AD_Rule rule = new X_AD_Rule(m_ctx, syncm.getAD_RuleAfter_ID(), conn);
            runQuery(rule.getScript(), null);
        }

        if (m_IsRootNode) {
            m_IsRootNode = false;
            //Get Child's Web Services
            List<MSPSSyncMenu> syncms = MSPSSyncMenu.getNodesFromParent(m_ctx,
                    Integer.valueOf(m_SPS_SyncMenu_ID).toString(), conn);

            for (MSPSSyncMenu mspsSyncMenu : syncms) {
                syncData(mspsSyncMenu.getSPS_SyncMenu_ID(), 0);
            }

        }
    }

    /**
     * 
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param sm
     * @return
     * @return SoapObject
     */
    private SoapObject getSoapParam(MSPSSyncMenu sm, int PageNo, PO data) {
        SoapObject param = null;
        MWSWebServiceType wst = new MWSWebServiceType(m_ctx, sm.getWS_WebServiceType_ID(), conn);

        if (m_MethodValue.equals(SyncValues.WSMQueryData)) {
            String whereClause = "";

            if (!sm.isForced() && !m_IsForced) {
                SimpleDateFormat sdf = DisplayType.getDateFormat(m_ctx, DisplayType.DATE_TIME,
                        "yyyy-MM-dd hh:mm:ss");
                whereClause += (sm.getLastSynchronized() != null
                        ? "(UPDATED >= '" + sdf.format(sm.getLastSynchronized()) + "')"
                        : "");
            }
            if (sm.getWhereClause() != null)
                whereClause += (whereClause.equals("") ? "" : " AND ") + "("
                        + Env.parseContext(sm.getWhereClause(), true) + ")";
            param = new WSModelCRUDRequest(m_ctx, m_NameSpace, wst.getWS_WebServiceType_ID(), conn, 0, null,
                    whereClause, PageNo);
        } else if (m_MethodValue.equals(SyncValues.WSMCreateData))
            param = new WSModelCRUDRequest(m_ctx, m_NameSpace, wst.getWS_WebServiceType_ID(), conn, data.get_ID(),
                    data);
        else if (m_MethodValue.equals(SyncValues.WSMUpdateData))
            param = new WSModelCRUDRequest(m_ctx, m_NameSpace, wst.getWS_WebServiceType_ID(), conn, data.get_ID(),
                    data);
        //   

        //   
        return param;
    }

    /**
     * 
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param sm
     * @param PageNo
     * @return
     * @return SoapObject
     */
    private SoapObject getSoapParam(MSPSSyncMenu sm, int PageNo) {
        return getSoapParam(sm, PageNo, null);
    }

    /**
     * Set Synchronize Values
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param sm
     * @return void
     */
    private void setSyncValues(MSPSSyncMenu sm) {
        MWSWebServiceType wst = new MWSWebServiceType(m_ctx, sm.getWS_WebServiceType_ID(), conn);

        if (wst.getWS_WebService_ID() != 0) {
            X_WS_WebService ws = new X_WS_WebService(m_ctx, wst.getWS_WebService_ID(), conn);
            m_Value = ws.getValue();
            m_NameSpace = (ws.getNameSpace() == null ? "" : ws.getNameSpace());
            m_Current_URL = SyncValues.getValidURL(m_URL, m_Value);
        }

        if (wst.getWS_WebServiceMethod_ID() != 0) {
            X_WS_WebServiceMethod wsm = new X_WS_WebServiceMethod(m_ctx, wst.getWS_WebServiceMethod_ID(), conn);
            if (wsm.getValue() != null)
                m_MethodValue = wsm.getValue();
        }
    }

    /**
     * Call Web Service And get Response
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param p_SO_Param
     * @throws IOException
     * @throws XmlPullParserException
     * @return void
     */
    private void callWebService(SoapObject p_SO_Param, MSPSSyncMenu sm) {

        m_PublicTittle = sm.getName();
        m_PublicMsg = sm.getDescription();
        m_Progress = -1;
        publishOnRunning();

        soapObject = new CommunicationSoap(m_Current_URL, m_NameSpace, m_MethodValue, SyncValues.IsNetService);
        soapObject.setM_SoapAction(m_NameSpace + "/" + m_MethodValue);

        if (p_SO_Param != null)
            soapObject.addSoapObject(p_SO_Param);

        soapObject.init_envelope();

        if (m_TimeOut == 0)
            soapObject.initTransport();
        else
            soapObject.initTransport(m_TimeOut);

        try {
            soapObject.call();
            soapResponse = (SoapObject) soapObject.getM_Envelope().getResponse();
        } catch (SocketTimeoutException e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } catch (IOException e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } catch (Exception e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } finally {
            publishOnRunning();
        }

    }

    /**
     * Write into DB
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param sm
     * @return void
     */
    private void writeDB(MSPSSyncMenu sm, int p_ID) {

        //Validate Response
        if (soapResponse == null)
            return;

        if (soapResponse.hasProperty(SyncValues.WSRespError)) {
            //   Mark like Not Synchronized
            if (m_MethodValue.equals(SyncValues.WSMQueryData)) {
                sm.setLastSynchronized(null);
                sm.save();
            }
            m_PublicMsg = soapResponse.getPropertyAsString("Error");
            LogM.log(m_ctx, SyncDataTask.class, Level.SEVERE, m_PublicMsg);
            publishOnRunning();
            return;
        }
        //   
        if (m_MethodValue.equals(SyncValues.WSMQueryData)) {
            //Validate Data Set
            if (!soapResponse.hasProperty(SyncValues.WSRespDataSet))
                return;
            //Soap Data Set
            SoapObject soapDataSet = (SoapObject) soapResponse.getProperty(SyncValues.WSRespDataSet);

            //Validate Data Row
            if (soapDataSet == null || !soapDataSet.hasProperty(SyncValues.WSRespDataRow))
                return;

            //Soap Data Row
            SoapObject soapDataRow = (SoapObject) soapDataSet.getProperty(SyncValues.WSRespDataRow);

            int countDataSet = soapDataSet.getPropertyCount();
            int countDataRow = soapDataRow.getPropertyCount();
            SoapObject field = null;
            Object value = null;
            PO data = null;
            String whereClause = "";
            String[] keyColumns = null;
            POInfo info = null;
            if (sm.getSPS_Table_ID() != 0)
                info = POInfo.getPOInfo(m_ctx, sm.getSPS_Table_ID(), conn);

            if (info == null)
                return;

            m_MaxPB = countDataSet;

            if (info.getKeyColumns() != null)
                keyColumns = info.getKeyColumns();
            else
                keyColumns = new String[] {};

            Arrays.sort(keyColumns);

            for (int i = 0; i < keyColumns.length; i++) {
                whereClause += (whereClause.equals("") ? " " : " AND ") + keyColumns[i] + "=?";
            }

            for (int i = 0; i < countDataSet; i++) {
                m_Progress = i + 1;
                //Soap Data Row
                soapDataRow = (SoapObject) soapDataSet.getProperty(i);
                Object[] keyValues = getKeyValues(soapDataRow, countDataRow, keyColumns);

                try {
                    data = new Query(m_ctx, info.getTableName(), whereClause, conn).setParameters(keyValues)
                            .first();

                    if (data == null) {
                        whereClause = "EXISTS (SELECT 1 FROM SPS_SyncTable st WHERE st.SPS_Table_ID = "
                                + info.getSPS_Table_ID();
                        for (int j = 0; j < keyColumns.length; j++)
                            whereClause += (j == 0 ? " AND (" : " OR ") + " st.SyncRecord_ID = ? ";

                        if (keyColumns.length > 0)
                            whereClause += ")";

                        for (int j = 0; j < keyColumns.length; j++)
                            whereClause += (j == 0 ? " AND (" : " OR ") + " st.Record_ID = " + info.getTableName()
                                    + "." + keyColumns[j];

                        if (keyColumns.length > 0)
                            whereClause += ")";

                        whereClause += " AND IsSynchronized='Y')";

                        data = new Query(m_ctx, info.getTableName(), whereClause, conn).setParameters(keyValues)
                                .first();

                    }

                    if (data == null) {
                        //Cursor rs = conn.querySQL(info.buildSelect().append(" WHERE 1=0 ").toString(),new String[]{});
                        MSPSTable table = new MSPSTable(m_ctx, info.getSPS_Table_ID(), conn);
                        data = table.getPO(null, conn);
                    }

                    if (data == null)
                        return;
                    for (int j = 0; j < countDataRow; j++) {
                        field = (SoapObject) soapDataRow.getProperty(j);
                        String columnName = field.getAttributeAsString(SyncValues.WSColumn);
                        if (keyColumns.length <= 1) {
                            int index = Arrays.binarySearch(keyColumns, columnName);
                            if (index >= 0 && data.get_ID() != 0)
                                continue;
                        }
                        if (field.getProperty(SyncValues.WSValue) == null)
                            value = null;
                        else
                            value = field.getPropertyAsString(SyncValues.WSValue);

                        value = DisplayType.parseValue(value, info.getDisplayType(columnName), columnName);

                        data.set_Value(columnName, value);
                    }
                    data.setSynchronization(true);
                    data.saveEx();
                    publishOnRunning();

                } catch (Exception e) {
                    m_PublicMsg = e.getLocalizedMessage();
                    LogM.log(m_ctx, SyncDataTask.class, Level.SEVERE, m_PublicMsg, e.getCause());
                    publishOnRunning();
                }

            }
            //   Mark like Synchronized
            sm.setLastSynchronized(new Timestamp(System.currentTimeMillis()));
            sm.save();
        } else if (m_MethodValue.equals(SyncValues.WSMCreateData)) {

            if (soapResponse.hasAttribute("RecordID")) {
                String whereClause = "SPS_Table_ID = " + sm.getSPS_Table_ID() + " AND " + "Record_ID = " + p_ID
                        + " AND " + "EventChangeLog ='" + X_SPS_SyncTable.EVENTCHANGELOG_Insert
                        + "' AND IsSynchronized='N'";

                try {
                    MSPSSyncTable synctable = MSPSSyncTable.getSyncTable(sm.getCtx(), conn, whereClause);
                    if (synctable.getSPS_SyncTable_ID() > 0) {
                        synctable.setSyncRecord_ID(soapResponse.getAttributeAsString("RecordID"));
                        synctable.setIsSynchronized(true);
                        synctable.save();
                        sm.setLastSynchronized(new Timestamp(System.currentTimeMillis()));
                        sm.save();
                    }
                } catch (Exception e) {
                    m_PublicMsg = e.getLocalizedMessage();
                    LogM.log(m_ctx, SyncDataTask.class, Level.SEVERE, m_PublicMsg, e.getCause());
                    publishOnRunning();
                }
            }

        } else if (m_MethodValue.equals(SyncValues.WSMUpdateData)) {

            if (soapResponse.hasAttribute("RecordID")) {
                String whereClause = "SPS_Table_ID = " + sm.getSPS_Table_ID() + " AND " + "Record_ID = " + p_ID
                        + " AND " + "EventChangeLog ='" + X_SPS_SyncTable.EVENTCHANGELOG_Update
                        + "' AND IsSynchronized='N'";

                try {
                    MSPSSyncTable synctable = MSPSSyncTable.getSyncTable(sm.getCtx(), conn, whereClause);
                    if (synctable.getSPS_SyncTable_ID() > 0) {
                        synctable.setSyncRecord_ID(soapResponse.getAttributeAsString("RecordID"));
                        synctable.setIsSynchronized(true);
                        synctable.save();
                        sm.setLastSynchronized(new Timestamp(System.currentTimeMillis()));
                        sm.save();
                    }
                } catch (Exception e) {
                    m_PublicMsg = e.getLocalizedMessage();
                    LogM.log(m_ctx, SyncDataTask.class, Level.SEVERE, m_PublicMsg, e.getCause());
                    publishOnRunning();
                }
            }

        }

        soapResponse = null;
    }

    /**
     * Run a Query
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param sql
     * @param data
     * @return void
     */
    private void runQuery(String sql, Object[] data) {
        try {
            //   Parse SQL
            String parsedSQL = Env.parseContext(sql, true);
            if (data != null)
                conn.executeSQL(parsedSQL, data);
            else
                conn.executeSQL(parsedSQL);
        } catch (SQLiteException e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } catch (Exception e) {
            e.printStackTrace();
            m_PublicMsg = e.getLocalizedMessage();
        } finally {
            publishOnRunning();
        }
    }

    /**
     * Get Key Values
     * @author Carlos Parada, cparada@erpcya.com, ERPCyA http://www.erpcya.com
     * @param soapDataRow
     * @param countDataRow
     * @param keyColumns
     * @return
     * @return Object[]
     */
    private Object[] getKeyValues(SoapObject soapDataRow, int countDataRow, String[] keyColumns) {
        Object[] keyValues = new String[keyColumns.length];
        SoapObject field = null;
        for (int i = 0; i < countDataRow; i++) {
            field = (SoapObject) soapDataRow.getProperty(i);
            String columnName = field.getAttributeAsString(SyncValues.WSColumn);
            int index = Arrays.binarySearch(keyColumns, columnName);
            if (index < 0)
                continue;
            if (field.getProperty(SyncValues.WSValue) == null)
                keyValues[index] = null;
            else
                keyValues[index] = field.getPropertyAsString(SyncValues.WSValue);

        }
        //   Return
        return keyValues;
    }
}