001 /*
002 * Copyright 2008-2014 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.core.formatters;
017
018 import javax.annotation.Nonnull;
019 import javax.annotation.Nullable;
020 import java.util.Arrays;
021
022 import static griffon.util.GriffonNameUtils.isBlank;
023 import static java.util.Objects.requireNonNull;
024
025 /**
026 * @author Andres Almiray
027 * @since 2.0.0
028 */
029 public class BooleanFormatter extends AbstractFormatter<Boolean> {
030 public static final String PATTERN_BOOL = "boolean";
031 public static final String PATTERN_QUERY = "query";
032 public static final String PATTERN_SWITCH = "switch";
033 public static final String DEFAULT_PATTERN = PATTERN_BOOL;
034
035 private static final String[] PATTERNS = new String[]{
036 PATTERN_BOOL,
037 PATTERN_QUERY,
038 PATTERN_SWITCH
039 };
040
041 public static final BooleanFormatter BOOL = new BooleanFormatter(PATTERN_BOOL);
042 public static final BooleanFormatter QUERY = new BooleanFormatter(PATTERN_QUERY);
043 public static final BooleanFormatter SWITCH = new BooleanFormatter(PATTERN_SWITCH);
044
045 private static final BooleanFormatter[] FORMATTERS = new BooleanFormatter[]{
046 BOOL,
047 QUERY,
048 SWITCH
049 };
050
051 @Nonnull
052 public static BooleanFormatter getInstance(@Nullable String pattern) {
053 return new BooleanFormatter(pattern);
054 }
055
056 private final BooleanFormatterDelegate delegate;
057
058 public BooleanFormatter() {
059 this(DEFAULT_PATTERN);
060 }
061
062 protected BooleanFormatter(@Nullable String pattern) {
063 if (PATTERN_BOOL.equals(pattern)) {
064 delegate = new BoolBooleanFormatterDelegate();
065 } else if (PATTERN_QUERY.equals(pattern)) {
066 delegate = new QueryBooleanFormatterDelegate();
067 } else if (PATTERN_SWITCH.equals(pattern)) {
068 delegate = new SwitchBooleanFormatterDelegate();
069 } else if (isBlank(pattern)) {
070 delegate = new BoolBooleanFormatterDelegate();
071 } else {
072 throw new IllegalArgumentException("Invalid pattern '" + pattern + "'. Valid patterns are " + Arrays.toString(PATTERNS));
073 }
074 }
075
076 @Nonnull
077 public String getPattern() {
078 return delegate.getPattern();
079 }
080
081 @Nullable
082 public static Boolean parseBoolean(@Nullable String str) throws ParseException {
083 if (isBlank(str)) return null;
084 for (BooleanFormatter formatter : FORMATTERS) {
085 try {
086 return formatter.parse(str);
087 } catch (ParseException e) {
088 // ignore
089 }
090 }
091 throw parseError(str, Boolean.class);
092 }
093
094 @Nullable
095 @Override
096 public String format(@Nullable Boolean value) {
097 return value == null ? null : delegate.format(value);
098 }
099
100 @Nullable
101 @Override
102 @SuppressWarnings("ConstantConditions")
103 public Boolean parse(@Nullable String str) throws ParseException {
104 return isBlank(str) ? null : delegate.parse(str);
105 }
106
107 private static interface BooleanFormatterDelegate {
108 @Nonnull
109 String getPattern();
110
111 @Nonnull
112 String format(@Nonnull Boolean value);
113
114 @Nonnull
115 Boolean parse(@Nonnull String str) throws ParseException;
116 }
117
118 private static abstract class AbstractBooleanFormatterDelegate implements BooleanFormatterDelegate {
119 private final String pattern;
120 private final String[] tokens;
121
122 private AbstractBooleanFormatterDelegate(String pattern, String[] tokens) {
123 this.pattern = pattern;
124 this.tokens = tokens;
125 }
126
127 @Nonnull
128 public String getPattern() {
129 return pattern;
130 }
131
132 @Nonnull
133 public String format(@Nonnull Boolean bool) {
134 requireNonNull(bool, "Can't format given Boolean because it's null");
135 return bool ? tokens[1] : tokens[0];
136 }
137
138 @Nonnull
139 public Boolean parse(@Nonnull String str) throws ParseException {
140 if (tokens[0].equalsIgnoreCase(str)) {
141 return Boolean.FALSE;
142 } else if (tokens[1].equalsIgnoreCase(str)) {
143 return Boolean.TRUE;
144 }
145 throw parseError(str, Boolean.class);
146 }
147 }
148
149 private static class BoolBooleanFormatterDelegate extends AbstractBooleanFormatterDelegate {
150 private BoolBooleanFormatterDelegate() {
151 super(PATTERN_BOOL, new String[]{"false", "true"});
152 }
153 }
154
155 private static class QueryBooleanFormatterDelegate extends AbstractBooleanFormatterDelegate {
156 private QueryBooleanFormatterDelegate() {
157 super(PATTERN_QUERY, new String[]{"no", "yes"});
158 }
159 }
160
161 private static class SwitchBooleanFormatterDelegate extends AbstractBooleanFormatterDelegate {
162 private SwitchBooleanFormatterDelegate() {
163 super(PATTERN_SWITCH, new String[]{"off", "on"});
164 }
165 }
166 }
|