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