com.prowidesoftware.swift.model.field.SwiftParseUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.prowidesoftware.swift.model.field.SwiftParseUtils.java

Source

/*******************************************************************************
 * Copyright (c) 2016 Prowide Inc.
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as 
 *     published by the Free Software Foundation, either version 3 of the 
 *     License, or (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 *     
 *     Check the LGPL at <http://www.gnu.org/licenses/> for more details.
 *******************************************************************************/
package com.prowidesoftware.swift.model.field;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.UnhandledException;

/**
 * This class provides methods to parse field components.
 *
 * @author www.prowidesoftware.com
 * @since 6.0
 */
public class SwiftParseUtils {
    @SuppressWarnings("unused")
    private static final transient java.util.logging.Logger log = java.util.logging.Logger
            .getLogger(SwiftParseUtils.class.getName());

    /**
     * Split components of a line, with an optional starting string and a component separator.
     * Adjacent separators are treated as one separator.
     * This method does not validate the starting string presence, it just strips it if present.
     * this methods uses {@link StringUtils#splitByWholeSeparator(String, String)}
     *
     * @param line the string to parse
     * @param starting an optional starting string
     * @param separator the components separator
     * @return a list of String with the found components or an empty list if none is found
     */
    public static List<String> splitComponents(final String line, final String starting, final String separator) {
        final ArrayList<String> result = new ArrayList<String>();

        if (StringUtils.isNotBlank(line)) {
            String lineNoPrefix = removePrefix(line, starting);

            if (StringUtils.isNotBlank(separator)) {
                final String[] tokens = StringUtils.splitByWholeSeparator(lineNoPrefix, separator);
                //add not empty tokens to result
                for (int i = 0; i < tokens.length; i++) {
                    if (StringUtils.isNotBlank(tokens[i])) {
                        result.add(tokens[i]);
                    }
                }
            } else {
                result.add(lineNoPrefix);
            }
        }
        return result;
    }

    /**
     * Split components of a line with an optional starting string and a component separator
     * and returns the first token found or <code>null</code> if the string without starting substring
     * is empty or <code>null</code>.<br />
     * This method does not validate the starting string presence, it just strips it if present.
     *
     * @param line
     * @param starting
     * @param separator
     * @return the first token found or <code>null</code>
     */
    public static String getTokenFirst(String line, final String starting, final String separator) {
        String result = null;
        if (StringUtils.isNotBlank(line)) {
            String lineNoPrefix = removePrefix(line, starting);

            result = StringUtils.substringBefore(lineNoPrefix, separator);
            if (StringUtils.isBlank(result)) {
                return null;
            }
        }
        return result;
    }

    /**
     * @param line
     * @param separator
     * @return found token
     * @see #getTokenFirst(String, String, String)
     */
    public static String getTokenFirst(final String line, final String separator) {
        return getTokenFirst(line, null, separator);
    }

    /**
     * @param value
     * @param prefix
     * @return s
     */
    public static String removePrefix(final String value, final String prefix) {
        if (StringUtils.isNotBlank(value) && StringUtils.isNotBlank(prefix) && value.startsWith(prefix)) {
            return StringUtils.substringAfter(value, prefix);
        }
        return value;
    }

    /**
     * Split components of a line using the parameter separator and returns the second token found or <code>null</code> if
     * second component is missing. Two adjacent separators are NOT treated as one.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc//def/ghi" will return null.</li>
     *       <li>for the literal "abc/foo/def" will return "foo".</li>
     *       <li>for the literal "abc/foo/def/ghi" will return "foo".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenSecond(final String line, final String separator) {
        //notice we cannot use String.split nor StringUtils.split because in that implementations two adjacent separators are treated as one
        final String result = getTokenFirst(StringUtils.substringAfter(line, separator), null, separator);
        return result;
    }

    /**
     * Split components of a line using the parameter separator and returns the second token found or <code>null</code> if
     * second component is missing. Two adjacent separators are NOT treated as one. The second component is assumed as the
     * last one so its content may have additional separators if present.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc//def/ghi" will return null.</li>
     *       <li>for the literal "abc/foo" will return "foo".</li>
     *       <li>for the literal "abc/foo/def/ghi" will return "foo/def/ghi".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenSecondLast(final String line, final String separator) {
        String result = StringUtils.substringAfter(line, separator);
        if (StringUtils.isBlank(result)) {
            result = null;
        }
        return result;
    }

    /**
     * Split components of a line with an optional starting string and a component separator
     * and returns the second token found or <code>null</code> if the string without starting substring
     * is empty or <code>null</code>.<br />
     * This method does not validate the starting string presence, it just strips it if present.
     *
     * @param line
     * @param starting
     * @param separator
     * @return the second token found or <code>null</code>
     * @since 7.4
     */
    public static String getTokenSecond(final String line, final String starting, final String separator) {
        return getTokenSecond(removePrefix(line, starting), separator);
    }

    /**
     * Split components of a line with an optional starting string and a component separator
     * and returns the second token found or <code>null</code> if the string without starting substring
     * is empty or <code>null</code>.
     * <br />
     * Two adjacent separators are NOT treated as one. The second component is assumed as the
     * last one so its content may have additional separators if present.<br />
     * This method does not validate the starting string presence, it just strips it if present.
     *
     * @param line
     * @param starting
     * @param separator
     * @return the second token found or <code>null</code>
     * @since 7.4
     */
    public static String getTokenSecondLast(final String line, final String starting, final String separator) {
        return getTokenSecondLast(removePrefix(line, starting), separator);
    }

    /**
     * Split components of a line using the parameter separator and returns the third token found or <code>null</code> if
     * third component is missing. Two adjacent separators are NOT treated as one.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc/def//ghi" will return null.</li>
     *       <li>for the literal "abc/foo" will return "null".</li>
     *       <li>for the literal "abc/def/foo" will return "foo".</li>
     *       <li>for the literal "abc/def/foo/ghi" will return "foo".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenThird(final String line, final String separator) {
        final String result = getTokenSecond(getTokenSecondLast(line, separator), separator);
        return result;
    }

    /**
     * Split components of a line using the parameter separator and returns the third token found or <code>null</code> if
     * third component is missing. Two adjacent separators are NOT treated as one. The third component is assumed as the
     * last one so its content may have additional separators if present.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc/def//ghi" will return null.</li>
     *       <li>for the literal "abc/foo" will return "null".</li>
     *       <li>for the literal "abc/def/foo" will return "foo".</li>
     *       <li>for the literal "abc/def/foo/ghi" will return "foo/ghi".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenThirdLast(final String line, final String separator) {
        String result = null;
        final String s1 = getTokenSecondLast(line, separator);
        if (StringUtils.isNotBlank(s1)) {
            result = StringUtils.substringAfter(s1, separator);
            if (StringUtils.isBlank(result)) {
                result = null;
            }
        }
        return result;
    }

    /**
     * Split components of a line using the parameter separator and returns the forth token found or <code>null</code> if
     * forth component is missing. Two adjacent separators are NOT treated as one.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc/def/ghi//ghi" will return null.</li>
     *       <li>for the literal "abc/foo/ghi" will return "null".</li>
     *       <li>for the literal "abc/def/ghi/foo" will return "foo".</li>
     *       <li>for the literal "abc/def/ghi/foo/ghi" will return "foo".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenForth(final String line, final String separator) {
        final String result = getTokenSecond(getTokenThirdLast(line, separator), separator);
        return result;
    }

    /**
     * Split components of a line using the parameter separator and returns the forth token found or <code>null</code> if
     * forth component is missing. Two adjacent separators are NOT treated as one. The forth component is assumed as the
     * last one so its content may have additional separators if present.<br />
     * Examples with slash as separator:<ul>
     *       <li>for the literal "abc/def/ghi//ghi" will return null.</li>
     *       <li>for the literal "abc/foo/ghi" will return "null".</li>
     *       <li>for the literal "abc/def/ghi/foo" will return "foo".</li>
     *       <li>for the literal "abc/def/ghi/foo/ghi" will return "foo/ghi".</li>
     * </ul>
     *
     * @param line
     * @param separator
     * @return s
     */
    public static String getTokenForthLast(final String line, final String separator) {
        String result = null;
        final String s1 = getTokenThirdLast(line, separator);
        if (StringUtils.isNotBlank(s1)) {
            result = StringUtils.substringAfter(s1, separator);
            if (StringUtils.isBlank(result)) {
                result = null;
            }
        }
        return result;
    }

    /**
     * Returns the alphabetic starting substring of the value.
     * The split is made when the first numeric character is found.
     * For example:<br />
     * ABCD2345,33 will be return ABCD<br />
     * If the value does not contain any alphabetic character <code>null</code> is returned.
     *
     * @param value
     * @return s
     */
    public static String getAlphaPrefix(final String value) {
        if (value != null && value.length() > 0) {
            int i = 0;
            while (i < value.length() && !StringUtils.isNumeric("" + value.charAt(i))) {
                i++;
            }
            if (i > 0) {
                return StringUtils.substring(value, 0, i);
            }
        }
        return null;
    }

    /**
     * Returns the numeric starting substring of the value.
     * The split is made when the first alpha character (not number or comma) is found.
     * For example:<br />
     * 2345,33ABCD will be return 2345,33<br />
     * If the value does not contain any numeric or comma character <code>null</code> is returned.
     *
     * @param value
     * @return s
     */
    public static String getNumericPrefix(final String value) {
        if (value != null && value.length() > 0) {
            int i = 0;
            while (i < value.length() && (StringUtils.isNumeric("" + value.charAt(i))
                    || StringUtils.equals("" + value.charAt(i), ","))) {
                i++;
            }
            if (i > 0) {
                return StringUtils.substring(value, 0, i);
            }
        }
        return null;
    }

    /**
     * Returns the numeric suffix of the value.
     * The split is made when the first numeric character is found.
     * For example:<br />
     * ABCD2345,33 will be return 2345,33<br />
     * If the value does not contain any numeric character <code>null</code> is returned.
     *
     * @param value
     * @return s
     */
    public static String getNumericSuffix(final String value) {
        if (value != null && value.length() > 0) {
            int i = 0;
            while (i < value.length() && !StringUtils.isNumeric("" + value.charAt(i))) {
                i++;
            }
            if (i < value.length()) {
                return StringUtils.substring(value, i);
            }
        }
        return null;
    }

    /**
     * Returns the alpha suffix of the value.
     * The split is made when the first alpha (not numetic or comma) character is found.
     * For example:<br />
     * 2345,33ABCD will be return ABCD<br />
     * If the value does not contain any alpha character <code>null</code> is returned.
     *
     * @param value
     * @return s
     */
    public static String getAlphaSuffix(final String value) {
        if (value != null && value.length() > 0) {
            int i = 0;
            while (i < value.length() && (StringUtils.isNumeric("" + value.charAt(i))
                    || StringUtils.equals("" + value.charAt(i), ","))) {
                i++;
            }
            if (i < value.length()) {
                return StringUtils.substring(value, i);
            }
        }
        return null;
    }

    /**
     * Separate the given string in lines using readline
     *
     * @param value
     * @return list of found lines
     */
    public static List<String> getLines(final String value) {
        final List<String> result = new ArrayList<String>();
        if (value != null) {
            final BufferedReader br = new BufferedReader(new StringReader(value));
            try {
                String l = br.readLine();
                while (l != null) {
                    result.add(l);
                    l = br.readLine();
                }
            } catch (final IOException e) {
                throw new UnhandledException(e);
            }
        }
        return result;
    }

    /**
     * Populates a multiline field with content from an array of Strings.
     *
     * @param f field to populate with components' values
     * @param startingComponentNumber first component number to be set, then it will increment on each line added
     * @param linesToSet how many components must to be set, or null to set all available lines as components
     * @param startingLine lines list offset, zero based
     * @param lines list of lines from where to get components content
     */
    public static void setComponentsFromLines(final Field f, final int startingComponentNumber,
            final Integer linesToSet, final int startingLine, final List<String> lines) {
        int max = linesToSet != null ? linesToSet : lines.size();
        int componentNumber = startingComponentNumber;
        int lineNumber = startingLine;
        for (int i = 0; i < max; i++) {
            if (lines.size() > lineNumber) {
                f.setComponent(componentNumber, lines.get(lineNumber));
            }
            componentNumber++;
            lineNumber++;
        }
    }

    /**
     * Populates field with content from of a String splited into fixed length tokens.
     *
     * @param f field to populate with components' values
     * @param startingComponentNumber first component number to be set, then it will increment on each token added
     * @param componentsToSet how many components must to be set
     * @param tokenSize fixed size for each token grabbed from the String value
     * @param value from where to get components content
     * @since 7.4
     */
    public static void setComponentsFromTokens(final Field f, final int startingComponentNumber,
            final int componentsToSet, final int tokenSize, final String value) {
        StringBuilder token = new StringBuilder();
        int componentNumber = startingComponentNumber;
        for (final char c : value.toCharArray()) {
            if (token.length() < tokenSize) {
                token.append(c);
            } else {
                //token complete
                if (componentNumber <= componentsToSet) {
                    f.setComponent(componentNumber, token.toString());
                }
                componentNumber++;
                token = new StringBuilder();
                token.append(c);
            }
        }
        //add remainder
        if (token.length() > 0 && componentNumber <= componentsToSet) {
            f.setComponent(componentNumber, token.toString());
        }
    }

}