Tue, 10 Feb 2015 18:12:00 +0100
Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.
michael@0 | 1 | /** |
michael@0 | 2 | * Copyright (c) 2012, Ben Fortuna |
michael@0 | 3 | * All rights reserved. |
michael@0 | 4 | * |
michael@0 | 5 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 6 | * modification, are permitted provided that the following conditions |
michael@0 | 7 | * are met: |
michael@0 | 8 | * |
michael@0 | 9 | * o Redistributions of source code must retain the above copyright |
michael@0 | 10 | * notice, this list of conditions and the following disclaimer. |
michael@0 | 11 | * |
michael@0 | 12 | * o Redistributions in binary form must reproduce the above copyright |
michael@0 | 13 | * notice, this list of conditions and the following disclaimer in the |
michael@0 | 14 | * documentation and/or other materials provided with the distribution. |
michael@0 | 15 | * |
michael@0 | 16 | * o Neither the name of Ben Fortuna nor the names of any other contributors |
michael@0 | 17 | * may be used to endorse or promote products derived from this software |
michael@0 | 18 | * without specific prior written permission. |
michael@0 | 19 | * |
michael@0 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
michael@0 | 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
michael@0 | 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
michael@0 | 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
michael@0 | 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
michael@0 | 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
michael@0 | 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
michael@0 | 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 31 | */ |
michael@0 | 32 | package net.fortuna.ical4j.util; |
michael@0 | 33 | |
michael@0 | 34 | import java.util.regex.Pattern; |
michael@0 | 35 | |
michael@0 | 36 | /** |
michael@0 | 37 | * $Id$ [23-Apr-2004] |
michael@0 | 38 | * |
michael@0 | 39 | * Utility methods for working with parameters. |
michael@0 | 40 | * @author Ben Fortuna |
michael@0 | 41 | * <pre> |
michael@0 | 42 | * 4.3.11 Text |
michael@0 | 43 | * |
michael@0 | 44 | * Value Name: TEXT |
michael@0 | 45 | * |
michael@0 | 46 | * Purpose This value type is used to identify values that contain human |
michael@0 | 47 | * readable text. |
michael@0 | 48 | * |
michael@0 | 49 | * Formal Definition: The character sets supported by this revision of |
michael@0 | 50 | * iCalendar are UTF-8 and US ASCII thereof. The applicability to other |
michael@0 | 51 | * character sets is for future work. The value type is defined by the |
michael@0 | 52 | * following notation. |
michael@0 | 53 | * |
michael@0 | 54 | * text = *(TSAFE-CHAR / ":" / DQUOTE / ESCAPED-CHAR) |
michael@0 | 55 | * ; Folded according to description above |
michael@0 | 56 | * |
michael@0 | 57 | * ESCAPED-CHAR = "\\" / "\;" / "\," / "\N" / "\n") |
michael@0 | 58 | * ; \\ encodes \, \N or \n encodes newline |
michael@0 | 59 | * ; \; encodes ;, \, encodes , |
michael@0 | 60 | * |
michael@0 | 61 | * TSAFE-CHAR = %x20-21 / %x23-2B / %x2D-39 / %x3C-5B |
michael@0 | 62 | * %x5D-7E / NON-US-ASCII |
michael@0 | 63 | * ; Any character except CTLs not needed by the current |
michael@0 | 64 | * ; character set, DQUOTE, ";", ":", "\", "," |
michael@0 | 65 | * |
michael@0 | 66 | * Note: Certain other character sets may require modification of the |
michael@0 | 67 | * above definitions, but this is beyond the scope of this document. |
michael@0 | 68 | * |
michael@0 | 69 | * Description: If the property permits, multiple "text" values are |
michael@0 | 70 | * specified by a COMMA character (US-ASCII decimal 44) separated list |
michael@0 | 71 | * of values. |
michael@0 | 72 | * |
michael@0 | 73 | * The language in which the text is represented can be controlled by |
michael@0 | 74 | * the "LANGUAGE" property parameter. |
michael@0 | 75 | * |
michael@0 | 76 | * An intentional formatted text line break MUST only be included in a |
michael@0 | 77 | * "TEXT" property value by representing the line break with the |
michael@0 | 78 | * character sequence of BACKSLASH (US-ASCII decimal 92), followed by a |
michael@0 | 79 | * LATIN SMALL LETTER N (US-ASCII decimal 110) or a LATIN CAPITAL LETTER |
michael@0 | 80 | * N (US-ASCII decimal 78), that is "\n" or "\N". |
michael@0 | 81 | * |
michael@0 | 82 | * The "TEXT" property values may also contain special characters that |
michael@0 | 83 | * are used to signify delimiters, such as a COMMA character for lists |
michael@0 | 84 | * of values or a SEMICOLON character for structured values. In order to |
michael@0 | 85 | * support the inclusion of these special characters in "TEXT" property |
michael@0 | 86 | * values, they MUST be escaped with a BACKSLASH character. A BACKSLASH |
michael@0 | 87 | * character (US-ASCII decimal 92) in a "TEXT" property value MUST be |
michael@0 | 88 | * escaped with another BACKSLASH character. A COMMA character in a |
michael@0 | 89 | * "TEXT" property value MUST be escaped with a BACKSLASH character |
michael@0 | 90 | * (US-ASCII decimal 92). A SEMICOLON character in a "TEXT" property |
michael@0 | 91 | * value MUST be escaped with a BACKSLASH character (US-ASCII decimal |
michael@0 | 92 | * 92). However, a COLON character in a "TEXT" property value SHALL NOT |
michael@0 | 93 | * be escaped with a BACKSLASH character.Example: A multiple line value |
michael@0 | 94 | * of: |
michael@0 | 95 | * |
michael@0 | 96 | * Project XYZ Final Review |
michael@0 | 97 | * Conference Room - 3B |
michael@0 | 98 | * Come Prepared. |
michael@0 | 99 | * |
michael@0 | 100 | * would be represented as: |
michael@0 | 101 | * |
michael@0 | 102 | * Project XYZ Final Review\nConference Room - 3B\nCome Prepared. |
michael@0 | 103 | * </pre> |
michael@0 | 104 | */ |
michael@0 | 105 | public final class Strings { |
michael@0 | 106 | |
michael@0 | 107 | /** |
michael@0 | 108 | * Defines a regular expression representing all parameter strings that |
michael@0 | 109 | * should be quoted. |
michael@0 | 110 | */ |
michael@0 | 111 | public static final Pattern PARAM_QUOTE_PATTERN = Pattern.compile("[:;,]|[^\\p{ASCII}]"); |
michael@0 | 112 | |
michael@0 | 113 | private static final Pattern ESCAPE_PUNCTUATION_PATTERN = Pattern.compile("([,;])"); |
michael@0 | 114 | private static final Pattern UNESCAPE_PUNCTUATION_PATTERN = Pattern.compile("\\\\([,;\"])"); |
michael@0 | 115 | |
michael@0 | 116 | private static final Pattern ESCAPE_NEWLINE_PATTERN = Pattern.compile("\r?\n"); |
michael@0 | 117 | private static final Pattern UNESCAPE_NEWLINE_PATTERN = Pattern.compile("(?<!\\\\)\\\\n"); |
michael@0 | 118 | |
michael@0 | 119 | private static final Pattern ESCAPE_BACKSLASH_PATTERN = Pattern.compile("\\\\"); |
michael@0 | 120 | private static final Pattern UNESCAPE_BACKSLASH_PATTERN = Pattern.compile("\\\\\\\\"); |
michael@0 | 121 | |
michael@0 | 122 | |
michael@0 | 123 | |
michael@0 | 124 | /** |
michael@0 | 125 | * A string used to denote the start (and end) of iCalendar content lines. |
michael@0 | 126 | */ |
michael@0 | 127 | public static final String LINE_SEPARATOR = "\r\n"; |
michael@0 | 128 | |
michael@0 | 129 | /** |
michael@0 | 130 | * Constructor made private to prevent instantiation. |
michael@0 | 131 | */ |
michael@0 | 132 | private Strings() { |
michael@0 | 133 | } |
michael@0 | 134 | |
michael@0 | 135 | /** |
michael@0 | 136 | * Convenience method for adding quotes. The specified |
michael@0 | 137 | * object is converted to a string representation by |
michael@0 | 138 | * calling its <code>toString()</code> method. |
michael@0 | 139 | * @param aValue an object to quote |
michael@0 | 140 | * @return a quoted string |
michael@0 | 141 | */ |
michael@0 | 142 | public static String quote(final Object aValue) { |
michael@0 | 143 | if (aValue != null) { |
michael@0 | 144 | return "\"" + aValue + "\""; |
michael@0 | 145 | } |
michael@0 | 146 | return "\"\""; |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | /** |
michael@0 | 150 | * Convenience method for removing surrounding quotes |
michael@0 | 151 | * from a string value. |
michael@0 | 152 | * @param aValue a string to remove quotes from |
michael@0 | 153 | * @return an un-quoted string |
michael@0 | 154 | */ |
michael@0 | 155 | public static String unquote(final String aValue) { |
michael@0 | 156 | if (aValue != null && aValue.startsWith("\"") && aValue.endsWith("\"")) { |
michael@0 | 157 | return aValue.substring(0, aValue.length() - 1).substring(1); |
michael@0 | 158 | } |
michael@0 | 159 | return aValue; |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | /** |
michael@0 | 163 | * Convenience method for escaping special characters. |
michael@0 | 164 | * @param aValue a string value to escape |
michael@0 | 165 | * @return an escaped representation of the specified |
michael@0 | 166 | * string |
michael@0 | 167 | */ |
michael@0 | 168 | public static String escape(final String aValue) { |
michael@0 | 169 | return escapePunctuation(escapeNewline(escapeBackslash(aValue))); |
michael@0 | 170 | } |
michael@0 | 171 | |
michael@0 | 172 | /** |
michael@0 | 173 | * Convenience method for replacing escaped special characters |
michael@0 | 174 | * with their original form. |
michael@0 | 175 | * @param aValue a string value to unescape |
michael@0 | 176 | * @return a string representation of the specified |
michael@0 | 177 | * string with escaped characters replaced with their |
michael@0 | 178 | * original form |
michael@0 | 179 | */ |
michael@0 | 180 | public static String unescape(final String aValue) { |
michael@0 | 181 | return unescapeBackslash(unescapeNewline(unescapePunctuation(aValue))); |
michael@0 | 182 | } |
michael@0 | 183 | |
michael@0 | 184 | private static String escapePunctuation(String value) { |
michael@0 | 185 | if (value != null) { |
michael@0 | 186 | return ESCAPE_PUNCTUATION_PATTERN.matcher(value).replaceAll("\\\\$1"); |
michael@0 | 187 | } |
michael@0 | 188 | return value; |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | private static String unescapePunctuation(String value) { |
michael@0 | 192 | if (value != null) { |
michael@0 | 193 | return UNESCAPE_PUNCTUATION_PATTERN.matcher(value).replaceAll("$1"); |
michael@0 | 194 | } |
michael@0 | 195 | return value; |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | public static String escapeNewline(String value) { |
michael@0 | 199 | if (value != null) { |
michael@0 | 200 | return ESCAPE_NEWLINE_PATTERN.matcher(value).replaceAll("\\\\n"); |
michael@0 | 201 | } |
michael@0 | 202 | return value; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | private static String unescapeNewline(String value) { |
michael@0 | 206 | if (value != null) { |
michael@0 | 207 | return UNESCAPE_NEWLINE_PATTERN.matcher(value).replaceAll("\n"); |
michael@0 | 208 | } |
michael@0 | 209 | return value; |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | private static String escapeBackslash(String value) { |
michael@0 | 213 | if (value != null) { |
michael@0 | 214 | return ESCAPE_BACKSLASH_PATTERN.matcher(value).replaceAll("\\\\\\\\"); |
michael@0 | 215 | } |
michael@0 | 216 | return value; |
michael@0 | 217 | } |
michael@0 | 218 | |
michael@0 | 219 | private static String unescapeBackslash(String value) { |
michael@0 | 220 | if (value != null) { |
michael@0 | 221 | return UNESCAPE_BACKSLASH_PATTERN.matcher(value).replaceAll("\\\\"); |
michael@0 | 222 | } |
michael@0 | 223 | return value; |
michael@0 | 224 | } |
michael@0 | 225 | |
michael@0 | 226 | /** |
michael@0 | 227 | * Wraps <code>java.lang.String.valueOf()</code> to return an empty string |
michael@0 | 228 | * where the specified object is null. |
michael@0 | 229 | * @param object an object instance |
michael@0 | 230 | * @return a string representation of the object |
michael@0 | 231 | */ |
michael@0 | 232 | public static String valueOf(final Object object) { |
michael@0 | 233 | if (object == null) { |
michael@0 | 234 | return ""; |
michael@0 | 235 | } |
michael@0 | 236 | return object.toString(); |
michael@0 | 237 | } |
michael@0 | 238 | } |