/* It is a application for event distribution to event n-consumers with m-sources. Copyright (C) 2010 "Imran M Yousuf <imran@smartitengineering.com>" 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 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, see <http://www.gnu.org/licenses/>. */ package com.smartitengineering.event.hub.spi.db; import com.smartitengineering.dao.common.CommonReadDao; import com.smartitengineering.dao.common.CommonWriteDao; import com.smartitengineering.dao.common.queryparam.MatchMode; import com.smartitengineering.dao.common.queryparam.Order; import com.smartitengineering.dao.common.queryparam.QueryParameter; import com.smartitengineering.dao.common.queryparam.QueryParameterFactory; import com.smartitengineering.event.hub.api.Channel; import com.smartitengineering.event.hub.api.Event; import com.smartitengineering.event.hub.spi.HubPersistentStorer; import com.smartitengineering.util.bean.adapter.GenericAdapter; import java.util.AbstractMap.SimpleEntry; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; /** * A Smart DAO based {@link HubPersistentStorer} implementation. * @author imyousuf */ public class DBPersistentStorer implements HubPersistentStorer { private CommonReadDao<PersistentChannel, Integer> channelReadDao; private CommonReadDao<PersistentEvent, Integer> eventReadDao; private CommonWriteDao<PersistentChannel> channelWriteDao; private CommonWriteDao<PersistentEvent> eventWriteDao; private GenericAdapter<Channel, PersistentChannel> channelConverter; private GenericAdapter<Event, PersistentEvent> eventConverter; public void setChannelConverter( GenericAdapter<Channel, PersistentChannel> channelConverter) { this.channelConverter = channelConverter; } public void setChannelReadDao(CommonReadDao<PersistentChannel, Integer> channelReadDao) { this.channelReadDao = channelReadDao; } public void setChannelWriteDao( CommonWriteDao<PersistentChannel> channelWriteDao) { this.channelWriteDao = channelWriteDao; } public void setEventConverter( GenericAdapter<Event, PersistentEvent> eventConverter) { this.eventConverter = eventConverter; } public void setEventReadDao(CommonReadDao<PersistentEvent, Integer> eventReadDao) { this.eventReadDao = eventReadDao; } public void setEventWriteDao(CommonWriteDao<PersistentEvent> eventWriteDao) { this.eventWriteDao = eventWriteDao; } protected GenericAdapter<Channel, PersistentChannel> getChannelConverter() { return channelConverter; } protected CommonReadDao<PersistentChannel, Integer> getChannelReadDao() { return channelReadDao; } protected CommonWriteDao<PersistentChannel> getChannelWriteDao() { return channelWriteDao; } protected GenericAdapter<Event, PersistentEvent> getEventConverter() { return eventConverter; } protected CommonReadDao<PersistentEvent, Integer> getEventReadDao() { return eventReadDao; } protected CommonWriteDao<PersistentEvent> getEventWriteDao() { return eventWriteDao; } @Override public void create(Channel channel) { PersistentChannel persistentChannel = getChannelConverter().convert(channel); if (persistentChannel == null) { return; } final Date date = new Date(); persistentChannel.setCreationDateTime(date); persistentChannel.setLastModifiedDateTime(date); getChannelWriteDao().save(persistentChannel); } @Override public void update(Channel channel) { PersistentChannel persistentChannel = getMergedPersistentChannel(channel); if (persistentChannel != null) { persistentChannel.setLastModifiedDateTime(new Date()); getChannelWriteDao().update(persistentChannel); } } @Override public void delete(Channel channel) { PersistentChannel persistentChannel = getMergedPersistentChannel(channel); if (persistentChannel != null) { getChannelWriteDao().delete(persistentChannel); } } @Override public Channel getChannel(String channelName) { PersistentChannel persistentChannel = getPersistentChannel(channelName); return getChannelConverter().convertInversely(persistentChannel); } @Override public Event create(Channel channel, Event event) { PersistentEvent persistentEvent = getEventConverter().convert(event); if (persistentEvent != null && channel != null) { persistentEvent.setChannelId(channel.getName()); persistentEvent.setCreationDateTime(new Date()); getEventWriteDao().save(persistentEvent); return getEventConverter().convertInversely(persistentEvent); } return null; } @Override public void delete(Event event) { PersistentEvent persistentEvent = getMergedPersistentEvent(event); if (persistentEvent != null) { getEventWriteDao().delete(persistentEvent); } } @Override public Event getEvent(String placeholderId) { PersistentEvent persistentEvent = getPersistentEvent(placeholderId); return getEventConverter().convertInversely(persistentEvent); } @Override public Event getEventByUUID(String uuid) { if (StringUtils.isBlank(uuid)) { return null; } PersistentEvent event = getEventReadDao().getSingle(QueryParameterFactory.getStringLikePropertyParam( PersistentEvent.UUID, uuid, MatchMode.EXACT)); return getEventConverter().convertInversely(event); } @Override public LinkedHashSet<Event> getEvents(String placeholderId, String channelId, int count) { int placeholderIdInt = NumberUtils.toInt(placeholderId); if (count == 0) { return new LinkedHashSet<Event>(); } else { List<QueryParameter> params = new ArrayList<QueryParameter>(); final QueryParameter<Order> orderByParam; if (placeholderIdInt > -1) { final QueryParameter<Integer> propertyParam; if (count > 0) { propertyParam = QueryParameterFactory.getGreaterThanPropertyParam(PersistentEvent.PLACE_HOLDER_ID, placeholderIdInt); orderByParam = QueryParameterFactory.getOrderByParam(PersistentEvent.PLACE_HOLDER_ID, Order.ASC); } else { propertyParam = QueryParameterFactory.getLesserThanPropertyParam(PersistentEvent.PLACE_HOLDER_ID, placeholderIdInt); orderByParam = QueryParameterFactory.getOrderByParam(PersistentEvent.PLACE_HOLDER_ID, Order.DESC); } params.add(propertyParam); } else { orderByParam = QueryParameterFactory.getOrderByParam(PersistentEvent.PLACE_HOLDER_ID, Order.DESC); } if (StringUtils.isNotBlank(channelId)) { params.add(QueryParameterFactory.getStringLikePropertyParam(PersistentEvent.CHANNEL_ID, channelId, MatchMode.EXACT)); } params.addAll(Arrays.asList(QueryParameterFactory.getMaxResultsParam(Math.abs(count)), orderByParam)); List<PersistentEvent> persistentEvents = getEventReadDao().getList(params); if (count > 0 && placeholderIdInt > -1) { Collections.reverse(persistentEvents); } if (persistentEvents == null || persistentEvents.isEmpty()) { return new LinkedHashSet<Event>(); } return new LinkedHashSet<Event>(getEventConverter().convertInversely(persistentEvents.toArray(new PersistentEvent[persistentEvents. size()]))); } } @Override public Collection<Channel> getChannels(int startIndex, int count) { if (startIndex < 0 || count == 0) { return Collections.emptyList(); } final QueryParameter<Integer> idParam; List<QueryParameter> params = new ArrayList<QueryParameter>(); final QueryParameter<Order> orderByParam; if (count > 0) { idParam = QueryParameterFactory.getGreaterThanPropertyParam("id", startIndex); orderByParam = QueryParameterFactory.getOrderByParam("id", Order.ASC); } else { idParam = QueryParameterFactory.getLesserThanPropertyParam("id", startIndex); orderByParam = QueryParameterFactory.getOrderByParam("id", Order.DESC); } params.add(idParam); params.addAll(Arrays.asList(QueryParameterFactory.getMaxResultsParam(Math.abs(count)), orderByParam)); List<PersistentChannel> channels = getChannelReadDao().getList(params); if (count > 0) { Collections.reverse(channels); } return getChannelConverter().convertInversely(channels.toArray(new PersistentChannel[channels.size()])); } protected PersistentChannel getMergedPersistentChannel(Channel channel) { if (channel == null) { return null; } PersistentChannel persistentChannel = getPersistentChannel(channel.getName()); Map.Entry<Channel, PersistentChannel> entry; entry = new SimpleEntry<Channel, PersistentChannel>(channel, persistentChannel); getChannelConverter().merge(entry); return persistentChannel; } protected PersistentChannel getPersistentChannel(String channelName) { PersistentChannel persistentChannel = getChannelReadDao().getSingle( QueryParameterFactory.getStringLikePropertyParam(PersistentChannel.NAME, channelName.toLowerCase(), MatchMode.EXACT)); return persistentChannel; } protected PersistentEvent getMergedPersistentEvent(Event event) { if (event == null) { return null; } PersistentEvent persistentEvent = getPersistentEvent(event.getPlaceholderId()); Map.Entry<Event, PersistentEvent> entry; entry = new SimpleEntry<Event, PersistentEvent>(event, persistentEvent); getEventConverter().merge(entry); return persistentEvent; } protected PersistentEvent getPersistentEvent(String placeholderId) { int placeholderIdInt = NumberUtils.toInt(placeholderId); if (placeholderIdInt <= 0) { return null; } PersistentEvent persistentEvent = getEventReadDao().getSingle( QueryParameterFactory.getEqualPropertyParam( PersistentEvent.PLACE_HOLDER_ID, placeholderIdInt)); return persistentEvent; } }