You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aurora.apache.org by zm...@apache.org on 2015/08/25 20:19:47 UTC
[33/37] aurora git commit: Import of Twitter Commons.
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/CharacterParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/CharacterParser.java b/commons/src/main/java/com/twitter/common/args/parsers/CharacterParser.java
new file mode 100644
index 0000000..9a5f9ad
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/CharacterParser.java
@@ -0,0 +1,36 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Character parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class CharacterParser extends NonParameterizedTypeParser<Character> {
+ @Override
+ public Character doParse(String raw) {
+ checkArgument(raw.length() == 1,
+ "String " + raw + " cannot be assigned to a character.");
+ return raw.charAt(0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/ClassParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/ClassParser.java b/commons/src/main/java/com/twitter/common/args/parsers/ClassParser.java
new file mode 100644
index 0000000..bf32dc1
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/ClassParser.java
@@ -0,0 +1,51 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.base.Preconditions;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.TypeUtil;
+
+/**
+ * Class parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ClassParser extends TypeParameterizedParser<Class<?>> {
+
+ public ClassParser() {
+ super(1);
+ }
+
+ @Override
+ public Class<?> doParse(ParserOracle parserOracle, String raw, final List<Type> typeParams) {
+ Class<?> rawClassType = TypeUtil.getRawType(typeParams.get(0));
+ try {
+ Class<?> actualClass = Class.forName(raw);
+ Preconditions.checkArgument(rawClassType.isAssignableFrom(actualClass));
+ return actualClass;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException("Could not find class " + raw);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/DateParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/DateParser.java b/commons/src/main/java/com/twitter/common/args/parsers/DateParser.java
new file mode 100644
index 0000000..651004b
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/DateParser.java
@@ -0,0 +1,44 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Date parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class DateParser extends NonParameterizedTypeParser<Date> {
+
+ private static final String FORMAT = "MM/dd/yyyy HH:mm";
+ private static final SimpleDateFormat SIMPLE_FORMAT = new SimpleDateFormat(FORMAT);
+
+ @Override
+ public Date doParse(String raw) {
+ try {
+ return SIMPLE_FORMAT.parse(raw);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException("Failed to parse " + raw + " in format " + FORMAT);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/DoubleParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/DoubleParser.java b/commons/src/main/java/com/twitter/common/args/parsers/DoubleParser.java
new file mode 100644
index 0000000..1965625
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/DoubleParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Double parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class DoubleParser extends NumberParser<Double> {
+ @Override
+ Double parseNumber(String raw) {
+ return Double.parseDouble(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/DurationParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/DurationParser.java b/commons/src/main/java/com/twitter/common/args/parsers/DurationParser.java
new file mode 100644
index 0000000..bcb4bf8
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/DurationParser.java
@@ -0,0 +1,83 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import com.google.common.base.Preconditions;
+
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Time;
+
+/**
+ * Utility class for parsing durations of the form "1d23h59m59s" (as well as subvariants, i.e.
+ * "10h5s" would also work, as would "2d"). These values are useful representations in HTTP query
+ * parameters for durations.
+ *
+ */
+public class DurationParser extends TypeParameterizedParser<Amount<?, ?>> {
+
+ private static final String SUFFIXES = "dhms";
+ private static final Time[] TIME_UNITS = {Time.DAYS, Time.HOURS, Time.MINUTES, Time.SECONDS};
+
+ public DurationParser() {
+ super(2);
+ }
+
+ @Override
+ Amount<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> paramParsers)
+ throws IllegalArgumentException {
+ Type secondParamClass = paramParsers.get(1);
+ Preconditions.checkArgument(
+ secondParamClass == Time.class,
+ String.format("Expected %s for "
+ + "second type parameter, but got got %s", Time.class.getName(),
+ secondParamClass));
+ return parse(raw);
+ }
+
+ /**
+ * Parses a duration of the form "1d23h59m59s" (as well as subvariants, i.e. "10h5s" would also
+ * work, as would "2d").
+ *
+ * @param spec the textual duration specification
+ * @return the parsed form
+ * @throws IllegalArgumentException if the specification can not be parsed
+ */
+ public static Amount<Long, Time> parse(String spec) {
+ long time = 0L;
+ final List<Object> tokens = Collections.list(new StringTokenizer(spec, SUFFIXES, true));
+ Preconditions.checkArgument(tokens.size() > 1);
+ for (int i = 1; i < tokens.size(); i += 2) {
+ final String token = (String) tokens.get(i);
+ Preconditions.checkArgument(token.length() == 1, "Too long suffix '%s'", token);
+ final int suffixIndex = SUFFIXES.indexOf(token.charAt(0));
+ Preconditions.checkArgument(suffixIndex != -1, "Unrecognized suffix '%s'", token);
+ try {
+ final int value = Integer.parseInt((String) tokens.get(i - 1));
+ time += Amount.of(value, TIME_UNITS[suffixIndex]).as(Time.SECONDS);
+ } catch (NumberFormatException e) {
+ Preconditions.checkArgument(false, "Invalid number %s", tokens.get(i - 1));
+ }
+ }
+ return Amount.of(time, Time.SECONDS);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/EnumParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/EnumParser.java b/commons/src/main/java/com/twitter/common/args/parsers/EnumParser.java
new file mode 100644
index 0000000..1741b7d
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/EnumParser.java
@@ -0,0 +1,39 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+
+/**
+ * An {@link Enum} parser that matches enum values via {@link Enum#valueOf(Class, String)}.
+ *
+ * @author John Sirois
+ */
+@ArgParser
+public class EnumParser<T extends Enum<T>> implements Parser<T> {
+
+ @Override
+ public T parse(ParserOracle parserOracle, Type type, String raw) throws IllegalArgumentException {
+ @SuppressWarnings("unchecked")
+ Class<T> enumClass = (Class<T>) type;
+ return Enum.valueOf(enumClass, raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/FileParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/FileParser.java b/commons/src/main/java/com/twitter/common/args/parsers/FileParser.java
new file mode 100644
index 0000000..a3cf1b2
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/FileParser.java
@@ -0,0 +1,34 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.io.File;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * File parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class FileParser extends NonParameterizedTypeParser<File> {
+ @Override
+ public File doParse(String raw) {
+ return new File(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/FloatParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/FloatParser.java b/commons/src/main/java/com/twitter/common/args/parsers/FloatParser.java
new file mode 100644
index 0000000..3330bba
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/FloatParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Float parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class FloatParser extends NumberParser<Float> {
+ @Override
+ Float parseNumber(String raw) {
+ return Float.parseFloat(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/InetSocketAddressParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/InetSocketAddressParser.java b/commons/src/main/java/com/twitter/common/args/parsers/InetSocketAddressParser.java
new file mode 100644
index 0000000..584240b
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/InetSocketAddressParser.java
@@ -0,0 +1,35 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.net.InetSocketAddress;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.net.InetSocketAddressHelper;
+
+/**
+ * InetSocketAddress parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class InetSocketAddressParser extends NonParameterizedTypeParser<InetSocketAddress> {
+ @Override
+ public InetSocketAddress doParse(String raw) {
+ return InetSocketAddressHelper.parse(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/IntegerParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/IntegerParser.java b/commons/src/main/java/com/twitter/common/args/parsers/IntegerParser.java
new file mode 100644
index 0000000..c4bcd23
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/IntegerParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Integer parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class IntegerParser extends NumberParser<Integer> {
+ @Override
+ Integer parseNumber(String raw) {
+ return Integer.parseInt(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/ListParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/ListParser.java b/commons/src/main/java/com/twitter/common/args/parsers/ListParser.java
new file mode 100644
index 0000000..79434c0
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/ListParser.java
@@ -0,0 +1,55 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.Parsers;
+
+/**
+ * List parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ListParser extends TypeParameterizedParser<List<?>> {
+
+ public ListParser() {
+ super(1);
+ }
+
+ @Override
+ List<?> doParse(final ParserOracle parserOracle, String raw, final List<Type> typeParams) {
+ final Type listType = typeParams.get(0);
+ final Parser<?> parser = parserOracle.get(TypeToken.of(listType));
+ return ImmutableList.copyOf(Iterables.transform(Parsers.MULTI_VALUE_SPLITTER.split(raw),
+ new Function<String, Object>() {
+ @Override public Object apply(String raw) {
+ return parser.parse(parserOracle, listType, raw);
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/LongParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/LongParser.java b/commons/src/main/java/com/twitter/common/args/parsers/LongParser.java
new file mode 100644
index 0000000..83c6752
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/LongParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Long parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class LongParser extends NumberParser<Long> {
+ @Override
+ Long parseNumber(String raw) {
+ return Long.parseLong(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/MapParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/MapParser.java b/commons/src/main/java/com/twitter/common/args/parsers/MapParser.java
new file mode 100644
index 0000000..19de492
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/MapParser.java
@@ -0,0 +1,71 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.Parsers;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Map parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class MapParser extends TypeParameterizedParser<Map<?, ?>> {
+
+ private static final Splitter KEY_VALUE_SPLITTER =
+ Splitter.on("=").trimResults().omitEmptyStrings();
+
+ public MapParser() {
+ super(2);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ Map<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> typeParams) {
+ Type keyType = typeParams.get(0);
+ Parser<?> keyParser = parserOracle.get(TypeToken.of(keyType));
+
+ Type valueType = typeParams.get(1);
+ Parser<?> valueParser = parserOracle.get(TypeToken.of(valueType));
+
+ ImmutableMap.Builder<Object, Object> map = ImmutableMap.builder();
+ for (String keyAndValue : Parsers.MULTI_VALUE_SPLITTER.split(raw)) {
+ List<String> fields = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyAndValue));
+ checkArgument(fields.size() == 2,
+ "Failed to parse key/value pair " + keyAndValue);
+
+ map.put(keyParser.parse(parserOracle, keyType, fields.get(0)),
+ valueParser.parse(parserOracle, valueType, fields.get(1)));
+ }
+
+ return map.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/NonParameterizedTypeParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/NonParameterizedTypeParser.java b/commons/src/main/java/com/twitter/common/args/parsers/NonParameterizedTypeParser.java
new file mode 100644
index 0000000..187de17
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/NonParameterizedTypeParser.java
@@ -0,0 +1,44 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+
+/**
+ * Base class for parsers of types that are not parameterized.
+ *
+ * @author William Farner
+ */
+public abstract class NonParameterizedTypeParser<T> implements Parser<T> {
+
+ /**
+ * Performs the parsing of the raw string.
+ *
+ * @param raw Value to parse.
+ * @return The parsed value.
+ * @throws IllegalArgumentException If the value could not be parsed into the target type.
+ */
+ public abstract T doParse(String raw) throws IllegalArgumentException;
+
+ @Override
+ public T parse(ParserOracle parserOracle, Type type, String raw) throws IllegalArgumentException {
+ return doParse(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/NumberParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/NumberParser.java b/commons/src/main/java/com/twitter/common/args/parsers/NumberParser.java
new file mode 100644
index 0000000..4214f59
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/NumberParser.java
@@ -0,0 +1,44 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+/**
+ * Parser that handles common functionality for parsing numbers.
+ *
+ * @author William Farner
+ */
+public abstract class NumberParser<T extends Number> extends NonParameterizedTypeParser<T> {
+
+ /**
+ * Performs the actual parsing of the value into the target type.
+ *
+ * @param raw Raw value to parse.
+ * @return The parsed value.
+ * @throws NumberFormatException If the raw value does not represent a valid number of the target
+ * type.
+ */
+ abstract T parseNumber(String raw) throws NumberFormatException;
+
+ @Override
+ public T doParse(String raw) throws IllegalArgumentException {
+ try {
+ return parseNumber(raw);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(String.format("Invalid value: " + e.getMessage()));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/PairParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/PairParser.java b/commons/src/main/java/com/twitter/common/args/parsers/PairParser.java
new file mode 100644
index 0000000..5356321
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/PairParser.java
@@ -0,0 +1,60 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.TypeToken;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.Parsers;
+import com.twitter.common.collections.Pair;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Pair parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class PairParser extends TypeParameterizedParser<Pair<?, ?>> {
+
+ public PairParser() {
+ super(2);
+ }
+
+ @Override
+ Pair<?, ?> doParse(ParserOracle parserOracle, String raw, List<Type> typeParams) {
+ Type leftType = typeParams.get(0);
+ Parser<?> leftParser = parserOracle.get(TypeToken.of(leftType));
+
+ Type rightType = typeParams.get(1);
+ Parser<?> rightParser = parserOracle.get(TypeToken.of(rightType));
+
+ List<String> parts = ImmutableList.copyOf(Parsers.MULTI_VALUE_SPLITTER.split(raw));
+ checkArgument(parts.size() == 2,
+ "Only two values may be specified for a pair, you gave " + parts.size());
+
+ return Pair.of(leftParser.parse(parserOracle, leftType, parts.get(0)),
+ rightParser.parse(parserOracle, rightType, parts.get(1)));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/PatternParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/PatternParser.java b/commons/src/main/java/com/twitter/common/args/parsers/PatternParser.java
new file mode 100644
index 0000000..1834628
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/PatternParser.java
@@ -0,0 +1,38 @@
+// =================================================================================================
+// Copyright 2013 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * A regular expression parser.
+ */
+@ArgParser
+public class PatternParser extends NonParameterizedTypeParser<Pattern> {
+
+ @Override
+ public Pattern doParse(String raw) throws IllegalArgumentException {
+ try {
+ return Pattern.compile(raw);
+ } catch (PatternSyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/RangeParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/RangeParser.java b/commons/src/main/java/com/twitter/common/args/parsers/RangeParser.java
new file mode 100644
index 0000000..0cba553
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/RangeParser.java
@@ -0,0 +1,33 @@
+package com.twitter.common.args.parsers;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Range;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * A parser that handles closed ranges. For the input "4-6", it will capture [4, 5, 6].
+ */
+@ArgParser
+public class RangeParser extends NonParameterizedTypeParser<Range<Integer>> {
+ @Override
+ public Range<Integer> doParse(String raw) throws IllegalArgumentException {
+ ImmutableList<String> numbers =
+ ImmutableList.copyOf(Splitter.on('-').omitEmptyStrings().split(raw));
+ try {
+ int from = Integer.parseInt(numbers.get(0));
+ int to = Integer.parseInt(numbers.get(1));
+ if (numbers.size() != 2) {
+ throw new IllegalArgumentException("Failed to parse the range:" + raw);
+ }
+ if (to < from) {
+ return Range.closed(to, from);
+ } else {
+ return Range.closed(from, to);
+ }
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Failed to parse the range:" + raw, e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/SetParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/SetParser.java b/commons/src/main/java/com/twitter/common/args/parsers/SetParser.java
new file mode 100644
index 0000000..fecaeb2
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/SetParser.java
@@ -0,0 +1,57 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.Parsers;
+
+/**
+ * Set parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class SetParser extends TypeParameterizedParser<Set<?>> {
+
+ public SetParser() {
+ super(1);
+ }
+
+ @Override
+ Set<?> doParse(final ParserOracle parserOracle, String raw, List<Type> typeParams) {
+ final Type setType = typeParams.get(0);
+ final Parser<?> parser = parserOracle.get(TypeToken.of(setType));
+
+ return ImmutableSet.copyOf(Iterables.transform(Parsers.MULTI_VALUE_SPLITTER.split(raw),
+ new Function<String, Object>() {
+ @Override public Object apply(String raw) {
+ return parser.parse(parserOracle, setType, raw);
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/ShortParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/ShortParser.java b/commons/src/main/java/com/twitter/common/args/parsers/ShortParser.java
new file mode 100644
index 0000000..b13386c
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/ShortParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * Short parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class ShortParser extends NumberParser<Short> {
+ @Override
+ Short parseNumber(String raw) {
+ return Short.parseShort(raw);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/StringParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/StringParser.java b/commons/src/main/java/com/twitter/common/args/parsers/StringParser.java
new file mode 100644
index 0000000..a403917
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/StringParser.java
@@ -0,0 +1,32 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * String parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class StringParser extends NonParameterizedTypeParser<String> {
+ @Override
+ public String doParse(String raw) {
+ return raw;
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/TypeParameterizedParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/TypeParameterizedParser.java b/commons/src/main/java/com/twitter/common/args/parsers/TypeParameterizedParser.java
new file mode 100644
index 0000000..7ded11f
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/TypeParameterizedParser.java
@@ -0,0 +1,68 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.lang.reflect.Type;
+import java.util.List;
+
+import com.twitter.common.args.Parser;
+import com.twitter.common.args.ParserOracle;
+import com.twitter.common.args.TypeUtil;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Parser that makes implementation of parsers for parameterized types simpler.
+ *
+ * @param <T> The raw type this parser can parse.
+ *
+ * @author William Farner
+ */
+public abstract class TypeParameterizedParser<T> implements Parser<T> {
+
+ private final int typeParamCount;
+
+ /**
+ * Creates a new type parameterized parser.
+ *
+ * @param typeParamCount Strict number of type parameters to allow on the assigned type.
+ */
+ TypeParameterizedParser(int typeParamCount) {
+ this.typeParamCount = typeParamCount;
+ }
+
+ /**
+ * Performs the actual parsing.
+ *
+ * @param parserOracle The registered parserOracle for delegation.
+ * @param raw The raw value to parse.
+ * @param typeParams The captured actual type parameters for {@code T}.
+ * @return The parsed value.
+ * @throws IllegalArgumentException If the value could not be parsed.
+ */
+ abstract T doParse(ParserOracle parserOracle, String raw, List<Type> typeParams)
+ throws IllegalArgumentException;
+
+ @Override public T parse(ParserOracle parserOracle, Type type, String raw) {
+ List<Type> typeParams = TypeUtil.getTypeParams(type);
+ checkArgument(typeParams.size() == typeParamCount, String.format(
+ "Expected %d type parameters for %s but got %d",
+ typeParamCount, type, typeParams.size()));
+
+ return doParse(parserOracle, raw, typeParams);
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/URIParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/URIParser.java b/commons/src/main/java/com/twitter/common/args/parsers/URIParser.java
new file mode 100644
index 0000000..fce84c0
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/URIParser.java
@@ -0,0 +1,39 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * URI parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class URIParser extends NonParameterizedTypeParser<URI> {
+ @Override
+ public URI doParse(String raw) {
+ try {
+ return new URI(raw);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Malformed URI " + raw + ", " + e.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/URLParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/URLParser.java b/commons/src/main/java/com/twitter/common/args/parsers/URLParser.java
new file mode 100644
index 0000000..33bcd49
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/URLParser.java
@@ -0,0 +1,39 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import com.twitter.common.args.ArgParser;
+
+/**
+ * URL parser.
+ *
+ * @author William Farner
+ */
+@ArgParser
+public class URLParser extends NonParameterizedTypeParser<URL> {
+ @Override
+ public URL doParse(String raw) {
+ try {
+ return new URL(raw);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException("Malformed URL " + raw + ", " + e.getMessage());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/args/parsers/UnitParser.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/args/parsers/UnitParser.java b/commons/src/main/java/com/twitter/common/args/parsers/UnitParser.java
new file mode 100644
index 0000000..0ccba62
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/args/parsers/UnitParser.java
@@ -0,0 +1,57 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.args.parsers;
+
+import java.util.EnumSet;
+import java.util.Map;
+
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+
+import com.twitter.common.args.ArgParser;
+import com.twitter.common.quantity.Data;
+import com.twitter.common.quantity.Time;
+import com.twitter.common.quantity.Unit;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Unit parser.
+ * Units are matched (case sensitively) against the result of {@link Unit#toString()}.
+ */
+@ArgParser
+public class UnitParser extends NonParameterizedTypeParser<Unit<?>> {
+
+ private final Map<String, Unit<?>> unitValues;
+
+ public UnitParser() {
+ unitValues = Maps.uniqueIndex(
+ ImmutableList.<Unit<?>>builder().add(Time.values()).add(Data.values()).build(),
+ Functions.toStringFunction());
+ }
+
+ @Override
+ public Unit<?> doParse(String raw) {
+ Unit<?> unit = unitValues.get(raw);
+
+ checkArgument(unit != null, String.format(
+ "No Units found matching %s, options: (Time): %s, (Data): %s",
+ raw, EnumSet.allOf(Time.class), EnumSet.allOf(Data.class)));
+ return unit;
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/CachingSupplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/CachingSupplier.java b/commons/src/main/java/com/twitter/common/base/CachingSupplier.java
new file mode 100644
index 0000000..561dfec
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/CachingSupplier.java
@@ -0,0 +1,71 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+import com.twitter.common.quantity.Amount;
+import com.twitter.common.quantity.Time;
+import com.twitter.common.util.Clock;
+
+/**
+ * A supplier that caches responses from an underling supplier, expiring the cached value after
+ * a fixed expiration time.
+ *
+ * @param <T> Supplied value type.
+ *
+ * @author William Farner
+ */
+public class CachingSupplier<T> implements Supplier<T> {
+
+ private final Supplier<T> wrapped;
+ private final long expirationNanos;
+ private final Clock clock;
+
+ private long lastFetchNanos = -1;
+ private T cachedValue;
+
+ /**
+ * Creates a new caching supplier.
+ *
+ * @param wrapped The supplier to delegate fetches to.
+ * @param expiration The maximum amount of time that a response from {@code supplier} will be
+ * cached for. The expiration must be positive.
+ */
+ public CachingSupplier(Supplier<T> wrapped, Amount<Long, Time> expiration) {
+ this(wrapped, expiration, Clock.SYSTEM_CLOCK);
+ }
+
+ @VisibleForTesting
+ CachingSupplier(Supplier<T> wrapped, Amount<Long, Time> expiration, Clock clock) {
+ this.wrapped = Preconditions.checkNotNull(wrapped);
+ this.expirationNanos = Preconditions.checkNotNull(expiration).as(Time.NANOSECONDS);
+ Preconditions.checkArgument(expiration.getValue() > 0, "Expiration must be positive.");
+ this.clock = Preconditions.checkNotNull(clock);
+ }
+
+ @Override
+ public synchronized T get() {
+ if ((lastFetchNanos == -1) || (clock.nowNanos() - lastFetchNanos > expirationNanos)) {
+ cachedValue = wrapped.get();
+ lastFetchNanos = clock.nowNanos();
+ }
+
+ return cachedValue;
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/CallableExceptionalSupplier.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/CallableExceptionalSupplier.java b/commons/src/main/java/com/twitter/common/base/CallableExceptionalSupplier.java
new file mode 100644
index 0000000..0d3692c
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/CallableExceptionalSupplier.java
@@ -0,0 +1,35 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+import java.util.concurrent.Callable;
+
+/**
+ * A supplier that may also be called.
+ *
+ * @param <T> The supplier type.
+ * @param <E> Supplier exception type.
+ *
+ * @author John Sirois
+ */
+public abstract class CallableExceptionalSupplier<T, E extends Exception>
+ implements ExceptionalSupplier<T, E>, Callable<T> {
+
+ @Override public T call() throws Exception {
+ return get();
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/Closure.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/Closure.java b/commons/src/main/java/com/twitter/common/base/Closure.java
new file mode 100644
index 0000000..94ae264
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/Closure.java
@@ -0,0 +1,28 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+/**
+ * A closure that does not throw any checked exceptions.
+ *
+ * @param <T> Closure value type.
+ *
+ * @author John Sirois
+ */
+public interface Closure<T> extends ExceptionalClosure<T, RuntimeException> {
+ // convenience typedef
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/Closures.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/Closures.java b/commons/src/main/java/com/twitter/common/base/Closures.java
new file mode 100644
index 0000000..f8dc61c
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/Closures.java
@@ -0,0 +1,136 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utilities for dealing with Closures.
+ *
+ * @author John Sirois
+ */
+public final class Closures {
+
+ private static final Closure<?> NOOP = new Closure<Object>() {
+ @Override public void execute(Object item) {
+ // noop
+ }
+ };
+
+ private Closures() {
+ // utility
+ }
+
+ /**
+ * Converts a closure into a function returning {@code null}.
+ */
+ public static <T> Function<T, Void> asFunction(final ExceptionalClosure<T, ?> closure) {
+ checkNotNull(closure);
+
+ // CHECKSTYLE:OFF IllegalCatch
+ return new Function<T, Void>() {
+ @Override public Void apply(T item) {
+ try {
+ closure.execute(item);
+ } catch (Exception e) {
+ Throwables.propagate(e);
+ }
+ return null;
+ }
+ };
+ // CHECKSTYLE:ON IllegalCatch
+ }
+
+ /**
+ * Varargs equivalent of {@link #combine(Iterable)}.
+ *
+ * @param closures Closures to combine.
+ * @param <T> Type accepted by the closures.
+ * @return A single closure that will fan out all calls to {@link Closure#execute(Object)} to
+ * the wrapped closures.
+ */
+ public static <T> Closure<T> combine(Closure<T>... closures) {
+ return combine(ImmutableList.copyOf(closures));
+ }
+
+ /**
+ * Combines multiple closures into a single closure, whose calls are replicated sequentially
+ * in the order that they were provided.
+ * If an exception is encountered from a closure it propagates to the top-level closure and the
+ * remaining closures are not executed.
+ *
+ * @param closures Closures to combine.
+ * @param <T> Type accepted by the closures.
+ * @return A single closure that will fan out all calls to {@link Closure#execute(Object)} to
+ * the wrapped closures.
+ */
+ public static <T> Closure<T> combine(Iterable<Closure<T>> closures) {
+ checkNotNull(closures);
+ checkArgument(Iterables.all(closures, Predicates.notNull()));
+
+ final Iterable<Closure<T>> closuresCopy = ImmutableList.copyOf(closures);
+
+ return new Closure<T>() {
+ @Override public void execute(T item) {
+ for (Closure<T> closure : closuresCopy) {
+ closure.execute(item);
+ }
+ }
+ };
+ }
+
+ /**
+ * Applies a filter to a closure, such that the closure will only be called when the filter is
+ * satisfied (returns {@code true}}.
+ *
+ * @param filter Filter to determine when {@code closure} is called.
+ * @param closure Closure to filter.
+ * @param <T> Type handled by the filter and the closure.
+ * @return A filtered closure.
+ */
+ public static <T> Closure<T> filter(final Predicate<T> filter, final Closure<T> closure) {
+ checkNotNull(filter);
+ checkNotNull(closure);
+
+ return new Closure<T>() {
+ @Override public void execute(T item) {
+ if (filter.apply(item)) {
+ closure.execute(item);
+ }
+ }
+ };
+ }
+
+ /**
+ * Returns a closure that will do nothing.
+ *
+ * @param <T> The closure argument type.
+ * @return A closure that does nothing.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Closure<T> noop() {
+ return (Closure<T>) NOOP;
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/Command.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/Command.java b/commons/src/main/java/com/twitter/common/base/Command.java
new file mode 100644
index 0000000..306b552
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/Command.java
@@ -0,0 +1,26 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+/**
+ * A command that does not throw any checked exceptions.
+ *
+ * @author John Sirois
+ */
+public interface Command extends ExceptionalCommand<RuntimeException> {
+ // convenience typedef
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/Commands.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/Commands.java b/commons/src/main/java/com/twitter/common/base/Commands.java
new file mode 100644
index 0000000..7d8d782
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/Commands.java
@@ -0,0 +1,80 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+import com.google.common.collect.ImmutableList;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utility functions for working with commands.
+ *
+ * @author John Sirois
+ */
+public final class Commands {
+
+ /**
+ * A command that does nothing when executed.
+ */
+ public static final Command NOOP = new Command() {
+ @Override public void execute() {
+ // noop
+ }
+ };
+
+ private Commands() {
+ // utility
+ }
+
+ /**
+ * Converts a command into a supplier returning null.
+ *
+ * @return A supplier whose {@link com.twitter.common.base.Supplier#get()} will cause the given
+ * {@code command} to be executed and {@code null} to be returned.
+ */
+ public static <E extends Exception> ExceptionalSupplier<Void, E> asSupplier(
+ final ExceptionalCommand<E> command) {
+ checkNotNull(command);
+
+ return new ExceptionalSupplier<Void, E>() {
+ @Override public Void get() throws E {
+ command.execute();
+ return null;
+ }
+ };
+ }
+
+ /**
+ * Combines multiple {@code commands} into a single command. A {@link RuntimeException} thrown
+ * during the execution of one of the commands will prevent the subsequent commands from being
+ * executed.
+ *
+ * @param commands Commands to compound.
+ * @return A command whose {@link Command#execute()} will cause the given {@code commands} to be
+ * executed serially.
+ */
+ public static Command compound(Iterable<Command> commands) {
+ final ImmutableList<Command> executableCommands = ImmutableList.copyOf(commands);
+ return new Command() {
+ @Override public void execute() {
+ for (Command command : executableCommands) {
+ command.execute();
+ }
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/Either.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/Either.java b/commons/src/main/java/com/twitter/common/base/Either.java
new file mode 100644
index 0000000..9b556a3
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/Either.java
@@ -0,0 +1,345 @@
+package com.twitter.common.base;
+
+import javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+/**
+ * A value of one of two possible types.
+ *
+ * <p>Often Either processing is used as an alternative exception flow control. In these uses the
+ * left type represents failure by convention and the right type the success path result.
+ *
+ * @param <L> The left type.
+ * @param <R> The right type.
+ */
+public final class Either<L, R> {
+ private final Optional<L> left;
+ private final Optional<R> right;
+
+ private Either(Optional<L> left, Optional<R> right) {
+ this.left = left;
+ this.right = right;
+ }
+
+ /**
+ * Turns a left into a right and vice-versa.
+ *
+ * @return A new swapped either instance.
+ */
+ public Either<R, L> swap() {
+ return new Either<R, L>(right, left);
+ }
+
+ /**
+ * Returns an optional the will be {@link Optional#isPresent() present} is this is a left
+ * instance.
+ *
+ * @return An optional value for the left.
+ */
+ public Optional<L> left() {
+ return left;
+ }
+
+ /**
+ * Returns an optional the will be {@link Optional#isPresent() present} is this is a right
+ * instance.
+ *
+ * @return An optional value for the right.
+ */
+ public Optional<R> right() {
+ return right;
+ }
+
+ /**
+ * Returns {@code true} if this is a left instance.
+ *
+ * @return {@code true} if this is a left.
+ */
+ public boolean isLeft() {
+ return left().isPresent();
+ }
+
+ /**
+ * Returns {@code true} if this is a right instance.
+ *
+ * @return {@code true} if this is a right.
+ */
+ public boolean isRight() {
+ return right().isPresent();
+ }
+
+ /**
+ * Returns the underlying value if this is a left; otherwise, throws.
+ *
+ * @return The underlying value.
+ * @throws IllegalStateException if this is a right instance.
+ */
+ public L getLeft() {
+ return left().get();
+ }
+
+ /**
+ * Returns the underlying value if this is a right; otherwise, throws.
+ *
+ * @return The underlying value.
+ * @throws IllegalStateException if this is a right instance.
+ */
+ public R getRight() {
+ return right().get();
+ }
+
+ /**
+ * If this is a left, maps its value into a new left; otherwise just returns this right.
+ *
+ * @param transformer The transformation to apply to the left value.
+ * @param <M> The type a left value will be mapped to.
+ * @return The mapped left or else the right.
+ */
+ public <M> Either<M, R> mapLeft(Function<? super L, M> transformer) {
+ if (isLeft()) {
+ return left(transformer.apply(getLeft()));
+ } else {
+ @SuppressWarnings("unchecked") // I am a right so my left is never accessible
+ Either<M, R> self = (Either<M, R>) this;
+ return self;
+ }
+ }
+
+ /**
+ * If this is a right, maps its value into a new right; otherwise just returns this left.
+ *
+ * @param transformer The transformation to apply to the left value.
+ * @param <M> The type a right value will be mapped to.
+ * @return The mapped right or else the left.
+ */
+ public <M> Either<L, M> mapRight(Function<? super R, M> transformer) {
+ if (isRight()) {
+ return right(transformer.apply(getRight()));
+ } else {
+ @SuppressWarnings("unchecked") // I am a left so my right is never accessible
+ Either<L, M> self = (Either<L, M>) this;
+ return self;
+ }
+ }
+
+ /**
+ * Can transform either a left or a right into a result.
+ *
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @param <T> The transformation result type.
+ */
+ public abstract static class Transformer<L, R, T> implements Function<Either<L, R>, T> {
+
+ /**
+ * Maps left values to a result.
+ *
+ * @param left the left value to map.
+ * @return The mapped value.
+ */
+ public abstract T mapLeft(L left);
+
+ /**
+ * Maps right values to a result.
+ *
+ * @param right the right value to map.
+ * @return The mapped value.
+ */
+ public abstract T mapRight(R right);
+
+ @Override
+ public final T apply(Either<L, R> either) {
+ return either.map(this);
+ }
+ }
+
+ /**
+ * Creates a transformer from left and right transformation functions.
+ *
+ * @param leftTransformer A transformer to process left values.
+ * @param rightTransformer A transformer to process right values.
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @param <T> The transformation result type.
+ * @return A new transformer composed of left and right transformer functions.
+ */
+ public static <L, R, T> Transformer<L, R, T> transformer(
+ final Function<? super L, T> leftTransformer,
+ final Function<? super R, T> rightTransformer) {
+
+ return new Transformer<L, R, T>() {
+ @Override public T mapLeft(L item) {
+ return leftTransformer.apply(item);
+ }
+ @Override public T mapRight(R item) {
+ return rightTransformer.apply(item);
+ }
+ };
+ }
+
+ /**
+ * Transforms this either instance to a value regardless of whether it is a left or a right.
+ *
+ * @param transformer The transformer to map this either instance.
+ * @param <T> The type the transformer produces.
+ * @return A value mapped by the transformer from this left or right instance.
+ */
+ public <T> T map(final Transformer<? super L, ? super R, T> transformer) {
+ if (isLeft()) {
+ return transformer.mapLeft(getLeft());
+ } else {
+ return transformer.mapRight(getRight());
+ }
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (!(o instanceof Either)) {
+ return false;
+ }
+ Either<?, ?> other = (Either<?, ?>) o;
+ return Objects.equal(left, other.left)
+ && Objects.equal(right, other.right);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(left, right);
+ }
+
+ @Override
+ public String toString() {
+ if (isLeft()) {
+ return String.format("Left(%s)", getLeft());
+ } else {
+ return String.format("Right(%s)", getRight());
+ }
+ }
+
+ /**
+ * Creates a left either instance.
+ *
+ * @param value The left value to wrap - may not be null.
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @return A left either instance wrapping {@code value}.
+ */
+ public static <L, R> Either<L, R> left(L value) {
+ return new Either<L, R>(Optional.of(value), Optional.<R>absent());
+ }
+
+ /**
+ * Creates a right either instance.
+ *
+ * @param value The right value to wrap - may not be null.
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @return A right either instance wrapping {@code value}.
+ */
+ public static <L, R> Either<L, R> right(R value) {
+ return new Either<L, R>(Optional.<L>absent(), Optional.of(value));
+ }
+
+ /**
+ * Extracts all the lefts from a sequence of eithers lazily.
+ *
+ * @param results A sequence of either's to process.
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @return A lazy iterable that will produce the lefts present in results in order.
+ */
+ public static <L, R> Iterable<L> lefts(Iterable<Either<L, R>> results) {
+ return Optional.presentInstances(Iterables.transform(results,
+ new Function<Either<L, R>, Optional<L>>() {
+ @Override public Optional<L> apply(Either<L, R> item) {
+ return item.left();
+ }
+ }));
+ }
+
+ /**
+ * Extracts all the rights from a sequence of eithers lazily.
+ *
+ * @param results A sequence of either's to process.
+ * @param <L> The left type.
+ * @param <R> The right type.
+ * @return A lazy iterable that will produce the rights present in results in order.
+ */
+ public static <L, R> Iterable<R> rights(Iterable<Either<L, R>> results) {
+ return Optional.presentInstances(Iterables.transform(results,
+ new Function<Either<L, R>, Optional<R>>() {
+ @Override public Optional<R> apply(Either<L, R> item) {
+ return item.right();
+ }
+ }));
+ }
+
+ /**
+ * A convenience method equivalent to calling {@code guard(work, exceptionType)}.
+ */
+ public static <X extends Exception, R> Either<X, R> guard(
+ Class<X> exceptionType,
+ ExceptionalSupplier<R, X> work) {
+
+ @SuppressWarnings("unchecked")
+ Either<X, R> either = guard(work, exceptionType);
+ return either;
+ }
+
+ /**
+ * A convenience method equivalent to calling
+ * {@code guard(Lists.asList(execpetionType, rest), work)}.
+ */
+ public static <X extends Exception, R> Either<X, R> guard(
+ ExceptionalSupplier<R, X> work,
+ Class<? extends X> exceptionType,
+ Class<? extends X>... rest) {
+
+ return guard(Lists.asList(exceptionType, rest), work);
+ }
+
+ /**
+ * Thrown when guarded work throws an unguarded exception. The {@link #getCause() cause} will
+ * contain the original unguarded exception.
+ */
+ public static class UnguardedException extends RuntimeException {
+ public UnguardedException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ /**
+ * Converts work that can throw exceptions into an either with a left exception base type. This
+ * can be useful to fold an exception throwing library call into an either processing style
+ * pipeline.
+ *
+ * @param exceptionTypes The expected exception types.
+ * @param work The work to perform to get a result produce an error.
+ * @param <X> The base error type.
+ * @param <R> The success type.
+ * @return An either wrapping the result of performing {@code work}.
+ * @throws UnguardedException if work throws an unguarded exception type.
+ */
+ public static <X extends Exception, R> Either<X, R> guard(
+ Iterable<Class<? extends X>> exceptionTypes,
+ ExceptionalSupplier<R, X> work) {
+
+ try {
+ return right(work.get());
+ // We're explicitly dealing with generic exception types here by design.
+ // SUPPRESS CHECKSTYLE RegexpSinglelineJava
+ } catch (Exception e) {
+ for (Class<? extends X> exceptionType : exceptionTypes) {
+ if (exceptionType.isInstance(e)) {
+ X exception = exceptionType.cast(e);
+ return left(exception);
+ }
+ }
+ throw new UnguardedException(e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aurora/blob/86a547b9/commons/src/main/java/com/twitter/common/base/ExceptionTransporter.java
----------------------------------------------------------------------
diff --git a/commons/src/main/java/com/twitter/common/base/ExceptionTransporter.java b/commons/src/main/java/com/twitter/common/base/ExceptionTransporter.java
new file mode 100644
index 0000000..5bd540e
--- /dev/null
+++ b/commons/src/main/java/com/twitter/common/base/ExceptionTransporter.java
@@ -0,0 +1,87 @@
+// =================================================================================================
+// Copyright 2011 Twitter, Inc.
+// -------------------------------------------------------------------------------------------------
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this work except in compliance with the License.
+// You may obtain a copy of the License in the LICENSE file, or 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.twitter.common.base;
+
+import com.google.common.base.Function;
+
+/**
+ * A utility for transporting checked exceptions across boundaries that do not allow for checked
+ * exception propagation.
+ *
+ * @param <E> The type of checked exception the ExceptionTransported can transport
+ *
+ * @author John Sirois
+ */
+public class ExceptionTransporter<E extends Exception> {
+
+ /**
+ * An exception wrapper used to transport checked exceptions. Never leaves an
+ * {@link ExceptionTransporter#guard(com.google.common.base.Function)} call.
+ */
+ private static final class TransportingException extends RuntimeException {
+ private TransportingException(Exception cause) {
+ super("It is a usage error to see this message!", cause);
+ }
+ }
+
+ /**
+ * Guards a unit of work that internally can generate checked exceptions. Callers wrap up the
+ * work in a function that rethrows any checked exceptions using the supplied
+ * ExceptionTransporter. Guard will ensure the original exception is unwrapped an re-thrown.
+ *
+ * @param work The unit of work that guards its checked exceptions.
+ * @param <T> The type returned by the unit of work when it successfully completes.
+ * @param <X> The type of checked exception that the unit of work wishes to guard.
+ * @return the result of the unit of work if no excpetions are thrown
+ * @throws X when the unit of work uses the ExceptionTransporter to throw a checked exception
+ */
+ public static <T, X extends Exception> T guard(Function<ExceptionTransporter<X>, T> work)
+ throws X {
+
+ try {
+ return work.apply(new ExceptionTransporter<X>());
+ } catch (TransportingException e) {
+ @SuppressWarnings("unchecked")
+ X cause = (X) e.getCause();
+ throw cause;
+ }
+ }
+
+ /**
+ * Throws the given {@code checked} exception across a boundary that does not allow checked
+ * exceptions. Although a RuntimeException is returned by this method signature, the method never
+ * actually completes normally. The return type does allow the following usage idiom however:
+ * <pre>
+ * public String apply(ExceptionTransporter transporter) {
+ * try {
+ * return doChecked();
+ * } catch (CheckedException e) {
+ * // Although transport internally throws and does not return, we satisfy the compiler that
+ * // our method returns a value or throws by pretending to throw the RuntimeException that
+ * // never actually gets returned by transporter.transport(...)
+ * throw transporter.transport(e);
+ * }
+ * }
+ * </pre>
+ *
+ * @param checked The checked exception to transport.
+ * @return A RuntimeException that can be thrown to satisfy the compiler at the call site
+ */
+ public RuntimeException transport(E checked) {
+ throw new TransportingException(checked);
+ }
+}