com.snaplogic.snaps.uniteller.BaseService.java Source code

Java tutorial

Introduction

Here is the source code for com.snaplogic.snaps.uniteller.BaseService.java

Source

/*
 * SnapLogic - Data Integration
 *
 * Copyright (C) 2014, SnapLogic, Inc. All rights reserved.
 *
 * This program is licensed under the terms of
 * the SnapLogic Commercial Subscription agreement
 *
 * "SnapLogic" is a trademark of SnapLogic, Inc.
 */
package com.snaplogic.snaps.uniteller;

import com.google.inject.Inject;
import com.snaplogic.account.api.capabilities.Accounts;
import com.snaplogic.api.ConfigurationException;
import com.snaplogic.api.ExecutionException;
import com.snaplogic.api.InputSchemaProvider;
import com.snaplogic.api.MetricsProvider;
import com.snaplogic.common.SnapType;
import com.snaplogic.common.metrics.Counter;
import com.snaplogic.common.properties.builders.PropertyBuilder;
import com.snaplogic.common.utilities.URLEncoder;
import com.snaplogic.snap.api.Document;
import com.snaplogic.snap.api.MetricsBuilder;
import com.snaplogic.snap.api.PropertyValues;
import com.snaplogic.snap.api.SimpleSnap;
import com.snaplogic.snap.api.SnapCategory;
import com.snaplogic.snap.api.SnapDataException;
import com.snaplogic.snap.api.capabilities.Category;
import com.snaplogic.snap.api.capabilities.Inputs;
import com.snaplogic.snap.api.capabilities.Outputs;
import com.snaplogic.snap.api.capabilities.Version;
import com.snaplogic.snap.api.capabilities.ViewType;
import com.snaplogic.snap.schema.api.SchemaBuilder;
import com.snaplogic.snap.schema.api.SchemaProvider;
import com.snaplogic.snaps.uniteller.Constants.SnapsModel;
import com.snaplogic.snaps.uniteller.bean.AccountBean;
import com.snaplogic.snaps.uniteller.util.Utilities;
import com.uniteller.support.common.IUFSConfigMgr;
import com.uniteller.support.common.IUFSSecurityMgr;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import static com.snaplogic.snaps.uniteller.Constants.*;
import static com.snaplogic.snaps.uniteller.Messages.*;

/**
 * Abstract base class for UniTeller snap pack which contains common snap properties, core logic.
 *
 * @author svatada
 */
@Inputs(min = 1, max = 1, accepts = { ViewType.DOCUMENT })
@Outputs(min = 1, max = 1, offers = { ViewType.DOCUMENT })
@Version(snap = 1)
@Category(snap = SnapCategory.TRANSFORM)
@Accounts(provides = { UniTellerBasicAuthAccount.class }, optional = false)
public abstract class BaseService extends SimpleSnap implements MetricsProvider, InputSchemaProvider {
    private SnapsModel snapsType;
    private Counter counter;
    private String resourceType;
    private boolean autoUpdatePsw;
    @Inject
    private Utilities util;
    @Inject
    private UniTellerBasicAuthAccount account;
    @Inject
    private URLEncoder urlEncoder;
    private static final Logger log = LoggerFactory.getLogger(BaseService.class);
    private static SimpleDateFormat sdtf = new SimpleDateFormat(DATETIME_FORMAT);
    private static SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);

    protected SnapsModel getSnapType() {
        return snapsType;
    }

    @Override
    public void defineProperties(final PropertyBuilder propertyBuilder) {
        propertyBuilder.describe(RESOURCE_PROP, RESOURCE_LABEL, RESOURCE_DESC)
                .withAllowedValues(RESOUCE_LIST.get(getSnapType().toString())).required().add();
        propertyBuilder.describe(CHNG_PSW_PROP, CHNG_PSW_LABEL, CHNG_PSW_DESC).type(SnapType.BOOLEAN)
                .defaultValue(true).add();
    }

    @Override
    public void defineInputSchema(SchemaProvider provider) {
        Class<?> classType = null;
        try {
            classType = Class.forName(getUFSReqClassType());
        } catch (ClassNotFoundException e) {
            log.error(e.getMessage(), e);
        }
        for (String viewName : provider.getRegisteredViewNames()) {
            SchemaBuilder schemaBuilder = provider.getSchemaBuilder(viewName);
            for (Method method : findSetters(classType)) {
                schemaBuilder.withChildSchema(
                        provider.createSchema(util.getDataTypes(method), method.getName().substring(3)));
            }
            schemaBuilder.build();
        }
    }

    @Override
    public void defineMetrics(final MetricsBuilder metricsBuilder) {
        counter = metricsBuilder.describe(DOCUMENT_COUNTER, COUNTER_DESCRIPTION).measuredIn(COUNTER_UNIT).counter();
    }

    @Override
    public void configure(final PropertyValues propertyValues) throws ConfigurationException {
        resourceType = propertyValues.get(RESOURCE_PROP).toString();
        autoUpdatePsw = propertyValues.get(CHNG_PSW_PROP);
    }

    @Override
    protected void process(Document document, String inputViewName) {
        try {
            AccountBean bean = account.connect();
            String UFSConfigFilePath = urlEncoder.validateAndEncodeURI(bean.getConfigFilePath(), PATTERN, null)
                    .toString();
            String UFSSecurityFilePath = urlEncoder
                    .validateAndEncodeURI(bean.getSecurityPermFilePath(), PATTERN, null).toString();
            /* instantiating USFCreationClient */
            Class<?> CustomUSFCreationClient = Class.forName(UFS_FOLIO_CREATION_CLIENT_PKG_URI);
            Constructor<?> constructor = CustomUSFCreationClient
                    .getDeclaredConstructor(new Class[] { IUFSConfigMgr.class, IUFSSecurityMgr.class });
            Object USFCreationClientObj = constructor.newInstance(CustomUFSConfigMgr.getInstance(UFSConfigFilePath),
                    CustomUFSSecurityMgr.getInstance(UFSSecurityFilePath));
            Method setAutoUpdatePsw = CustomUSFCreationClient.getDeclaredMethod("setAutoUpdatePsw", Boolean.TYPE);
            setAutoUpdatePsw.invoke(USFCreationClientObj, autoUpdatePsw);
            /* Preparing the request for USF */
            Object data;
            if (document != null && (data = document.get()) != null) {
                if (data instanceof Map) {
                    Map<String, Object> map = (Map<String, Object>) data;
                    Class<?> UFSRequest = Class.forName(getUFSReqClassType());
                    Object UFSRequestObj = UFSRequest.newInstance();
                    Object inputFieldValue = null;
                    Calendar cal = Calendar.getInstance();
                    for (Method method : UFSRequest.getDeclaredMethods()) {
                        if (isSetter(method)
                                && (inputFieldValue = map.get(method.getName().substring(3))) != null) {
                            try {
                                String paramType = method.getParameterTypes()[0].getName();
                                if (paramType.equalsIgnoreCase(String.class.getName())) {
                                    method.invoke(UFSRequest.cast(UFSRequestObj), String.valueOf(inputFieldValue));
                                } else if (paramType.equalsIgnoreCase(Double.class.getSimpleName())) {
                                    method.invoke(UFSRequest.cast(UFSRequestObj),
                                            Double.parseDouble(String.valueOf(inputFieldValue)));
                                } else if (paramType.equalsIgnoreCase(INT)) {
                                    method.invoke(UFSRequest.cast(UFSRequestObj),
                                            Integer.parseInt(String.valueOf(inputFieldValue)));
                                } else if (paramType.equalsIgnoreCase(Calendar.class.getName())) {
                                    try {
                                        cal.setTime(sdtf.parse(String.valueOf(inputFieldValue)));
                                    } catch (ParseException pe1) {
                                        try {
                                            cal.setTime(sdf.parse(String.valueOf(inputFieldValue)));
                                        } catch (ParseException pe) {
                                            writeToErrorView(
                                                    String.format(DATE_PARSER_ERROR, DATETIME_FORMAT, DATE_FORMAT),
                                                    pe.getMessage(), ERROR_RESOLUTION, pe);
                                        }
                                    }
                                    method.invoke(UFSRequest.cast(UFSRequestObj), cal);
                                }
                            } catch (IllegalArgumentException iae) {
                                writeToErrorView(String.format(ILLEGAL_ARGS_EXE, method.getName()),
                                        iae.getMessage(), ERROR_RESOLUTION, iae);
                            } catch (InvocationTargetException ite) {
                                writeToErrorView(ite.getTargetException().getMessage(), ite.getMessage(),
                                        ERROR_RESOLUTION, ite);
                            }
                        }
                    }
                    /* Invoking the request over USFCreationClient */
                    Object UFSResponseObj = null;
                    Method creationClientMethod = CustomUSFCreationClient
                            .getMethod(getCamelCaseForMethod(resourceType), UFSRequest);
                    try {
                        UFSResponseObj = creationClientMethod.invoke(USFCreationClientObj,
                                UFSRequest.cast(UFSRequestObj));
                    } catch (IllegalArgumentException iae) {
                        writeToErrorView(String.format(ILLEGAL_ARGS_EXE, creationClientMethod.getName()),
                                iae.getMessage(), ERROR_RESOLUTION, iae);
                    } catch (InvocationTargetException ite) {
                        writeToErrorView(ite.getTargetException().getMessage(), ite.getMessage(), ERROR_RESOLUTION,
                                ite);
                    }
                    if (null != UFSResponseObj) {
                        outputViews.write(documentUtility.newDocument(processResponseObj(UFSResponseObj)));
                        counter.inc();
                    }
                } else {
                    writeToErrorView(NO_DATA_ERRMSG, NO_DATA_WARNING, NO_DATA_REASON, NO_DATA_RESOLUTION);
                }
            }
        } catch (Exception ex) {
            writeToErrorView(ERRORMSG, ex.getMessage(), ERROR_RESOLUTION, ex);
        }
    }

    @Override
    public void cleanup() throws ExecutionException {
        // NOOP
    }

    /**
     * @param UFSResponseObj
     * @return Map
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException
     */
    public Map<String, Object> processResponseObj(Object UFSResponseObj)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Map<String, Object> map = new HashMap<String, Object>();
        /* Preparing the map to write the values to output */
        if (UFSResponseObj != null) {
            Class<? extends Object> UFSResponse = UFSResponseObj.getClass();
            for (Method method : findGetters(UFSResponse)) {
                if (method.getReturnType().isPrimitive() || method.getReturnType().isAssignableFrom(String.class)
                        || method.getReturnType().isAssignableFrom(Calendar.class)) {
                    map.put(method.getName().substring(3), method.invoke(UFSResponseObj));
                } else {
                    log.debug(method.toGenericString());
                    map.put(method.getName().substring(3), processNestedResponseObj(method.invoke(UFSResponseObj)));
                }
            }
        }
        return map;
    }

    /**
     * @param UFSResponseObj
     * @return Object
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     * @throws InvocationTargetException Object
     */
    public Object processNestedResponseObj(Object UFSResponseObj)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (UFSResponseObj == null) {
            return StringUtils.EMPTY;
        } else if (UFSResponseObj instanceof Object[]) {
            ArrayList<Object> list = new ArrayList<Object>();
            Object[] objArray = (Object[]) UFSResponseObj;
            for (Object obj : objArray) {
                list.add(processResponseObj(obj));
            }
            return list;
        } else {
            return processResponseObj(UFSResponseObj);
        }
    }

    /*
     * Returns absolute class type for UFS request object
     */
    private String getUFSReqClassType() {
        if (resourceType.equals(CHANGE_PASSWORD)) {
            return UNITELLER_CHANGE_PASS_PKG;
        } else if (resourceType.equals(INFO_MODIFY_TX)) {
            return UNITELLER_INFO_MODIFY;
        }
        return new StringBuilder().append(UNITELLER_PKG_PREFIX).append(resourceType).append(UNITELLER_REQ_TAG)
                .toString();
    }

    /*
     * Returns absolute class type for UFS response object
     */
    @SuppressWarnings("unused")
    private String getUFSRespClassType() {
        return new StringBuilder().append(UNITELLER_PKG_PREFIX).append(resourceType).append(UNITELLER_RESP_TAG)
                .toString();
    }

    /*
     * Returns absolute class type for UFS response object
     */
    private String getCamelCaseForMethod(String resourceType) {
        return new StringBuilder().append(StringUtils.substring(resourceType, 0, 1).toLowerCase())
                .append(StringUtils.substring(resourceType, 1)).toString();
    }

    /* Writes the exception records to error view */
    private void writeToErrorView(final String errMsg, final String errReason, final String errResoulution,
            Exception ex) {
        log.error(ex.getMessage(), ex);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(DOCNUM_TAG, counter.getStats());
        map.put(ERROR_TAG, errMsg);
        map.put(MESSAGE_TAG, ex.getLocalizedMessage());
        map.put(REASON_TAG, errReason);
        map.put(RESOLUTION_TAG, errResoulution);
        SnapDataException snapException = new SnapDataException(documentUtility.newDocument(map), ex.getMessage())
                .withReason(errReason).withResolution(errResoulution);
        errorViews.write(snapException);
    }

    /* Writes the error records to error view */
    private void writeToErrorView(final String errMsg, final String errReason, final String errResoulution,
            final String errResponse) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put(DOCNUM_TAG, counter.getStats());
        map.put(ERROR_TAG, errMsg);
        map.put(MESSAGE_TAG, errResponse);
        map.put(REASON_TAG, errReason);
        map.put(RESOLUTION_TAG, errResoulution);
        SnapDataException snapException = new SnapDataException(documentUtility.newDocument(map), errResponse)
                .withReason(errReason).withResolution(errResoulution);
        errorViews.write(snapException);
    }

    /*
     * finds the declared setter methods in the given classtype
     */
    static ArrayList<Method> findSetters(Class<?> classType) {
        ArrayList<Method> list = new ArrayList<Method>();
        Method[] methods = classType.getDeclaredMethods();
        for (Method method : methods) {
            if (isSetter(method)) {
                list.add(method);
            }
        }
        return list;
    }

    /**
     * finds the declared getter methods in the given classtype
     *
     * @param c
     * @return ArrayList<Method>
     */
    public static ArrayList<Method> findGetters(Class<?> c) {
        ArrayList<Method> list = new ArrayList<Method>();
        Method[] methods = c.getDeclaredMethods();
        for (Method method : methods) {
            if (isGetter(method)) {
                list.add(method);
            }
        }
        return list;
    }

    /*
     * finds whether the given method setter or not
     */
    static boolean isSetter(Method method) {
        return Modifier.isPublic(method.getModifiers()) && method.getReturnType().equals(void.class)
                && method.getParameterTypes().length == 1 && method.getName().matches(REGEX_SET);
    }

    /*
     * finds whether the given method getter or not
     */
    static boolean isGetter(Method method) {
        if (Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0) {
            String methodName = method.getName();
            if (methodName.matches(GET_REGEX) && !method.getReturnType().equals(void.class))
                return true;
            if (methodName.matches(IS_REGEX) && method.getReturnType().equals(boolean.class))
                return true;
        }
        return false;
    }
}