Package org.apache.camel.dataformat.bindy

Source Code of org.apache.camel.dataformat.bindy.BindyKeyValuePairFactory

/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.camel.dataformat.bindy;

import java.lang.reflect.Field;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.camel.dataformat.bindy.annotation.KeyValuePairField;
import org.apache.camel.dataformat.bindy.annotation.Link;
import org.apache.camel.dataformat.bindy.annotation.Message;
import org.apache.camel.dataformat.bindy.util.Converter;
import org.apache.camel.spi.PackageScanClassResolver;
import org.apache.camel.util.ObjectHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* The BindyKeyValuePairFactory is the class who allows to bind data of type
* key value pair. Such format exist in financial messages FIX.
* This class allows to generate a model associated to message, bind data from a message
* to the POJOs, export data of POJOs to a message and format data
* into String, Date, Double, ... according to the format/pattern defined
*/
public class BindyKeyValuePairFactory extends BindyAbstractFactory implements BindyFactory  {

    private static final transient Log LOG = LogFactory.getLog(BindyKeyValuePairFactory.class);

    private Map<Integer, KeyValuePairField> mapKeyValuePairField = new LinkedHashMap<Integer, KeyValuePairField>();
    private Map<Integer, Field> mapAnnotedField = new LinkedHashMap<Integer, Field>();

    private String keyValuePairSeparator;
    private String pairSeparator;

    public BindyKeyValuePairFactory(PackageScanClassResolver resolver, String packageName) throws Exception {
       
        super(resolver, packageName);
       
        // Initialize what is specific to Key Value Pair model
        initKeyValuePairModel();
    }

    /**
     * method uses to initialize the model representing the classes who will
     * bind the data This process will scan for classes according to the package
     * name provided, check the classes and fields annoted. Next, we retrieve the
     * parameters required like : Pair Separator & key value pair separator
     *
     * @throws Exception
     */
    public void initKeyValuePairModel() throws Exception {
       
        // Find annotated KeyValuePairfields declared in the Model classes
        initAnnotedFields();
       
        // Initialize key value pair parameter(s)
        initMessageParameters();

    }
   
   
    public void initAnnotedFields() {

        for (Class<?> cl : models) {

            for (Field field : cl.getDeclaredFields()) {
                KeyValuePairField keyValuePairField = field.getAnnotation(KeyValuePairField.class);
                if (keyValuePairField != null) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Key declared in the class : " + cl.getName() + ", key : "
                            + keyValuePairField.tag() + ", Field : " + keyValuePairField.toString());
                    }
                    mapKeyValuePairField.put(keyValuePairField.tag(), keyValuePairField);
                    mapAnnotedField.put(keyValuePairField.tag(), field);
                }

                Link linkField = field.getAnnotation(Link.class);

                if (linkField != null) {
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Class linked  : " + cl.getName() + ", Field" + field.toString());
                    }
                    mapAnnotedLinkField.put(cl.getName(), field);
                }
            }

        }
    }
   

    public void bind(List<String> data, Map<String, Object> model) throws Exception {

        int pos = 0;
       
        if (LOG.isDebugEnabled()) {
            LOG.debug("Data : " + data);
        }

        while (pos < data.size()) {
       
            if (!data.get(pos).equals("")) {
          
                // Separate the key from its value
                // e.g 8=FIX 4.1 --> key = 8 and Value = FIX 4.1
                ObjectHelper.notNull(this.keyValuePairSeparator, "Key Value Pair not defined in the @Message annotation");
                String[] keyValuePair = data.get(pos).split(this.getKeyValuePairSeparator());
               
                int tag = Integer.parseInt(keyValuePair[0]);
                String value = keyValuePair[1];
               
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Key : " + tag + ", value : " + value);
                }

                KeyValuePairField keyValuePairField = mapKeyValuePairField.get(tag);
                ObjectHelper.notNull(keyValuePairField, "No tag defined for the field : " + tag);

                Field field = mapAnnotedField.get(tag);
                field.setAccessible(true);

                if (LOG.isDebugEnabled()) {
                    LOG.debug("Tag : " + tag + ", Data : " + value + ", Field type : " + field.getType());
                }

                Format<?> format;
                String pattern = keyValuePairField.pattern();

                format = FormatFactory.getFormat(field.getType(), pattern, keyValuePairField.precision());
                field.set(model.get(field.getDeclaringClass().getName()), format.parse(value));

            }

            pos++;
        }

    }

    public String unbind(Map<String, Object> model) throws Exception {

        StringBuilder builder = new StringBuilder();

        Map<Integer, KeyValuePairField> keyValuePairFields = new TreeMap<Integer, KeyValuePairField>(mapKeyValuePairField);
        Iterator<Integer> it = keyValuePairFields.keySet().iterator();

        // Check if separator exists
        ObjectHelper.notNull(this.pairSeparator,
             "The pair separator has not been instantiated or property not defined in the @Message annotation");

        char separator = Converter.getCharDelimitor(this.getPairSeparator());

        if (LOG.isDebugEnabled()) {
            LOG.debug("Separator converted : '0x" + Integer.toHexString(separator) + "', from : " + this.getPairSeparator());
        }

        while (it.hasNext()) {

            KeyValuePairField keyValuePairField = mapKeyValuePairField.get(it.next());
            ObjectHelper.notNull(keyValuePairField, "KeyValuePair is null !");

            // Retrieve the field
            Field field = mapAnnotedField.get(keyValuePairField.tag());
            // Change accessibility to allow to read protected/private fields
            field.setAccessible(true);

            if (LOG.isDebugEnabled()) {
                LOG.debug("Tag : " + keyValuePairField.tag() + ", Field type : " + field.getType()
                    + ", class : " + field.getDeclaringClass().getName());
            }

            // Retrieve the format associated to the type
            Format format;

            String pattern = keyValuePairField.pattern();
            format = FormatFactory.getFormat(field.getType(), pattern, keyValuePairField.precision());

            Object obj = model.get(field.getDeclaringClass().getName());

            if (LOG.isDebugEnabled()) {
                LOG.debug("Model object : " + obj.toString());
            }

            // Convert the content to a String and append it to the builder
            // Add the tag followed by its key value pair separator
            // the data and finish by the pair separator
            builder.append(keyValuePairField.tag() + this.getKeyValuePairSeparator()
                           + format.format(field.get(obj)) + separator);
        }

        return builder.toString();
    }

    /**
     * Find the pair separator used to delimit the key value pair fields
     */
    public String getPairSeparator() {
        return pairSeparator;
    }
   
    /**
     * Find the key value pair separator used to link the key with its value
     */
    public String getKeyValuePairSeparator() {
        return keyValuePairSeparator;
    }

    /**
     * Get parameters defined in @Message annotation
     */
    private void initMessageParameters() {

        if ((pairSeparator == null) || (keyValuePairSeparator == null)) {

            for (Class<?> cl : models) {
               
                // Get annotation @Message from the class
                Message message = cl.getAnnotation(Message.class);

                if (message != null) {
                   
                    // Get Pair Separator parameter
                    ObjectHelper.notNull(message.pairSeparator(),
                        "No Pair Separator has been defined in the @Message annotation !");
                    pairSeparator = message.pairSeparator();
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Pair Separator defined for the message : " + pairSeparator);
                    }

                    // Get KeyValuePair Separator parameter
                    ObjectHelper.notNull(message.keyValuePairSeparator(),
                        "No Key Value Pair Separator has been defined in the @Message annotation !");
                    keyValuePairSeparator = message.keyValuePairSeparator();
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Key Value Pair Separator defined for the message : "
                            + keyValuePairSeparator);
                    }

                    // Get carriage return parameter
                    crlf = message.crlf();
                    if (LOG.isDebugEnabled()) {
                        LOG.debug("Carriage return defined for the message : " + crlf);
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.apache.camel.dataformat.bindy.BindyKeyValuePairFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.