summaryrefslogtreecommitdiffstats
path: root/sched/src/com/android/sched/util/codec/PairCodec.java
diff options
context:
space:
mode:
Diffstat (limited to 'sched/src/com/android/sched/util/codec/PairCodec.java')
-rw-r--r--sched/src/com/android/sched/util/codec/PairCodec.java167
1 files changed, 167 insertions, 0 deletions
diff --git a/sched/src/com/android/sched/util/codec/PairCodec.java b/sched/src/com/android/sched/util/codec/PairCodec.java
new file mode 100644
index 00000000..4032bf89
--- /dev/null
+++ b/sched/src/com/android/sched/util/codec/PairCodec.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.sched.util.codec;
+
+import com.android.sched.util.config.ChainedException.ChainedExceptionBuilder;
+import com.android.sched.util.config.ConfigurationError;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
+/**
+ * This {@link StringCodec} is used to create an instance of {@link Entry}
+ */
+// STOPSHIP see https://android-review.googlesource.com/#/c/120553/17
+public class PairCodec<T, U> implements StringCodec<Entry<T, U>>{
+ @Nonnull
+ private final StringCodec<T> keyParser;
+ @Nonnull
+ private final StringCodec<U> valueParser;
+
+ @Nonnull
+ private String separator = "=";
+
+ public PairCodec(@Nonnull StringCodec<T> keyParser, @Nonnull StringCodec<U> valueParser) {
+ this.keyParser = keyParser;
+ this.valueParser = valueParser;
+ }
+
+ @Nonnull
+ public PairCodec<T, U> on(@Nonnull String separator) {
+ this.separator = separator;
+
+ return this;
+ }
+
+ @Nonnull
+ public String getSeparator() {
+ return separator;
+ }
+
+ @Override
+ @Nonnull
+ public Entry<T, U> parseString(@Nonnull CodecContext context,
+ @Nonnull String string) {
+ int endKey = string.indexOf(separator);
+ if (endKey == -1) {
+ throw new ConfigurationError("Missing '"
+ + separator + "' in '" + string + "'");
+ }
+ String key = string.substring(0, endKey);
+ String valueString = string.substring(endKey + separator.length());
+ return new AbstractMap.SimpleEntry<T, U>(keyParser.parseString(context, key),
+ valueParser.parseString(context, valueString));
+ }
+
+ @Override
+ @CheckForNull
+ public Entry<T, U> checkString(@Nonnull CodecContext context,
+ @Nonnull String string)
+ throws ParsingException {
+
+ ChainedExceptionBuilder<ParsingException> exceptions =
+ new ChainedExceptionBuilder<ParsingException>();
+
+ T keyElement = null;
+ U valueElement = null;
+ int endKey = string.indexOf(separator);
+ if (endKey == -1) {
+ exceptions.appendException(new ParsingException("Missing '"
+ + separator + "' in '" + string + "'"));
+ } else {
+ String key = string.substring(0, endKey);
+ String valueString = string.substring(endKey + separator.length());
+ try {
+ keyElement = keyParser.checkString(context, key);
+ } catch (ParsingException e) {
+ exceptions.appendException(e);
+ }
+ try {
+ valueElement = valueParser.checkString(context, valueString);
+ } catch (ParsingException e) {
+ exceptions.appendException(e);
+ }
+ }
+
+ exceptions.throwIfNecessary();
+ // If one element is null, do not compute the pair
+ if (keyElement == null || valueElement == null) {
+ return null;
+ } else {
+ return new AbstractMap.SimpleEntry<T, U>(keyElement, valueElement);
+ }
+ }
+
+ @Override
+ @Nonnull
+ public String getUsage() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("<key>" + separator + "<value>");
+ sb.append(" where <key> is ");
+ sb.append(keyParser.getUsage());
+ sb.append(" and where <value> is ");
+ sb.append(valueParser.getUsage());
+
+ return sb.toString();
+ }
+
+ @Override
+ @Nonnull
+ public List<com.android.sched.util.codec.Parser.ValueDescription> getValueDescriptions() {
+ List<com.android.sched.util.codec.Parser.ValueDescription> list =
+ new ArrayList<Parser.ValueDescription>();
+ list.addAll(keyParser.getValueDescriptions());
+ list.addAll(valueParser.getValueDescriptions());
+ return list;
+ }
+
+ @Override
+ @Nonnull
+ public String formatValue(@Nonnull Entry<T, U> data) {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(keyParser.formatValue(data.getKey()));
+ sb.append(separator);
+ sb.append(valueParser.formatValue(data.getValue()));
+ return sb.toString();
+ }
+
+ @Override
+ public void checkValue(@Nonnull CodecContext context, @Nonnull Entry<T, U> data)
+ throws CheckingException {
+ ChainedExceptionBuilder<CheckingException> exceptions =
+ new ChainedExceptionBuilder<CheckingException>();
+ try {
+ keyParser.checkValue(context, data.getKey());
+ } catch (CheckingException e) {
+ exceptions.appendException(e);
+ }
+ try {
+ valueParser.checkValue(context, data.getValue());
+ } catch (CheckingException e) {
+ exceptions.appendException(e);
+ }
+
+ exceptions.throwIfNecessary();
+ }
+
+}