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

Java tutorial

Introduction

Here is the source code for com.jkoolcloud.tnt4j.streams.parsers.MessageActivityXmlParser.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.text.ParseException;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang3.StringUtils;

import com.jkoolcloud.tnt4j.core.OpLevel;
import com.jkoolcloud.tnt4j.sink.DefaultEventSinkFactory;
import com.jkoolcloud.tnt4j.sink.EventSink;
import com.jkoolcloud.tnt4j.streams.configure.ParserProperties;
import com.jkoolcloud.tnt4j.streams.fields.ActivityField;
import com.jkoolcloud.tnt4j.streams.fields.ActivityInfo;
import com.jkoolcloud.tnt4j.streams.fields.StreamFieldType;
import com.jkoolcloud.tnt4j.streams.utils.StreamsResources;
import com.jkoolcloud.tnt4j.streams.utils.Utils;

/**
 * This class extends the basic activity XML parser for handling data specific to messaging operations. It provides
 * additional transformations of the raw activity data collected for specific fields.
 * <p>
 * In particular, this class will convert the {@link StreamFieldType#TrackingId} and {@link StreamFieldType#Correlator}
 * fields values from a tokenized list of items into a value in the appropriate form required by the JKool Cloud.
 * <p>
 * This parser supports the following properties (in addition to those supported by {@link ActivityXmlParser}):
 * <ul>
 * <li>SignatureDelim - signature fields delimiter. (Optional)</li>
 * </ul>
 *
 * @version $Revision: 1 $
 */
public class MessageActivityXmlParser extends ActivityXmlParser {
    private static final EventSink LOGGER = DefaultEventSinkFactory
            .defaultEventSink(MessageActivityXmlParser.class);
    /**
     * Contains the field separator (set by {@code SignatureDelim} property) - Default:
     * "{@value com.jkoolcloud.tnt4j.streams.parsers.GenericActivityParser#DEFAULT_DELIM}"
     */
    protected String sigDelim = DEFAULT_DELIM;

    /**
     * Constructs a new MessageActivityXmlParser.
     *
     * @throws ParserConfigurationException
     *             if any errors configuring the parser
     */
    public MessageActivityXmlParser() throws ParserConfigurationException {
    }

    @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();
            if (ParserProperties.PROP_SIG_DELIM.equalsIgnoreCase(name)) {
                if (StringUtils.isNotEmpty(value)) {
                    sigDelim = value;
                    logger().log(OpLevel.DEBUG, StreamsResources.getString(StreamsResources.RESOURCE_BUNDLE_NAME,
                            "ActivityParser.setting"), name, value);
                }
            }
        }
    }

    /**
     * {@inheritDoc}
     * <p>
     * This method applies custom handling for setting field values. This method will construct the signature to use for
     * the message from the specified value, which is assumed to be a string containing the inputs required for the
     * message signature calculation, with each input separated by the delimiter specified in property
     * {@code SignatureDelim}.
     * <p>
     * The signature items MUST be specified in the following order:
     * <ol>
     * <li>Message Type</li>
     * <li>Message Format</li>
     * <li>Message ID</li>
     * <li>Message User</li>
     * <li>Message Application Type</li>
     * <li>Message Application Name</li>
     * <li>Message Date</li>
     * <li>Message Time</li>
     * </ol>
     * <p>
     * Individual items can be omitted, but must contain a place holder (except for trailing items).
     */
    @Override
    protected void applyFieldValue(ActivityInfo ai, ActivityField field, Object value) throws ParseException {
        StreamFieldType fieldType = field.getFieldType();
        if (fieldType != null) {
            switch (fieldType) {
            case Correlator:
            case TrackingId:
                Object[] sigItems = null;
                if (value instanceof Object[]) {
                    sigItems = (Object[]) value;
                } else if (value instanceof String) {
                    String sigStr = (String) value;
                    if (sigStr.contains(sigDelim)) {
                        sigItems = sigStr.split(Pattern.quote(sigDelim));
                    }
                }
                if (sigItems != null) {
                    MessageType msgType = null;
                    String msgFormat = null;
                    byte[] msgId = null;
                    String msgUser = null;
                    String msgApplType = null;
                    String msgApplName = null;
                    String msgPutDate = null;
                    String msgPutTime = null;
                    for (int i = 0; i < sigItems.length; i++) {
                        Object item = sigItems[i];
                        if (item == null) {
                            continue;
                        }
                        switch (i) {
                        case 0:
                            msgType = MessageType.valueOf(item instanceof Number ? ((Number) item).intValue()
                                    : Integer.parseInt(item.toString()));
                            break;
                        case 1:
                            msgFormat = item.toString();
                            break;
                        case 2:
                            msgId = item instanceof byte[] ? (byte[]) item : item.toString().getBytes();
                            break;
                        case 3:
                            msgUser = item.toString();
                            break;
                        case 4:
                            msgApplType = item.toString();
                            break;
                        case 5:
                            msgApplName = item.toString();
                            break;
                        case 6:
                            msgPutDate = item.toString();
                            break;
                        case 7:
                            msgPutTime = item.toString();
                            break;
                        default:
                            break;
                        }
                    }
                    value = Utils.computeSignature(msgType, msgFormat, msgId, msgUser, msgApplType, msgApplName,
                            msgPutDate, msgPutTime);
                    logger().log(OpLevel.TRACE,
                            StreamsResources.getString(StreamsResources.RESOURCE_BUNDLE_NAME,
                                    "MessageActivityXmlParser.msg.signature"),
                            value, msgType, msgFormat, msgId == null ? "null" : Utils.encodeHex(msgId),
                            msgId == null ? "null" : new String(msgId), msgUser, msgApplType, msgApplName,
                            msgPutDate, msgPutTime);
                }
                break;
            default:
                break;
            }
        }
        super.applyFieldValue(ai, field, value);
    }
}