1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package Torello.Java;

import static Torello.Java.StrSource.GENERIC_PARAMS;

import java.util.regex.Matcher;
import java.util.stream.Stream;

class ParseGenericType
{
    static String[] parse(String genericTypeParamOrDefinition)
    {
        Matcher m               = GENERIC_PARAMS.matcher(genericTypeParamOrDefinition);
        String  innerGenericStr = m.find() ? m.group(1) : null;

        if (innerGenericStr == null) throw new NoMatchException(
            "The provided value to parameter 'genericTypeParamOrDefinition' [" + 
            genericTypeParamOrDefinition + "] did not match the Java Generics " +
            "Regular-Expression:\n" + GENERIC_PARAMS.toString()
        );

        Stream.Builder<String>  b               = Stream.builder();
        String[]                sArr            = innerGenericStr.split(",");

        for (int i=0; i < sArr.length; i++)

            // We have shifted elements, and now all of the remaining elements would be null
            // return immediately

            if (sArr[i] == null) return b.build().toArray(String[]::new);


            // Simple generic-type definition: has no "sub-generics" or "inner-generics"
            // Add this to the list, and move on

            else if ((! sArr[i].contains("<")) && (! sArr[i].contains(">")))
                b.accept(sArr[i].trim());


            // This is a generic-type definition that has at least one "sub-generic"
            // If there are an equal number of '<' and '>' then there were no commas
            // in between the sub-generics.  Add this to this list, and move on.

            else if (   StringParse.countCharacters(sArr[i], '<') ==
                        StringParse.countCharacters(sArr[i], '>')
            )
                b.accept(sArr[i].trim());

            // There was a generic with a sub-generic that had a comma...
            else
            {
                // If we have reached the end of the String, the number of greater than and
                // less than symbols was not balanced.

                if (i == (sArr.length - 1)) throw new StringFormatException(
                    "The provided value to parameter 'genericTypeParamOrDefinition' [" + 
                    genericTypeParamOrDefinition + "], was not properly formatted, and could " +
                    "not be parsed."
                );

                // Join the next String Array Element with the current one.
                sArr[i] = sArr[i].trim() + ", " + sArr[i + 1].trim();

                // Shift the rest of the array left.
                for (int j=i+1; j < (sArr.length-1); j++) sArr[j] = sArr[j+1];
                sArr[sArr.length - 1] = null;

                // decrement the counter to retest this array-index location
                i--;
            }

        // Return the list
        return b.build().toArray(String[]::new);
    }    
}