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

org.jumpmind.symmetric.route.LookupTableDataRouter Maven / Gradle / Ivy

Go to download

SymmetricDS is an open source database synchronization solution. It is platform-independent, web-enabled, and database-agnostic. SymmetricDS was first built to replicate changes between 'retail store' databases and ad centralized 'corporate' database.

The newest version!
/*
 * Licensed to JumpMind Inc under one or more contributor 
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding 
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU Lesser General Public License (the
 * "License"); you may not use this file except in compliance
 * with the License. 
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see           
 * .
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License. 
 */

package org.jumpmind.symmetric.route;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.jumpmind.symmetric.common.logging.ILog;
import org.jumpmind.symmetric.common.logging.LogFactory;
import org.jumpmind.symmetric.model.DataMetaData;
import org.jumpmind.symmetric.model.Node;
import org.jumpmind.symmetric.model.Router;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;

/**
 * A data router that uses a lookup table to map data to nodes
 *
 * 
 */
public class LookupTableDataRouter extends AbstractDataRouter implements IDataRouter {

    final static ILog log = LogFactory.getLog(LookupTableDataRouter.class);

    public final static String PARAM_TABLE = "LOOKUP_TABLE";
    public final static String PARAM_KEY_COLUMN = "KEY_COLUMN";
    public final static String PARAM_MAPPED_KEY_COLUMN = "LOOKUP_KEY_COLUMN";
    public final static String PARAM_EXTERNAL_ID_COLUMN = "EXTERNAL_ID_COLUMN";

    final static String EXPRESSION_KEY = String.format("%s.Expression.",
            LookupTableDataRouter.class.getName());

    final static String LOOKUP_TABLE_KEY = String.format("%s.Table.", LookupTableDataRouter.class
            .getName());

    private JdbcTemplate jdbcTemplate;

    public Collection routeToNodes(IRouterContext routingContext,
            DataMetaData dataMetaData, Set nodes, boolean initialLoad) {

        Set nodeIds = null;
        Router router = dataMetaData.getTriggerRouter().getRouter();
        Map params = getParams(router, routingContext);
        Map dataMap = getDataMap(dataMetaData);
        boolean validExpression = params.containsKey(PARAM_TABLE)
                && params.containsKey(PARAM_KEY_COLUMN) && params.containsKey(PARAM_MAPPED_KEY_COLUMN)
                && params.containsKey(PARAM_EXTERNAL_ID_COLUMN);
        if (validExpression) {
            Map> lookupTable = getLookupTable(params, router, routingContext);
            String column = params.get(PARAM_KEY_COLUMN);
            String keyData = dataMap.get(column);
            Set externalIds = lookupTable.get(keyData);
            if (externalIds != null) {
                for (Node node : nodes) {
                    if (externalIds.contains(node.getExternalId())) {
                        nodeIds = addNodeId(node.getNodeId(), nodeIds, nodes);
                    }
                }
            }

        } else {
            log.warn("RouterIllegalLookupTableExpression", router.getRouterExpression());
        }

        return nodeIds;

    }

    /**
     * Cache parsed expressions in the context to minimize the amount of parsing
     * we have to do when we have lots of throughput.
     */
    @SuppressWarnings("unchecked")
    protected Map getParams(Router router, IRouterContext routingContext) {
        final String KEY = EXPRESSION_KEY + router.getRouterId();
        Map params = (Map) routingContext.getContextCache()
                .get(KEY);
        if (params == null) {
            params = new HashMap();
            routingContext.getContextCache().put(KEY, params);
            String routerExpression = router.getRouterExpression();
            if (!StringUtils.isBlank(routerExpression)) {
                String[] expTokens = routerExpression.split("\r\n|\r|\n");
                if (expTokens != null) {
                    for (String t : expTokens) {
                        if (!StringUtils.isBlank(t)) {
                            String[] tokens = t.split("=");
                            if (tokens.length >= 2) {
                                params.put(tokens[0], tokens[1]);
                            }
                        }
                    }
                }
            }
        }
        return params;
    }

    @SuppressWarnings("unchecked")
    protected Map> getLookupTable(Map params, Router router,
            IRouterContext routingContext) {
        final String CTX_CACHE_KEY = LOOKUP_TABLE_KEY + "." + params.get("TABLENAME");
        Map> lookupMap = (Map>) routingContext.getContextCache().get(
                CTX_CACHE_KEY);
        if (lookupMap == null) {
            final Map> fillMap = new HashMap>();
            jdbcTemplate.query(String.format("select %s, %s from %s", params.get(PARAM_MAPPED_KEY_COLUMN),
                    params.get(PARAM_EXTERNAL_ID_COLUMN), params.get(PARAM_TABLE)),
                    new RowCallbackHandler() {
                        public void processRow(ResultSet rs) throws SQLException {
                            String key = rs.getString(1);
                            Set set = fillMap.get(key);
                            if (set == null) {
                                set = new HashSet();
                                fillMap.put(key, set);
                            }
                            set.add(rs.getString(2));
                        }
                    });
            lookupMap = fillMap;
            routingContext.getContextCache().put(CTX_CACHE_KEY, lookupMap);
        }
        return lookupMap;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy