/**
* 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 General Public License, version 3.0 (GPLv3)
* (the "License"); you may not use this file except in compliance
* with the License.
*
* You should have received a copy of the GNU General Public License,
* version 3.0 (GPLv3) along with this library; if not, see
* <http://www.gnu.org/licenses/>.
*
* 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.service.impl;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jumpmind.db.sql.ISqlRowMapper;
import org.jumpmind.db.sql.ISqlTemplate;
import org.jumpmind.db.sql.Row;
import org.jumpmind.symmetric.ISymmetricEngine;
import org.jumpmind.symmetric.common.ParameterConstants;
import org.jumpmind.symmetric.model.Grouplet;
import org.jumpmind.symmetric.model.Grouplet.GroupletLinkPolicy;
import org.jumpmind.symmetric.model.GroupletLink;
import org.jumpmind.symmetric.model.Node;
import org.jumpmind.symmetric.model.TriggerRouter;
import org.jumpmind.symmetric.model.TriggerRouterGrouplet;
import org.jumpmind.symmetric.model.TriggerRouterGrouplet.AppliesWhen;
import org.jumpmind.symmetric.service.IGroupletService;
public class GroupletService extends AbstractService implements IGroupletService {
protected ISymmetricEngine engine;
protected List<Grouplet> cache;
protected long lastCacheTime = 0;
private Date lastUpdateTime;
public GroupletService(ISymmetricEngine engine) {
super(engine.getParameterService(), engine.getSymmetricDialect());
this.engine = engine;
setSqlMap(new GroupletServiceSqlMap(symmetricDialect.getPlatform(),
createSqlReplacementTokens()));
}
public boolean refreshFromDatabase() {
Date date1 = sqlTemplate.queryForObject(getSql("selectMaxGroupletLastUpdateTime"), Date.class);
Date date2 = sqlTemplate.queryForObject(getSql("selectMaxGroupletLinkLastUpdateTime"), Date.class);
Date date3 = sqlTemplate.queryForObject(getSql("selectMaxTriggerRouterGroupletLastUpdateTime"), Date.class);
Date date = maxDate(date1, date2, date3);
if (date != null) {
if (lastUpdateTime == null || lastUpdateTime.before(date)) {
if (lastUpdateTime != null) {
log.info("Newer grouplet settings were detected");
}
lastUpdateTime = date;
clearCache();
return true;
}
}
return false;
}
public void clearCache() {
lastCacheTime = 0;
}
public boolean isSourceEnabled(TriggerRouter triggerRouter) {
boolean enabled = true;
Node node = engine.getNodeService().findIdentity();
if (node == null) {
enabled = false;
} else {
List<Grouplet> grouplets = getGroupletsFor(triggerRouter, AppliesWhen.S, false);
if (grouplets != null && grouplets.size() > 0) {
enabled = false;
for (Grouplet grouplet : grouplets) {
GroupletLinkPolicy policy = grouplet.getGroupletLinkPolicy();
List<GroupletLink> links = grouplet.getGroupletLinks();
boolean foundMatch = false;
for (GroupletLink groupletLink : links) {
if (groupletLink.getExternalId().equals(node.getExternalId())) {
foundMatch = true;
}
}
if ((foundMatch && policy == GroupletLinkPolicy.I)
|| (!foundMatch && policy == GroupletLinkPolicy.E)) {
enabled = true;
}
}
}
}
return enabled;
}
public boolean isTargetEnabled(TriggerRouter triggerRouter, Node node) {
Set<Node> nodes = new HashSet<Node>(1);
nodes.add(node);
return getTargetEnabled(triggerRouter, nodes).size() > 0;
}
public Set<Node> getTargetEnabled(TriggerRouter triggerRouter, Set<Node> nodes) {
Set<Node> matchedNodes = new HashSet<Node>();
Set<Node> excludedNodes = new HashSet<Node>();
List<Grouplet> grouplets = getGroupletsFor(triggerRouter, AppliesWhen.T, false);
if (grouplets != null && grouplets.size() > 0) {
for (Grouplet grouplet : grouplets) {
GroupletLinkPolicy policy = grouplet.getGroupletLinkPolicy();
List<GroupletLink> links = grouplet.getGroupletLinks();
for (GroupletLink groupletLink : links) {
for (Node node : nodes) {
if (groupletLink.getExternalId().equals(node.getExternalId())) {
if (policy == GroupletLinkPolicy.I) {
matchedNodes.add(node);
} else {
excludedNodes.add(node);
}
}
}
}
}
Set<Node> toReturn = new HashSet<Node>();
excludedNodes.removeAll(matchedNodes);
if (excludedNodes.size() > 0) {
toReturn.addAll(nodes);
toReturn.removeAll(excludedNodes);
} else {
toReturn.addAll(matchedNodes);
}
return toReturn;
} else {
return nodes;
}
}
public List<Grouplet> getGrouplets(boolean refreshCache) {
long maxCacheTime = parameterService
.getLong(ParameterConstants.CACHE_TIMEOUT_GROUPLETS_IN_MS);
List<Grouplet> all = cache;
if (all == null || System.currentTimeMillis() - lastCacheTime >= maxCacheTime
|| lastCacheTime == 0 || refreshCache) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
final Map<String, Grouplet> groupletMap = new HashMap<String, Grouplet>();
all = sqlTemplate.query(getSql("selectGroupletSql"), new ISqlRowMapper<Grouplet>() {
public Grouplet mapRow(Row rs) {
Grouplet grouplet = new Grouplet();
grouplet.setGroupletId(rs.getString("grouplet_id"));
grouplet.setDescription(rs.getString("description"));
grouplet.setGroupletLinkPolicy(GroupletLinkPolicy.valueOf(rs
.getString("grouplet_link_policy")));
grouplet.setCreateTime(rs.getDateTime("create_time"));
grouplet.setLastUpdateBy(rs.getString("last_update_by"));
grouplet.setLastUpdateTime(rs.getDateTime("last_update_time"));
groupletMap.put(grouplet.getGroupletId(), grouplet);
return grouplet;
}
});
sqlTemplate.query(getSql("selectGroupletLinkSql"), new ISqlRowMapper<GroupletLink>() {
public GroupletLink mapRow(Row rs) {
GroupletLink groupletLink = new GroupletLink();
String groupletId = rs.getString("grouplet_id");
Grouplet grouplet = groupletMap.get(groupletId);
groupletLink.setExternalId(rs.getString("external_id"));
groupletLink.setCreateTime(rs.getDateTime("create_time"));
groupletLink.setLastUpdateBy(rs.getString("last_update_by"));
groupletLink.setLastUpdateTime(rs.getDateTime("last_update_time"));
if (grouplet != null) {
grouplet.getGroupletLinks().add(groupletLink);
}
return groupletLink;
}
});
sqlTemplate.query(getSql("selectTriggerRouterGroupletSql"),
new ISqlRowMapper<TriggerRouterGrouplet>() {
public TriggerRouterGrouplet mapRow(Row rs) {
TriggerRouterGrouplet trGrouplet = new TriggerRouterGrouplet();
String groupletId = rs.getString("grouplet_id");
Grouplet grouplet = groupletMap.get(groupletId);
trGrouplet.setAppliesWhen(AppliesWhen.valueOf(rs
.getString("applies_when")));
trGrouplet.setRouterId(rs.getString("router_id"));
trGrouplet.setTriggerId(rs.getString("trigger_id"));
trGrouplet.setCreateTime(rs.getDateTime("create_time"));
trGrouplet.setLastUpdateBy(rs.getString("last_update_by"));
trGrouplet.setLastUpdateTime(rs.getDateTime("last_update_time"));
if (grouplet != null) {
grouplet.getTriggerRouterGrouplets().add(trGrouplet);
}
return trGrouplet;
}
});
cache = all;
lastCacheTime = System.currentTimeMillis();
}
return all;
}
protected List<Grouplet> getGroupletsFor(TriggerRouter triggerRouter, AppliesWhen appliesWhen,
boolean refreshCache) {
List<Grouplet> all = getGrouplets(refreshCache);
List<Grouplet> grouplets = new ArrayList<Grouplet>();
for (Grouplet grouplet : all) {
List<TriggerRouterGrouplet> trGrouplets = grouplet.getTriggerRouterGrouplets();
for (TriggerRouterGrouplet trGrouplet : trGrouplets) {
if (trGrouplet.getTriggerId().equals(triggerRouter.getTrigger().getTriggerId())
&& trGrouplet.getRouterId().equals(triggerRouter.getRouter().getRouterId())
&& (trGrouplet.getAppliesWhen() == appliesWhen || trGrouplet.getAppliesWhen() == AppliesWhen.B)) {
grouplets.add(grouplet);
}
}
}
return grouplets;
}
public void saveGrouplet(Grouplet grouplet) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
grouplet.setLastUpdateTime(new Date());
if (sqlTemplate.update(
getSql("updateGroupletSql"),
new Object[] { grouplet.getGroupletLinkPolicy().name(), grouplet.getDescription(),
grouplet.getCreateTime(), grouplet.getLastUpdateBy(),
grouplet.getLastUpdateTime(), grouplet.getGroupletId() }, new int[] {
Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR,
Types.TIMESTAMP, Types.VARCHAR }) == 0) {
grouplet.setCreateTime(new Date());
sqlTemplate.update(
getSql("insertGroupletSql"),
new Object[] { grouplet.getGroupletLinkPolicy().name(),
grouplet.getDescription(), grouplet.getCreateTime(),
grouplet.getLastUpdateBy(), grouplet.getLastUpdateTime(),
grouplet.getGroupletId() }, new int[] { Types.VARCHAR, Types.VARCHAR,
Types.TIMESTAMP, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR });
}
}
public void deleteGrouplet(Grouplet grouplet) {
List<GroupletLink> links = grouplet.getGroupletLinks();
for (GroupletLink link : links) {
deleteGroupletLink(grouplet, link);
}
List<TriggerRouterGrouplet> triggerRouters = grouplet.getTriggerRouterGrouplets();
for (TriggerRouterGrouplet triggerRouterGrouplet : triggerRouters) {
deleteTriggerRouterGrouplet(grouplet, triggerRouterGrouplet);
}
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
sqlTemplate.update(getSql("deleteGroupletSql"), new Object[] { grouplet.getGroupletId() },
new int[] { Types.VARCHAR });
}
public void saveGroupletLink(Grouplet grouplet, GroupletLink link) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
link.setLastUpdateTime(new Date());
if (sqlTemplate.update(
getSql("updateGroupletLinkSql"),
new Object[] { link.getCreateTime(), link.getLastUpdateBy(),
link.getLastUpdateTime(), grouplet.getGroupletId(), link.getExternalId() },
new int[] { Types.TIMESTAMP, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR,
Types.VARCHAR }) == 0) {
link.setCreateTime(new Date());
sqlTemplate.update(getSql("insertGroupletLinkSql"), new Object[] {
link.getCreateTime(), link.getLastUpdateBy(), link.getLastUpdateTime(),
grouplet.getGroupletId(), link.getExternalId() }, new int[] { Types.TIMESTAMP,
Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR });
}
}
public void deleteGroupletLink(Grouplet grouplet, GroupletLink link) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
sqlTemplate.update(getSql("deleteGroupletLinkSql"), new Object[] {
grouplet.getGroupletId(), link.getExternalId() }, new int[] { Types.VARCHAR,
Types.VARCHAR });
}
public void saveTriggerRouterGrouplet(Grouplet grouplet,
TriggerRouterGrouplet triggerRouterGrouplet) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
triggerRouterGrouplet.setLastUpdateTime(new Date());
if (sqlTemplate.update(getSql("updateTriggerRouterGroupletSql"), new Object[] {
triggerRouterGrouplet.getCreateTime(), triggerRouterGrouplet.getLastUpdateBy(),
triggerRouterGrouplet.getLastUpdateTime(), grouplet.getGroupletId(),
triggerRouterGrouplet.getAppliesWhen().name(),
triggerRouterGrouplet.getTriggerId(), triggerRouterGrouplet.getRouterId() },
new int[] { Types.TIMESTAMP, Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR,
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR }) == 0) {
triggerRouterGrouplet.setCreateTime(new Date());
sqlTemplate.update(
getSql("insertTriggerRouterGroupletSql"),
new Object[] { triggerRouterGrouplet.getCreateTime(),
triggerRouterGrouplet.getLastUpdateBy(),
triggerRouterGrouplet.getLastUpdateTime(), grouplet.getGroupletId(),
triggerRouterGrouplet.getAppliesWhen().name(),
triggerRouterGrouplet.getTriggerId(),
triggerRouterGrouplet.getRouterId() }, new int[] { Types.TIMESTAMP,
Types.VARCHAR, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR,
Types.VARCHAR, Types.VARCHAR });
}
}
public void deleteTriggerRouterGroupletsFor(TriggerRouter triggerRouter) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
sqlTemplate
.update(getSql("deleteTriggerRouterGroupletForSql"),
new Object[] {
triggerRouter.getTrigger().getTriggerId(),
triggerRouter.getRouter().getRouterId() }, new int[] { Types.VARCHAR,
Types.VARCHAR });
}
public void deleteTriggerRouterGrouplet(Grouplet grouplet,
TriggerRouterGrouplet triggerRouterGrouplet) {
ISqlTemplate sqlTemplate = platform.getSqlTemplate();
sqlTemplate
.update(getSql("deleteTriggerRouterGroupletSql"),
new Object[] { grouplet.getGroupletId(),
triggerRouterGrouplet.getAppliesWhen().name(),
triggerRouterGrouplet.getTriggerId(),
triggerRouterGrouplet.getRouterId() }, new int[] { Types.VARCHAR,
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR });
}
}