Coverage Report - org.jscsi.target.settings.TextParameter
 
Classes in this File Line Coverage Branch Coverage Complexity
TextParameter
0%
0/46
0%
0/48
4.6
 
 1  
 package org.jscsi.target.settings;
 2  
 
 3  
 
 4  
 import java.util.ArrayList;
 5  
 import java.util.Collection;
 6  
 import java.util.List;
 7  
 import java.util.Vector;
 8  
 import java.util.regex.Matcher;
 9  
 import java.util.regex.Pattern;
 10  
 
 11  
 
 12  
 /**
 13  
  * This is a utility class with static methods useful for dealing with <i>key-value</i> pairs.
 14  
  * 
 15  
  * @author Andreas Ergenzinger
 16  
  */
 17  0
 public final class TextParameter {
 18  
 
 19  
     /**
 20  
      * Returns the <i>key-value</i> pairs contained in a null character-separated text data segment in an array of
 21  
      * {@link String}s.
 22  
      * <p>
 23  
      * If the parameter equals <code>null</code> an empty {@link List} will be returned.
 24  
      * 
 25  
      * @param keyValuePairs a login request or text negotiation text data segment
 26  
      * @return a {@link Vector} of {@link String}s containing the purged key value pairs
 27  
      */
 28  
     public static List<String> tokenizeKeyValuePairs (final String keyValuePairs) {
 29  0
         final List<String> result = new Vector<String>();
 30  0
         if (keyValuePairs == null) return result;
 31  0
         final String[] split = keyValuePairs.split(TextKeyword.NULL_CHAR);
 32  0
         for (int i = 0; i < split.length; ++i)
 33  0
             if (split[i].length() > 0) // does not mean key-value pair is
 34  
                                        // RFC-conform
 35  0
             result.add(split[i]);
 36  0
         return result;
 37  
     }
 38  
 
 39  
     /**
 40  
      * Concatenates the <i>key-value</i> pair elements from the specified {@link Collection} to a
 41  
      * null-character-separated {@link String} that can be sent as a text parameter data segment.
 42  
      * 
 43  
      * @param keyValuePairs a {@link Collection} of <i>key-value</i> pairs
 44  
      * @return null-character-separated {@link String} containing all elements
 45  
      */
 46  
     public static String concatenateKeyValuePairs (final Collection<String> keyValuePairs) {
 47  0
         final StringBuilder sb = new StringBuilder();
 48  0
         for (String s : keyValuePairs) {
 49  0
             sb.append(s);
 50  0
             sb.append(TextKeyword.NULL_CHAR);
 51  0
         }
 52  0
         return sb.toString();
 53  
     }
 54  
 
 55  
     /**
 56  
      * Returns the suffix of a specified {@link String}. The length of the suffix is equal to the length of
 57  
      * <i>string</i> minus the lenght of <i>prefix</i>, but of course only if the beginning of <i>string</i> does equal
 58  
      * <i>prefix<i>. If <i>prefix</i> is not a prefix of <i>string</i>, <code>null</code> is returned.
 59  
      * 
 60  
      * @param string the {@link String} whose suffix we want to have returned
 61  
      * @param prefix a prefix of <i>string</i>
 62  
      * @return the suffix or <code>null</code>
 63  
      */
 64  
     public static String getSuffix (final String string, final String prefix) {
 65  0
         if (string == null || prefix == null || prefix.length() > string.length()) return null;
 66  0
         final String stringPrefix = string.substring(0, prefix.length());
 67  0
         if (stringPrefix.equals(prefix)) return string.substring(prefix.length());
 68  0
         return null;
 69  
     }
 70  
 
 71  
     /**
 72  
      * Splits a <i>key=value</i> pair and returns an array with the separated <i>key</i> and <i>value</i> parts.
 73  
      * <p>
 74  
      * If the parameter does not match this required pattern, then <code>null</code> will be returned.
 75  
      * 
 76  
      * @param keyValuePair a {@link String} with a <i>key</i> prefix of length > 0, a '=' in the middle and a
 77  
      *            <i>value</i> suffix of length > 0
 78  
      * @return array with the separated <i>key</i> and <i>value</i> parts or <code>null</code>.
 79  
      */
 80  
     public static String[] splitKeyValuePair (final String keyValuePair) {
 81  0
         String[] split = keyValuePair.split(TextKeyword.EQUALS);
 82  0
         if (split.length != 2 || split[0].length() == 0 || split[1].length() == 0) return null;
 83  0
         return split;
 84  
     }
 85  
 
 86  
     /**
 87  
      * Splits a String of (one or more) values at the ',' signs and returns the values in an array of Strings.
 88  
      * <p>
 89  
      * Returns <code>null</code> if <i>values</i> parameter is <code>null</code>.
 90  
      * 
 91  
      * @param values a comma-separated String of text parameter values
 92  
      * @return a String array of values or <code>null</code>
 93  
      */
 94  
     public static String[] splitValues (final String values) {
 95  0
         if (values == null) return null;
 96  0
         return values.split(TextKeyword.COMMA);
 97  
     }
 98  
 
 99  
     /**
 100  
      * Returns an array of Strings containing only those String values present in both input String arrays <i>a</i> and
 101  
      * <i>b</i>.
 102  
      * <p>
 103  
      * The order of elements in the returned array equals that in array <i>a</i>.
 104  
      * <p>
 105  
      * If <i>a</i> or <i>b</i> or one of their elements is <code>null</code>, <code>null</code> is returned.
 106  
      * 
 107  
      * @param a an array of Strings (element order will be preserved)
 108  
      * @param b an array of Strings
 109  
      * @return an array of shared Strings or <code>null</code>
 110  
      */
 111  
     public static String[] intersect (String[] a, String[] b) {
 112  0
         if (a == null || b == null) return null;
 113  0
         final int maxLength = Math.max(a.length, b.length);// prevent growing of
 114  
                                                            // the ArrayList
 115  0
         final ArrayList<String> intersection = new ArrayList<String>(maxLength);
 116  0
         for (int i = 0; i < a.length; ++i) {
 117  0
             for (int j = 0; j < b.length; ++j) {
 118  0
                 if (a[i] == null || b[j] == null) return null;
 119  0
                 if (a[i].matches(b[j])) {
 120  
                     // add element to intersection and check next String in a
 121  0
                     intersection.add(a[i]);
 122  0
                     break;
 123  
                 }
 124  
             }
 125  
         }
 126  0
         String[] result = new String[intersection.size()];
 127  0
         result = intersection.toArray(result);
 128  0
         return result;
 129  
     }
 130  
 
 131  
     /**
 132  
      * A methods for parsing boolean values from the <i>value</i> part of a <i>key=value</i> pair String. If
 133  
      * <i>value</i> equals <i>"Yes"</i>, then <code>true</code> will be returned, if <i>value</i> equals <i>"No"</i>,
 134  
      * then <code>false</code> will be returned. In all other cases the method will return <code>null</code>.
 135  
      * 
 136  
      * @param value a String containing
 137  
      * @return <code>true</code>, <code>false</code>, or <code>null</code>
 138  
      */
 139  
     public static Boolean parseBooleanValue (final String value) {
 140  0
         if (value == null) return null;
 141  0
         if (TextKeyword.YES.equals(value)) return true;
 142  0
         if (TextKeyword.NO.equals(value)) return false;
 143  0
         return null;
 144  
     }
 145  
 
 146  0
     private static final Pattern TEXT_VALUE_PATTERN = Pattern.compile("[\\[\\]a-zA-Z0-9.:;_@/+-]+");
 147  
 
 148  
     /**
 149  
      * Checks if the <i>value</i> parameter is a properly formatted String value, i.e. if it only contains the allowed
 150  
      * characters. The list of legal characters is specified in RFC3720, section 5.1. All characters from that list
 151  
      * except for '~' and the null character are considered legitimate.
 152  
      * <p>
 153  
      * If those constraints are violated, the method returns <code>null</code>.
 154  
      * 
 155  
      * @param value the <i>value</i> part of a <i>key=value</i> pair, which is a String text parameter
 156  
      * @return the properly formatted value String or <code>null</code>
 157  
      */
 158  
     public static boolean checkTextValueFormat (final String value) {
 159  0
         if (value == null) return false;
 160  0
         final Matcher matcher = TEXT_VALUE_PATTERN.matcher(value);
 161  0
         return matcher.matches();
 162  
     }
 163  
 
 164  
     /**
 165  
      * Joins a <i>key</i> and a <i>value</i> {@link String} to a <i>key=value</i> pair as required by iSCSI text
 166  
      * parameter negotiation and returns the result.
 167  
      * 
 168  
      * @param key the <i>key</i> part
 169  
      * @param value the <i>value</i> part
 170  
      * @return the concatenated <i>key=value</i> pair
 171  
      */
 172  
     public static String toKeyValuePair (final String key, final String value) {
 173  0
         return key + TextKeyword.EQUALS + value;
 174  
     }
 175  
 
 176  
     /**
 177  
      * Translates boolean values to either <code>Yes</code> (<code>true</code>) or <code>No</code> (<code>false</code>).
 178  
      * 
 179  
      * @param value the value to translate
 180  
      * @return <code>Yes</code> or <code>No</code>
 181  
      */
 182  
     public static String booleanToTextValue (final boolean value) {
 183  0
         if (value) return TextKeyword.YES;
 184  0
         return TextKeyword.NO;
 185  
     }
 186  
 }