1 /* 2 * Copyright (C) 2015 Square, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.squareup.javapoet; 17 18 import java.util.ArrayList; 19 import java.util.Arrays; 20 import java.util.Collection; 21 import java.util.Collections; 22 import java.util.LinkedHashMap; 23 import java.util.LinkedHashSet; 24 import java.util.List; 25 import java.util.Map; 26 import java.util.Set; 27 import javax.lang.model.element.Modifier; 28 29 import static java.lang.Character.isISOControl; 30 31 /** 32 * Like Guava, but worse and standalone. This makes it easier to mix JavaPoet with libraries that 33 * bring their own version of Guava. 34 */ 35 final class Util { Util()36 private Util() { 37 } 38 immutableMultimap(Map<K, List<V>> multimap)39 static <K, V> Map<K, List<V>> immutableMultimap(Map<K, List<V>> multimap) { 40 LinkedHashMap<K, List<V>> result = new LinkedHashMap<>(); 41 for (Map.Entry<K, List<V>> entry : multimap.entrySet()) { 42 if (entry.getValue().isEmpty()) continue; 43 result.put(entry.getKey(), immutableList(entry.getValue())); 44 } 45 return Collections.unmodifiableMap(result); 46 } 47 immutableMap(Map<K, V> map)48 static <K, V> Map<K, V> immutableMap(Map<K, V> map) { 49 return Collections.unmodifiableMap(new LinkedHashMap<>(map)); 50 } 51 checkArgument(boolean condition, String format, Object... args)52 static void checkArgument(boolean condition, String format, Object... args) { 53 if (!condition) throw new IllegalArgumentException(String.format(format, args)); 54 } 55 checkNotNull(T reference, String format, Object... args)56 static <T> T checkNotNull(T reference, String format, Object... args) { 57 if (reference == null) throw new NullPointerException(String.format(format, args)); 58 return reference; 59 } 60 checkState(boolean condition, String format, Object... args)61 static void checkState(boolean condition, String format, Object... args) { 62 if (!condition) throw new IllegalStateException(String.format(format, args)); 63 } 64 immutableList(Collection<T> collection)65 static <T> List<T> immutableList(Collection<T> collection) { 66 return Collections.unmodifiableList(new ArrayList<>(collection)); 67 } 68 immutableSet(Collection<T> set)69 static <T> Set<T> immutableSet(Collection<T> set) { 70 return Collections.unmodifiableSet(new LinkedHashSet<>(set)); 71 } 72 union(Set<T> a, Set<T> b)73 static <T> Set<T> union(Set<T> a, Set<T> b) { 74 Set<T> result = new LinkedHashSet<>(); 75 result.addAll(a); 76 result.addAll(b); 77 return result; 78 } 79 requireExactlyOneOf(Set<Modifier> modifiers, Modifier... mutuallyExclusive)80 static void requireExactlyOneOf(Set<Modifier> modifiers, Modifier... mutuallyExclusive) { 81 int count = 0; 82 for (Modifier modifier : mutuallyExclusive) { 83 if (modifiers.contains(modifier)) count++; 84 } 85 checkArgument(count == 1, "modifiers %s must contain one of %s", 86 modifiers, Arrays.toString(mutuallyExclusive)); 87 } 88 characterLiteralWithoutSingleQuotes(char c)89 static String characterLiteralWithoutSingleQuotes(char c) { 90 // see https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.10.6 91 switch (c) { 92 case '\b': return "\\b"; /* \u0008: backspace (BS) */ 93 case '\t': return "\\t"; /* \u0009: horizontal tab (HT) */ 94 case '\n': return "\\n"; /* \u000a: linefeed (LF) */ 95 case '\f': return "\\f"; /* \u000c: form feed (FF) */ 96 case '\r': return "\\r"; /* \u000d: carriage return (CR) */ 97 case '\"': return "\""; /* \u0022: double quote (") */ 98 case '\'': return "\\'"; /* \u0027: single quote (') */ 99 case '\\': return "\\\\"; /* \u005c: backslash (\) */ 100 default: 101 return isISOControl(c) ? String.format("\\u%04x", (int) c) : Character.toString(c); 102 } 103 } 104 105 /** Returns the string literal representing {@code value}, including wrapping double quotes. */ stringLiteralWithDoubleQuotes(String value, String indent)106 static String stringLiteralWithDoubleQuotes(String value, String indent) { 107 StringBuilder result = new StringBuilder(value.length() + 2); 108 result.append('"'); 109 for (int i = 0; i < value.length(); i++) { 110 char c = value.charAt(i); 111 // trivial case: single quote must not be escaped 112 if (c == '\'') { 113 result.append("'"); 114 continue; 115 } 116 // trivial case: double quotes must be escaped 117 if (c == '\"') { 118 result.append("\\\""); 119 continue; 120 } 121 // default case: just let character literal do its work 122 result.append(characterLiteralWithoutSingleQuotes(c)); 123 // need to append indent after linefeed? 124 if (c == '\n' && i + 1 < value.length()) { 125 result.append("\"\n").append(indent).append(indent).append("+ \""); 126 } 127 } 128 result.append('"'); 129 return result.toString(); 130 } 131 } 132