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

io.bigdime.core.handler.AbstractHandler Maven / Gradle / Ivy

There is a newer version: 0.9.3
Show newest version
/**
 * Copyright (C) 2015 Stubhub.
 */
package io.bigdime.core.handler;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import io.bigdime.alert.LoggerFactory;
import io.bigdime.core.ActionEvent;
import io.bigdime.core.AdaptorConfigurationException;
import io.bigdime.core.DataChannel;
import io.bigdime.core.Handler;
import io.bigdime.core.HandlerException;
import io.bigdime.core.InputDescriptor;
import io.bigdime.core.commons.AdaptorLogger;
import io.bigdime.core.config.AdaptorConfig;
import io.bigdime.core.config.AdaptorConfigConstants.HandlerConfigConstants;
import io.bigdime.core.config.AdaptorConfigConstants.SourceConfigConstants;
import io.bigdime.core.constants.ActionEventHeaderConstants;
import io.bigdime.core.runtimeinfo.RuntimeInfo;
import io.bigdime.core.runtimeinfo.RuntimeInfoStore;
import io.bigdime.core.runtimeinfo.RuntimeInfoStore.Status;
import io.bigdime.core.runtimeinfo.RuntimeInfoStoreException;

/**
 * Abstract implementation of Handler.
 * 
 * @author Neeraj Jain
 *
 */

public abstract class AbstractHandler implements Handler {
	private static final AdaptorLogger logger = new AdaptorLogger(LoggerFactory.getLogger(AbstractHandler.class));
	private final String id = UUID.randomUUID().toString();
	private State state;
	/**
	 * Name of this handler.
	 */
	private String name;
	private int index;

	/**
	 * Invocation count for this handler.
	 */
	private long invocationCount;

	/**
	 * Properties set for this handler.
	 */
	private Map propertyMap;

	/**
	 * Map from input to outputChannel, defines which outputChannel the data from an input should be sent to.
	 * @formatter:off
	 * e.g. "outputChannel-map" : "input1:channel1, input2:channel2",
	 * means input1's data should be sent to channel1 and input2's data should be sent to channel2.
	 * @formatter:on
	 */
	private DataChannel outputChannel;

	private String[] getInputChannelArray(String channelMapValue) {
		return channelMapValue.split(","); // spilt "input1:channel1,
											// input2:channel2"
	}

	@Override
	public void build() throws AdaptorConfigurationException {
		logger.info("building handler", "handler_index=\"{}\" handler_name=\"{}\" properties=\"{}\"", getIndex(),
				getName(), getPropertyMap());
		@SuppressWarnings("unchecked")
		Entry srcDesc = (Entry) getPropertyMap().get(SourceConfigConstants.SRC_DESC);
		logger.info("building handler", "handler_name=\"{}\" \"src_desc\"=\"{}\" handler=\"{}\"", getName(), srcDesc,
				this.getId());
		if (srcDesc != null) {
			String srcDescInputName = srcDesc.getValue();
			if (getPropertyMap().containsKey(HandlerConfigConstants.CHANNEL_MAP)) {
				String channelMapValue = getPropertyMap().get(HandlerConfigConstants.CHANNEL_MAP).toString();
				logger.debug("building handler", "handler_name=\"{}\" channel_map=\"{}\"", getName(), channelMapValue);
				String[] inputChannelArray = getInputChannelArray(channelMapValue);

				final Map channelMap = AdaptorConfig.getInstance().getAdaptorContext()
						.getChannelMap();

				for (String inputChannelValue : inputChannelArray) {
					String[] inputChannelValuesMap = inputChannelValue.split(":");
					if (inputChannelValuesMap.length != 2) {
						throw new AdaptorConfigurationException("value must be in input:channel format");
					}
					String inputName = inputChannelValuesMap[0].trim();
					if (!inputName.equals(srcDescInputName)) {
						continue;
					}
					setOutputChannel(channelMap.get(inputChannelValuesMap[1].trim()));
					if (getOutputChannel() == null) {
						throw new AdaptorConfigurationException(
								"invalid value of outputChannel, outputChannel with name=" + inputName + " not found");
					}
					break;
				}

				if (outputChannel == null) {
					throw new AdaptorConfigurationException("no channel mapped for input=" + srcDescInputName);
				}
				logger.debug("building handler", "handler_name=\"{}\" src_desc=\"{}\" outputChannel=\"{}\"", getName(),
						srcDescInputName, outputChannel.getName());
			}
		}
	}

	@Override
	public String getId() {
		return id;
	}

	protected boolean setState(final State state) {
		if (this.state == state) {
			return false;
		}
		this.state = state;
		return true;
	}

	@Override
	public State getState() {
		return state;
	}

	@Override
	public void shutdown() {
		state = State.TERMINATED;
	}

	@Override
	public String getName() {
		return name;
	}

	@Override
	public void setName(String name) {
		this.name = name;
	}

	@Override
	public void setPropertyMap(Map propertyMap) {
		this.propertyMap = propertyMap;
	}

	protected Map getPropertyMap() {
		return propertyMap;
	}

	public DataChannel getOutputChannel() {
		return outputChannel;
	}

	protected void setOutputChannel(DataChannel outputChannel) {
		this.outputChannel = outputChannel;
	}

	/**
	 * 
	 * @param runtimeInfoStore
	 *            store to get from and save to runtime information
	 * @param entityName
	 *            entity that the runtime information belongs to
	 * @param availableDescriptors
	 *            list of descriptors(files, tables etc) that are available to
	 *            this handler
	 * @param inputDescriptor
	 *            descriptor
	 * @return
	 * @throws RuntimeInfoStoreException
	 */
	protected  T getNextDescriptorToProcess(final RuntimeInfoStore runtimeInfoStore,
			final String entityName, List availableDescriptors, final InputDescriptor inputDescriptor)
					throws RuntimeInfoStoreException {
		final List runtimeInfos = runtimeInfoStore.getAll(AdaptorConfig.getInstance().getName(),
				entityName);
		logger.debug(getHandlerPhase(), "runtimeInfos=\"{}\"", runtimeInfos);

		final RuntimeInfo runtimeInfo = runtimeInfoStore.getLatest(AdaptorConfig.getInstance().getName(), entityName);
		logger.debug(getHandlerPhase(), "latestRuntimeInfo=\"{}\"", runtimeInfo);
		T nextDescriptorToProcess = null;
		if (runtimeInfo == null) {
			nextDescriptorToProcess = availableDescriptors.get(0);
		} else {
			logger.debug(getHandlerPhase(), "handler_id=\"{}\" latestRuntimeInfo=\"{}\"", getId(), runtimeInfo);
			String lastRuntimeInfoDescriptor = runtimeInfo.getInputDescriptor();
			nextDescriptorToProcess = inputDescriptor.getNext(availableDescriptors, lastRuntimeInfoDescriptor);
			logger.debug(getHandlerPhase(), "computed nextDescriptorToProcess=\"{}\"", nextDescriptorToProcess);
		}
		return nextDescriptorToProcess;
	}

	protected RuntimeInfo getOneQueuedRuntimeInfo(final RuntimeInfoStore runtimeInfoStore,
			final String entityName) throws RuntimeInfoStoreException {
		final List runtimeInfos = runtimeInfoStore.getAll(AdaptorConfig.getInstance().getName(),
				entityName, RuntimeInfoStore.Status.QUEUED);
		logger.debug(getHandlerPhase(), "queued_runtimeInfos=\"{}\"", runtimeInfos);
		if (runtimeInfos != null && !runtimeInfos.isEmpty()) {
			return runtimeInfos.get(0);
		}
		return null;
	}

	protected List getAllStartedRuntimeInfos(final RuntimeInfoStore runtimeInfoStore,
			final String entityName) throws RuntimeInfoStoreException {
		final List runtimeInfos = runtimeInfoStore.getAll(AdaptorConfig.getInstance().getName(),
				entityName, RuntimeInfoStore.Status.STARTED);
		logger.debug(getHandlerPhase(), "started_runtimeInfos=\"{}\"", runtimeInfos);
		return runtimeInfos;
	}

	/**
	 * 
	 * Update RuntimeInfoStore with the status as Started.
	 * 
	 * @param runtimeInfoStore
	 * @param entityName
	 * @param inputDescriptor
	 * @return true if the update was successful, false otherwise
	 * @throws RuntimeInfoStoreException
	 */
	protected  boolean addRuntimeInfo(final RuntimeInfoStore runtimeInfoStore, final String entityName,
			final String inputDescriptor) throws RuntimeInfoStoreException {
		return updateRuntimeInfo(runtimeInfoStore, entityName, inputDescriptor, RuntimeInfoStore.Status.STARTED);
	}

	protected  boolean queueRuntimeInfo(final RuntimeInfoStore runtimeInfoStore,
			final String entityName, final String inputDescriptor) throws RuntimeInfoStoreException {
		if (runtimeInfoStore.get(AdaptorConfig.getInstance().getName(), entityName, inputDescriptor) == null) {
			logger.info(getHandlerPhase(), "queueing adaptorName=\"{}\" entityName={} inputDescriptor={}",
					AdaptorConfig.getInstance().getName(), entityName, inputDescriptor);
			return updateRuntimeInfo(runtimeInfoStore, entityName, inputDescriptor, RuntimeInfoStore.Status.QUEUED);
		} else {
			logger.debug(getHandlerPhase(), "already in progress, adaptorName=\"{}\" entityName={} inputDescriptor={}",
					AdaptorConfig.getInstance().getName(), entityName, inputDescriptor);

		}
		return false;
	}

	protected  boolean updateRuntimeInfoToStoreAfterValidation(final RuntimeInfoStore runtimeInfoStore,
			boolean validationPassed, ActionEvent actionEvent) throws RuntimeInfoStoreException {
		
		String entityName = actionEvent.getHeaders().get(ActionEventHeaderConstants.ENTITY_NAME);	
		String inputDescriptor = actionEvent.getHeaders().get(ActionEventHeaderConstants.INPUT_DESCRIPTOR);
		Map properties = actionEvent.getHeaders();
		if (validationPassed) {
			return updateRuntimeInfo(runtimeInfoStore, entityName, inputDescriptor, Status.VALIDATED, properties);
		} else {
			return updateRuntimeInfo(runtimeInfoStore, entityName, inputDescriptor, Status.FAILED, properties);
		}
	}

	protected  boolean updateRuntimeInfo(final RuntimeInfoStore runtimeInfoStore,
			final String entityName, final String inputDescriptor, RuntimeInfoStore.Status status)
					throws RuntimeInfoStoreException {
		return updateRuntimeInfo(runtimeInfoStore, entityName, inputDescriptor, status, null);
	}

	protected  boolean updateRuntimeInfo(final RuntimeInfoStore runtimeInfoStore,
			final String entityName, final String inputDescriptor, RuntimeInfoStore.Status status,
			Map properties) throws RuntimeInfoStoreException {
		RuntimeInfo startingRuntimeInfo = new RuntimeInfo();
		startingRuntimeInfo.setAdaptorName(AdaptorConfig.getInstance().getName());
		startingRuntimeInfo.setEntityName(entityName);
		startingRuntimeInfo.setInputDescriptor(inputDescriptor);
		startingRuntimeInfo.setStatus(status);
		startingRuntimeInfo.setProperties(properties);
		logger.debug(getHandlerPhase(), "updating runtime info store, calling put");
		return runtimeInfoStore.put(startingRuntimeInfo);
	}

	/**
	 * Get the context from ThreadLocal.
	 * 
	 * @return
	 */
	protected HandlerContext getHandlerContext() {
		return HandlerContext.get();
	}

	/**
	 * Get the journal for this handler.
	 * 
	 * @return
	 */
	// protected Object getJournal() {
	// return getHandlerContext().getJournal(getId());
	// }

	@SuppressWarnings("unchecked")
	protected  T getJournal(Class clazz) throws HandlerException {
		return (T) getHandlerContext().getJournal(getId());
	}

	protected  T getNonNullJournal(Class clazz) throws HandlerException {
		// return (T) getHandlerContext().getJournal(getId());
		T journal = getJournal(clazz);
		if (journal == null) {
			try {
				journal = clazz.newInstance();
			} catch (InstantiationException | IllegalAccessException ex) {
				throw new HandlerException(ex);
			}
		}
		getHandlerContext().setJournal(getId(), journal);
		return journal;
	}

	/**
	 * Set the journal for this handler.
	 * 
	 * @param journal
	 */
	protected void setJournal(HandlerJournal journal) {
		getHandlerContext().setJournal(getId(), journal);
	}

	protected String getHandlerPhase() {
		return "processing abstractHandler";
	}

	/**
	 * @param outputEvent
	 */
	protected void processChannelSubmission(final ActionEvent outputEvent) {
		logger.debug(getHandlerPhase(), "checking channel submission, output_channel=\"{}\"", getOutputChannel());
		if (getOutputChannel() != null) {
			logger.debug(getHandlerPhase(), "submitting to channel");
			getOutputChannel().put(outputEvent);
		}
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractHandler other = (AbstractHandler) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	@Override
	public void handleException() {
		// default implementation does nothing.
	}

	@Override
	public void setIndex(final int index) {
		this.index = index;
	}

	@Override
	public int getIndex() {
		return index;
	}

	public long getInvocationCount() {
		return invocationCount;
	}

	public void incrementInvocationCount() {
		this.invocationCount++;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy