All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.prowidesoftware.swift.model.field.SwiftParseUtils Maven / Gradle / Ivy

There is a newer version: SRU2024-10.2.3
Show newest version
/*
 * Copyright 2006-2023 Prowide
 *
 * 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.prowidesoftware.swift.model.field;

import com.prowidesoftware.ProwideException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

/**
 * This class provides methods to parse field components.
 *
 * @author sebastian
 * @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());

    // Suppress default constructor for noninstantiability
    private SwiftParseUtils() {
        throw new AssertionError();
    }

    /**
     * Checks if a string contains only ASCII digits
     * @param value the value to check
     * @return true if all the characters are ASCII digits, false otherwise
     */
    public static boolean isAllAsciiDigits(final String value) {
        if (value == null) {
            return false;
        }
        for (char c : value.toCharArray()) {
            if (c < '0' || '9' < c) {
                return false;
            }
        }
        return true;
    }

    /**
     * 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 splitComponents(final String line, final String starting, final String separator) {
        final List result = new ArrayList<>();

        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 (String token : tokens) {
                    if (StringUtils.isNotBlank(token)) {
                        result.add(token);
                    }
                }
            } 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 null if the string without starting substring
     * is empty or null.
* This method does not validate the starting string presence, it just strips it if present. * * @return the first token found or null */ 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; } /** * @return found token * @see #getTokenFirst(String, String, String) */ public static String getTokenFirst(final String line, final String separator) { return getTokenFirst(line, null, separator); } /** * @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 null if * second component is missing. Two adjacent separators are NOT treated as one.
* Examples with slash as separator:
    *
  • for the literal "abc//def/ghi" will return null.
  • *
  • for the literal "abc/foo/def" will return "foo".
  • *
  • for the literal "abc/foo/def/ghi" will return "foo".
  • *
* * @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 return getTokenFirst(StringUtils.substringAfter(line, separator), null, separator); } /** * Split components of a line using the parameter separator and returns the second token found or null 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.
* Examples with slash as separator:
    *
  • for the literal "abc//def/ghi" will return null.
  • *
  • for the literal "abc/foo" will return "foo".
  • *
  • for the literal "abc/foo/def/ghi" will return "foo/def/ghi".
  • *
* * @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 null if the string without starting substring * is empty or null.
* This method does not validate the starting string presence, it just strips it if present. * * @return the second token found or null * @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 null if the string without starting substring * is empty or null. *
* 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.
* This method does not validate the starting string presence, it just strips it if present. * * @return the second token found or null * @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 null if * third component is missing. Two adjacent separators are NOT treated as one.
* Examples with slash as separator:
    *
  • for the literal "abc/def//ghi" will return null.
  • *
  • for the literal "abc/foo" will return "null".
  • *
  • for the literal "abc/def/foo" will return "foo".
  • *
  • for the literal "abc/def/foo/ghi" will return "foo".
  • *
* * @return s */ public static String getTokenThird(final String line, final String separator) { return getTokenSecond(getTokenSecondLast(line, separator), separator); } /** * Split components of a line using the parameter separator and returns the third token found or null 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.
* Examples with slash as separator:
    *
  • for the literal "abc/def//ghi" will return null.
  • *
  • for the literal "abc/foo" will return "null".
  • *
  • for the literal "abc/def/foo" will return "foo".
  • *
  • for the literal "abc/def/foo/ghi" will return "foo/ghi".
  • *
* * @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 null if * forth component is missing. Two adjacent separators are NOT treated as one.
* Examples with slash as separator:
    *
  • for the literal "abc/def/ghi//ghi" will return null.
  • *
  • for the literal "abc/foo/ghi" will return "null".
  • *
  • for the literal "abc/def/ghi/foo" will return "foo".
  • *
  • for the literal "abc/def/ghi/foo/ghi" will return "foo".
  • *
* * @return s */ public static String getTokenForth(final String line, final String separator) { return getTokenSecond(getTokenThirdLast(line, separator), separator); } /** * Split components of a line using the parameter separator and returns the forth token found or null 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.
* Examples with slash as separator:
    *
  • for the literal "abc/def/ghi//ghi" will return null.
  • *
  • for the literal "abc/foo/ghi" will return "null".
  • *
  • for the literal "abc/def/ghi/foo" will return "foo".
  • *
  • for the literal "abc/def/ghi/foo/ghi" will return "foo/ghi".
  • *
* * @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:
* ABCD2345,33 will be return ABCD
* If the value does not contain any alphabetic character null is returned. * * @return s */ public static String getAlphaPrefix(final String value) { if (value != null && value.length() > 0) { int i = 0; while (i < value.length() && !StringUtils.isNumeric(Character.toString(value.charAt(i)))) { i++; } if (i > 0) { return StringUtils.substring(value, 0, i); } } return null; } /** * Same as {@link #getAlphaPrefix(String)} but if the result consist only of slash characters, then null is returned. * This implementation variant is helpful when parsing fields that uses the slash as component separator, to avoid * spurious components consisting of just the separator, when a malformed field is parsed. * @since 9.2.9 */ public static String getAlphaPrefixTrimSlash(final String value) { String prefix = getAlphaPrefix(value); if (StringUtils.containsOnly(prefix, '/')) { return null; } else { return prefix; } } /** * 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:
* 2345,33ABCD will be return 2345,33
* If the value does not contain any numeric or comma character null is returned. * * @return s */ public static String getNumericPrefix(final String value) { if (value != null && value.length() > 0) { int i = 0; while (i < value.length() && (StringUtils.isNumeric(Character.toString(value.charAt(i))) || 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:
* ABCD2345,33 will be return 2345,33
* If the value does not contain any numeric character null is returned. * * @return s */ public static String getNumericSuffix(final String value) { if (value != null && value.length() > 0) { int i = 0; while (i < value.length() && !StringUtils.isNumeric(Character.toString(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:
* 2345,33ABCD will be return ABCD
* If the value does not contain any alpha character null is returned. * * @return s */ public static String getAlphaSuffix(final String value) { if (value != null && value.length() > 0) { int i = 0; while (i < value.length() && (StringUtils.isNumeric(Character.toString(value.charAt(i))) || value.charAt(i) == ',')) { i++; } if (i < value.length()) { return StringUtils.substring(value, i); } } return null; } /** * Separate the given string in lines, removing trailing empty lines. *

The implementation uses using {@link BufferedReader#readLine()} so if the string ends with a LF, the trailing * "empty" line is not returned in the result. * * @return list of found lines */ public static List getLines(final String value) { final List result = new ArrayList<>(); 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 ProwideException(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 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 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()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy