com.jkoolcloud.tnt4j.streams.parsers.ActivityJavaObjectParser.java Source code

Java tutorial

Introduction

Here is the source code for com.jkoolcloud.tnt4j.streams.parsers.ActivityJavaObjectParser.java

Source

/*
 * Copyright 2014-2017 JKOOL, LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 com.jkoolcloud.tnt4j.streams.parsers;

import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import com.jkoolcloud.tnt4j.core.OpLevel;
import com.jkoolcloud.tnt4j.sink.DefaultEventSinkFactory;
import com.jkoolcloud.tnt4j.sink.EventSink;
import com.jkoolcloud.tnt4j.streams.fields.ActivityFieldLocator;
import com.jkoolcloud.tnt4j.streams.inputs.TNTInputStream;
import com.jkoolcloud.tnt4j.streams.utils.StreamsConstants;
import com.jkoolcloud.tnt4j.streams.utils.StreamsResources;
import com.jkoolcloud.tnt4j.streams.utils.Utils;

/**
 * Implements an activity data parser that assumes each activity data item is an plain java {@link Object} data
 * structure, where each field is represented by declared class field and the field name is used to map each field into
 * its corresponding activity field.
 * <p>
 * If field is complex object, sub-fields can be accessed using
 * '{@value com.jkoolcloud.tnt4j.streams.utils.StreamsConstants#DEFAULT_PATH_DELIM}' as naming hierarchy separator:
 * e.g., 'header.author.name'.
 *
 * @version $Revision: 1 $
 */
public class ActivityJavaObjectParser extends GenericActivityParser<Object> {
    private static final EventSink LOGGER = DefaultEventSinkFactory
            .defaultEventSink(ActivityJavaObjectParser.class);

    /**
     * Constructs a new ActivityJavaObjectParser.
     */
    public ActivityJavaObjectParser() {
        super();
    }

    @Override
    protected EventSink logger() {
        return LOGGER;
    }

    @Override
    public void setProperties(Collection<Map.Entry<String, String>> props) throws Exception {
        if (props == null) {
            return;
        }

        super.setProperties(props);

        // for (Map.Entry<String, String> prop : props) {
        // String name = prop.getKey();
        // String value = prop.getValue();
        //
        // // no any additional properties are required yet.
        // if (false) {
        // logger().log(OpLevel.DEBUG,
        // StreamsResources.getString(StreamsResources.RESOURCE_BUNDLE_NAME, "ActivityParser.setting"),
        // name, value);
        // }
        // }
    }

    /**
     * Returns whether this parser supports the given format of the activity data. This is used by activity streams to
     * determine if the parser can parse the data in the format that the stream has it.
     * <p>
     * This parser supports the following class types (and all classes extending/implementing any of these):
     * <ul>
     * <li>{@link java.lang.Object}</li>
     * </ul>
     *
     * @param data
     *            data object whose class is to be verified
     * @return {@code true} if this parser can process data in the specified format, {@code false} - otherwise
     */
    @Override
    protected boolean isDataClassSupportedByParser(Object data) {
        return Object.class.isInstance(data);
    }

    @Override
    protected ActivityContext prepareItem(TNTInputStream<?, ?> stream, Object data) throws ParseException {
        ActivityContext cData = new ActivityContext(stream, data, data);
        cData.setMessage(getRawDataAsMessage(data));

        return cData;
    }

    @Override
    protected String getRawDataAsMessage(Object data) {
        return ToStringBuilder.reflectionToString(data, ToStringStyle.MULTI_LINE_STYLE);
    }

    /**
     * Gets field raw data value resolved by locator.
     *
     * @param locator
     *            activity field locator
     * @param cData
     *            activity data carrier object
     * @param formattingNeeded
     *            flag to set if value formatting is not needed
     * @return raw value resolved by locator, or {@code null} if value is not resolved
     */
    @Override
    protected Object resolveLocatorValue(ActivityFieldLocator locator, ActivityContext cData,
            AtomicBoolean formattingNeeded) {
        Object val = null;
        String locStr = locator.getLocator();
        String[] path = Utils.getNodePath(locStr, StreamsConstants.DEFAULT_PATH_DELIM);
        val = getFieldValue(path, cData.getData(), 0);

        return val;
    }

    private static Object getFieldValue(String[] path, Object dataObj, int i) {
        if (ArrayUtils.isEmpty(path) || dataObj == null) {
            return null;
        }

        try {
            Field f = dataObj.getClass().getDeclaredField(path[i]);
            Object obj = f.get(dataObj);

            if (i < path.length - 1 && !f.getType().isPrimitive()) {
                obj = getFieldValue(path, obj, ++i);
            }

            return obj;
        } catch (Exception exc) {
            LOGGER.log(OpLevel.WARNING,
                    StreamsResources.getString(StreamsResources.RESOURCE_BUNDLE_NAME,
                            "ActivityJavaObjectParser.could.not.get.declared.field"),
                    path[i], dataObj.getClass().getSimpleName(), toString(dataObj));
            return null;
        }
    }

    /**
     * Returns type of RAW activity data entries.
     *
     * @return type of RAW activity data entries - OBJECT
     */
    @Override
    protected String getActivityDataType() {
        return "OBJECT"; // NON-NLS
    }
}