You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ha...@apache.org on 2015/08/18 17:03:28 UTC
[19/64] [abbrv] incubator-brooklyn git commit: BROOKLYN-162 - apply
org.apache package prefix to utils-common
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/time/Duration.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/time/Duration.java b/utils/common/src/main/java/brooklyn/util/time/Duration.java
deleted file mode 100644
index 3107bf4..0000000
--- a/utils/common/src/main/java/brooklyn/util/time/Duration.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 brooklyn.util.time;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nullable;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-
-/** simple class determines a length of time */
-public class Duration implements Comparable<Duration>, Serializable {
-
- private static final long serialVersionUID = -2303909964519279617L;
-
- public static final Duration ZERO = of(0, null);
- public static final Duration ONE_MILLISECOND = of(1, TimeUnit.MILLISECONDS);
- public static final Duration ONE_SECOND = of(1, TimeUnit.SECONDS);
- public static final Duration FIVE_SECONDS = of(5, TimeUnit.SECONDS);
- public static final Duration TEN_SECONDS = of(10, TimeUnit.SECONDS);
- public static final Duration THIRTY_SECONDS = of(30, TimeUnit.SECONDS);
- public static final Duration ONE_MINUTE = of(1, TimeUnit.MINUTES);
- public static final Duration TWO_MINUTES = of(2, TimeUnit.MINUTES);
- public static final Duration FIVE_MINUTES = of(5, TimeUnit.MINUTES);
- public static final Duration ONE_HOUR = of(1, TimeUnit.HOURS);
- public static final Duration ONE_DAY = of(1, TimeUnit.DAYS);
-
- /** longest supported duration, 2^{63}-1 nanoseconds, approx ten billion seconds, or 300 years */
- public static final Duration PRACTICALLY_FOREVER = of(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
-
- private final long nanos;
-
- public Duration(long value, TimeUnit unit) {
- if (value != 0) {
- Preconditions.checkNotNull(unit, "Cannot accept null timeunit (unless value is 0)");
- } else {
- unit = TimeUnit.MILLISECONDS;
- }
- nanos = TimeUnit.NANOSECONDS.convert(value, unit);
- }
-
- @Override
- public int compareTo(Duration o) {
- return ((Long)toNanoseconds()).compareTo(o.toNanoseconds());
- }
-
- @Override
- public String toString() {
- return Time.makeTimeStringExact(this);
- }
-
- public String toStringRounded() {
- return Time.makeTimeStringRounded(this);
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof Duration)) return false;
- return toMilliseconds() == ((Duration)o).toMilliseconds();
- }
-
- @Override
- public int hashCode() {
- return Long.valueOf(toMilliseconds()).hashCode();
- }
-
- /** converts to the given {@link TimeUnit}, using {@link TimeUnit#convert(long, TimeUnit)} which rounds _down_
- * (so 1 nanosecond converted to milliseconds gives 0 milliseconds, and -1 ns gives -1 ms) */
- public long toUnit(TimeUnit unit) {
- return unit.convert(nanos, TimeUnit.NANOSECONDS);
- }
-
- /** as {@link #toUnit(TimeUnit)} but rounding as indicated
- * (rather than always taking the floor which is TimeUnit's default behaviour) */
- public long toUnit(TimeUnit unit, RoundingMode rounding) {
- long result = unit.convert(nanos, TimeUnit.NANOSECONDS);
- long check = TimeUnit.NANOSECONDS.convert(result, unit);
- if (check==nanos || rounding==null || rounding==RoundingMode.UNNECESSARY) return result;
- return new BigDecimal(nanos).divide(new BigDecimal(unit.toNanos(1)), rounding).longValue();
- }
-
- /** as {@link #toUnit(TimeUnit)} but rounding away from zero,
- * so 1 ns converted to ms gives 1 ms, and -1 ns gives 1ms */
- public long toUnitRoundingUp(TimeUnit unit) {
- return toUnit(unit, RoundingMode.UP);
- }
-
- public long toMilliseconds() {
- return toUnit(TimeUnit.MILLISECONDS);
- }
-
- /** as {@link #toMilliseconds()} but rounding away from zero (so 1 nanosecond gets rounded to 1 millisecond);
- * see {@link #toUnitRoundingUp(TimeUnit)}; provided as a convenience on top of {@link #toUnit(TimeUnit, RoundingMode)}
- * as this is a common case (when you want to make sure you wait at least a certain amount of time) */
- public long toMillisecondsRoundingUp() {
- return toUnitRoundingUp(TimeUnit.MILLISECONDS);
- }
-
- public long toNanoseconds() {
- return nanos;
- }
-
- public long toSeconds() {
- return toUnit(TimeUnit.SECONDS);
- }
-
- /** number of nanoseconds of this duration */
- public long nanos() {
- return nanos;
- }
-
- /**
- * See {@link Time#parseElapsedTime(String)};
- * also accepts "forever" (and for those who prefer things exceedingly accurate, "practically_forever").
- * Also see {@link #of(Object)}. */
- public static Duration parse(String textualDescription) {
- if (textualDescription==null) return null;
- if ("null".equalsIgnoreCase(textualDescription)) return null;
-
- if ("forever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
- if ("practicallyforever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
- if ("practically_forever".equalsIgnoreCase(textualDescription)) return Duration.PRACTICALLY_FOREVER;
-
- return new Duration((long) Time.parseElapsedTimeAsDouble(textualDescription), TimeUnit.MILLISECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration days(Number n) {
- return new Duration((long) (n.doubleValue() * TimeUnit.DAYS.toNanos(1)), TimeUnit.NANOSECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration hours(Number n) {
- return new Duration((long) (n.doubleValue() * TimeUnit.HOURS.toNanos(1)), TimeUnit.NANOSECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration minutes(Number n) {
- return new Duration((long) (n.doubleValue() * TimeUnit.MINUTES.toNanos(1)), TimeUnit.NANOSECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration seconds(Number n) {
- return new Duration((long) (n.doubleValue() * TimeUnit.SECONDS.toNanos(1)), TimeUnit.NANOSECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration millis(Number n) {
- return new Duration((long) (n.doubleValue() * TimeUnit.MILLISECONDS.toNanos(1)), TimeUnit.NANOSECONDS);
- }
-
- /** creates new {@link Duration} instance of the given length of time */
- public static Duration nanos(Number n) {
- return new Duration(n.longValue(), TimeUnit.NANOSECONDS);
- }
-
- public static Function<Number, String> millisToStringRounded() { return millisToStringRounded; }
- private static Function<Number, String> millisToStringRounded = new Function<Number, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Number input) {
- if (input == null) return null;
- return Duration.millis(input).toStringRounded();
- }
- };
-
- public static Function<Number, String> secondsToStringRounded() { return secondsToStringRounded; }
- private static Function<Number, String> secondsToStringRounded = new Function<Number, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Number input) {
- if (input == null) return null;
- return Duration.seconds(input).toStringRounded();
- }
- };
-
- /** tries to convert given object to a Duration, parsing strings, treating numbers as millis, etc;
- * throws IAE if not convertible */
- public static Duration of(Object o) {
- if (o == null) return null;
- if (o instanceof Duration) return (Duration)o;
- if (o instanceof String) return parse((String)o);
- if (o instanceof Number) return millis((Number)o);
- if (o instanceof Stopwatch) return millis(((Stopwatch)o).elapsed(TimeUnit.MILLISECONDS));
-
- try {
- // this allows it to work with groovy TimeDuration
- Method millisMethod = o.getClass().getMethod("toMilliseconds");
- return millis((Long)millisMethod.invoke(o));
- } catch (Exception e) {
- // probably no such method
- }
-
- throw new IllegalArgumentException("Cannot convert "+o+" (type "+o.getClass()+") to a duration");
- }
-
- public static Duration of(long value, TimeUnit unit) {
- return new Duration(value, unit);
- }
-
- public static Duration max(Duration first, Duration second) {
- return checkNotNull(first, "first").nanos >= checkNotNull(second, "second").nanos ? first : second;
- }
-
- public static Duration min(Duration first, Duration second) {
- return checkNotNull(first, "first").nanos <= checkNotNull(second, "second").nanos ? first : second;
- }
-
- public static Duration untilUtc(long millisSinceEpoch) {
- return millis(millisSinceEpoch - System.currentTimeMillis());
- }
-
- public static Duration sinceUtc(long millisSinceEpoch) {
- return millis(System.currentTimeMillis() - millisSinceEpoch);
- }
-
- public Duration add(Duration other) {
- return nanos(nanos() + other.nanos());
- }
-
- public Duration subtract(Duration other) {
- return nanos(nanos() - other.nanos());
- }
-
- public Duration multiply(long x) {
- return nanos(nanos() * x);
- }
- public Duration times(long x) {
- return multiply(x);
- }
-
- /** as #multiply(long), but approximate due to the division (nano precision) */
- public Duration multiply(double d) {
- return nanos(nanos() * d);
- }
-
- public Duration half() {
- return multiply(0.5);
- }
-
- /** see {@link Time#sleep(long)} */
- public static void sleep(Duration duration) {
- Time.sleep(duration);
- }
-
- /** returns a new started {@link CountdownTimer} with this duration */
- public CountdownTimer countdownTimer() {
- return CountdownTimer.newInstanceStarted(this);
- }
-
- public boolean isPositive() {
- return nanos()>0;
- }
-
- public boolean isLongerThan(Duration x) {
- return compareTo(x) > 0;
- }
-
- public boolean isLongerThan(Stopwatch stopwatch) {
- return isLongerThan(Duration.millis(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
- }
-
- public boolean isShorterThan(Duration x) {
- return compareTo(x) < 0;
- }
-
- public boolean isShorterThan(Stopwatch stopwatch) {
- return isShorterThan(Duration.millis(stopwatch.elapsed(TimeUnit.MILLISECONDS)));
- }
-
- /** returns the larger of this value or the argument */
- public Duration lowerBound(Duration alternateMinimumValue) {
- if (isShorterThan(alternateMinimumValue)) return alternateMinimumValue;
- return this;
- }
-
- /** returns the smaller of this value or the argument */
- public Duration upperBound(Duration alternateMaximumValue) {
- if (isLongerThan(alternateMaximumValue)) return alternateMaximumValue;
- return this;
- }
-
- /** @deprecated since 0.7.0 use {@link #lowerBound(Duration)} */ @Deprecated
- public Duration minimum(Duration alternateMinimumValue) {
- return lowerBound(alternateMinimumValue);
- }
-
- /** @deprecated since 0.7.0 use {@link #upperBound(Duration)} */ @Deprecated
- /** returns the smaller of this value or the argument */
- public Duration maximum(Duration alternateMaximumValue) {
- return upperBound(alternateMaximumValue);
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/time/Durations.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/time/Durations.java b/utils/common/src/main/java/brooklyn/util/time/Durations.java
deleted file mode 100644
index 21450a6..0000000
--- a/utils/common/src/main/java/brooklyn/util/time/Durations.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 brooklyn.util.time;
-
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-
-public class Durations {
-
- public static boolean await(CountDownLatch latch, Duration time) throws InterruptedException {
- return latch.await(time.toNanoseconds(), TimeUnit.NANOSECONDS);
- }
-
- public static void join(Thread thread, Duration time) throws InterruptedException {
- thread.join(time.toMillisecondsRoundingUp());
- }
-
- public static <T> Maybe<T> get(Future<T> t, Duration timeout) {
- try {
- if (timeout==null || timeout.toMilliseconds()<0 || Duration.PRACTICALLY_FOREVER.equals(timeout))
- return Maybe.of(t.get());
- if (timeout.toMilliseconds()==0 && !t.isDone()) {
- for (int i=0; i<10; i++) {
- // give it 10 nanoseconds to complete - heuristically this is often enough
- // (Thread.yield should do it, but often seems to have no effect, e.g. on Mac)
- Thread.yield();
- Thread.sleep(0, 1);
- }
- return Maybe.absent("Task "+t+" not completed when immediate completion requested");
- }
- return Maybe.of(t.get(timeout.toMilliseconds(), TimeUnit.MILLISECONDS));
- } catch (TimeoutException e) {
- return Maybe.absent("Task "+t+" did not complete within "+timeout);
- } catch (CancellationException e) {
- return Maybe.absent("Task "+t+" was cancelled");
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
-
- public static <T> Maybe<T> get(Future<T> t, CountdownTimer timer) {
- if (timer==null) return get(t, (Duration)null);
- Duration remaining = timer.getDurationRemaining();
- if (remaining.isPositive()) return get(t, remaining);
- return get(t, Duration.ZERO);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/time/Time.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/time/Time.java b/utils/common/src/main/java/brooklyn/util/time/Time.java
deleted file mode 100644
index 3379d49..0000000
--- a/utils/common/src/main/java/brooklyn/util/time/Time.java
+++ /dev/null
@@ -1,962 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 brooklyn.util.time;
-
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.ParsePosition;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-import java.util.SimpleTimeZone;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.guava.Maybe;
-import brooklyn.util.text.Strings;
-
-import com.google.common.base.Function;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Stopwatch;
-
-public class Time {
-
- private static final Logger log = LoggerFactory.getLogger(Time.class);
-
- public static final String DATE_FORMAT_PREFERRED_W_TZ = "yyyy-MM-dd HH:mm:ss.SSS Z";
- public static final String DATE_FORMAT_PREFERRED = "yyyy-MM-dd HH:mm:ss.SSS";
- public static final String DATE_FORMAT_STAMP = "yyyyMMdd-HHmmssSSS";
- public static final String DATE_FORMAT_SIMPLE_STAMP = "yyyy-MM-dd-HHmm";
- public static final String DATE_FORMAT_OF_DATE_TOSTRING = "EEE MMM dd HH:mm:ss zzz yyyy";
- public static final String DATE_FORMAT_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
- public static final String DATE_FORMAT_ISO8601_NO_MILLIS = "yyyy-MM-dd'T'HH:mm:ssZ";
-
- public static final long MILLIS_IN_SECOND = 1000;
- public static final long MILLIS_IN_MINUTE = 60*MILLIS_IN_SECOND;
- public static final long MILLIS_IN_HOUR = 60*MILLIS_IN_MINUTE;
- public static final long MILLIS_IN_DAY = 24*MILLIS_IN_HOUR;
- public static final long MILLIS_IN_YEAR = 365*MILLIS_IN_DAY;
-
- /** GMT/UTC/Z time zone constant */
- public static final TimeZone TIME_ZONE_UTC = TimeZone.getTimeZone("");
-
- /** as {@link #makeDateString(Date)} for current date/time */
- public static String makeDateString() {
- return makeDateString(System.currentTimeMillis());
- }
-
- /** as {@link #makeDateString(Date)} for long millis since UTC epock */
- public static String makeDateString(long date) {
- return makeDateString(new Date(date), DATE_FORMAT_PREFERRED);
- }
- /** returns the time in {@value #DATE_FORMAT_PREFERRED} format for the given date;
- * this format is numeric big-endian but otherwise optimized for people to read, with spaces and colons and dots;
- * time is local to the server and time zone is <i>not</i> included */
- public static String makeDateString(Date date) {
- return makeDateString(date, DATE_FORMAT_PREFERRED);
- }
- /** as {@link #makeDateString(Date, String, TimeZone)} for the local time zone */
- public static String makeDateString(Date date, String format) {
- return makeDateString(date, format, null);
- }
- /** as {@link #makeDateString(Date, String, TimeZone)} for the given time zone; consider {@link TimeZone#GMT} */
- public static String makeDateString(Date date, String format, TimeZone tz) {
- SimpleDateFormat fmt = new SimpleDateFormat(format);
- if (tz!=null) fmt.setTimeZone(tz);
- return fmt.format(date);
- }
- /** as {@link #makeDateString(Date, String)} using {@link #DATE_FORMAT_PREFERRED_W_TZ} */
- public static String makeDateString(Calendar date) {
- return makeDateString(date.getTime(), DATE_FORMAT_PREFERRED_W_TZ);
- }
- /** as {@link #makeDateString(Date, String, TimeZone)} for the time zone of the given calendar object */
- public static String makeDateString(Calendar date, String format) {
- return makeDateString(date.getTime(), format, date.getTimeZone());
- }
-
- public static Function<Long, String> toDateString() { return dateString; }
- private static Function<Long, String> dateString = new Function<Long, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeDateString(input);
- }
- };
-
- /** returns the current time in {@value #DATE_FORMAT_STAMP} format,
- * suitable for machines to read with only numbers and dashes and quite precise (ms) */
- public static String makeDateStampString() {
- return makeDateStampString(System.currentTimeMillis());
- }
-
- /** returns the time in {@value #DATE_FORMAT_STAMP} format, given a long (e.g. returned by System.currentTimeMillis);
- * cf {@link #makeDateStampString()} */
- public static String makeDateStampString(long date) {
- return new SimpleDateFormat(DATE_FORMAT_STAMP).format(new Date(date));
- }
-
- /** returns the current time in {@value #DATE_FORMAT_SIMPLE_STAMP} format,
- * suitable for machines to read but easier for humans too,
- * like {@link #makeDateStampString()} but not as precise */
- public static String makeDateSimpleStampString() {
- return makeDateSimpleStampString(System.currentTimeMillis());
- }
-
- /** returns the time in {@value #DATE_FORMAT_SIMPLE_STAMP} format, given a long (e.g. returned by System.currentTimeMillis);
- * cf {@link #makeDateSimpleStampString()} */
- public static String makeDateSimpleStampString(long date) {
- return new SimpleDateFormat(DATE_FORMAT_SIMPLE_STAMP).format(new Date(date));
- }
-
- public static Function<Long, String> toDateStampString() { return dateStampString; }
- private static Function<Long, String> dateStampString = new Function<Long, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeDateStampString(input);
- }
- };
-
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringExact(long t, TimeUnit unit) {
- long nanos = unit.toNanos(t);
- return makeTimeStringNanoExact(nanos);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringRounded(long t, TimeUnit unit) {
- long nanos = unit.toNanos(t);
- return makeTimeStringNanoRounded(nanos);
- }
- public static String makeTimeStringRounded(Stopwatch timer) {
- return makeTimeStringRounded(timer.elapsed(TimeUnit.MILLISECONDS), TimeUnit.MILLISECONDS);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringExact(long t) {
- return makeTimeString(t, false);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringRounded(long t) {
- return makeTimeString(t, true);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringRoundedSince(long utc) {
- return makeTimeString(System.currentTimeMillis() - utc, true);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringExact(Duration d) {
- return makeTimeStringNanoExact(d.toNanoseconds());
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringRounded(Duration d) {
- return makeTimeStringNanoRounded(d.toNanoseconds());
- }
- /** given an elapsed time, makes it readable, eg 44d 6h, or 8s 923ms, optionally rounding */
- public static String makeTimeString(long t, boolean round) {
- return makeTimeStringNano(t*1000000L, round);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringNanoExact(long tn) {
- return makeTimeStringNano(tn, false);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringNanoRounded(long tn) {
- return makeTimeStringNano(tn, true);
- }
- /** @see #makeTimeString(long, boolean) */
- public static String makeTimeStringNano(long tn, boolean round) {
- if (tn<0) return "-"+makeTimeStringNano(-tn, round);
- // units don't matter, but since ms is the usual finest granularity let's use it
- // (previously was just "0" but that was too ambiguous in contexts like "took 0")
- if (tn==0) return "0ms";
-
- long tnm = tn % 1000000;
- long t = tn/1000000;
- String result = "";
-
- long d = t/MILLIS_IN_DAY; t %= MILLIS_IN_DAY;
- long h = t/MILLIS_IN_HOUR; t %= MILLIS_IN_HOUR;
- long m = t/MILLIS_IN_MINUTE; t %= MILLIS_IN_MINUTE;
- long s = t/MILLIS_IN_SECOND; t %= MILLIS_IN_SECOND;
- long ms = t;
-
- int segments = 0;
- if (d>0) { result += d+"d "; segments++; }
- if (h>0) { result += h+"h "; segments++; }
- if (round && segments>=2) return Strings.removeAllFromEnd(result, " ");
- if (m>0) { result += m+"m "; segments++; }
- if (round && (segments>=2 || d>0)) return Strings.removeAllFromEnd(result, " ");
- if (s>0) {
- if (ms==0 && tnm==0) {
- result += s+"s"; segments++;
- return result;
- }
- if (round && segments>0) {
- result += s+"s"; segments++;
- return result;
- }
- if (round && s>10) {
- result += toDecimal(s, ms/1000.0, 1)+"s"; segments++;
- return result;
- }
- if (round) {
- result += toDecimal(s, ms/1000.0, 2)+"s"; segments++;
- return result;
- }
- result += s+"s ";
- }
- if (round && segments>0)
- return Strings.removeAllFromEnd(result, " ");
- if (ms>0) {
- if (tnm==0) {
- result += ms+"ms"; segments++;
- return result;
- }
- if (round && ms>=100) {
- result += toDecimal(ms, tnm/1000000.0, 1)+"ms"; segments++;
- return result;
- }
- if (round && ms>=10) {
- result += toDecimal(ms, tnm/1000000.0, 2)+"ms"; segments++;
- return result;
- }
- if (round) {
- result += toDecimal(ms, tnm/1000000.0, 3)+"ms"; segments++;
- return result;
- }
- result += ms+"ms ";
- }
-
- long us = tnm/1000;
- long ns = tnm % 1000;
-
- if (us>0) {
- if (ns==0) {
- result += us+"us"; segments++;
- return result;
- }
- if (round && us>=100) {
- result += toDecimal(us, ns/1000.0, 1)+"us"; segments++;
- return result;
- }
- if (round && us>=10) {
- result += toDecimal(us, ns/1000.0, 2)+"us"; segments++;
- return result;
- }
- if (round) {
- result += toDecimal(us, ns/1000.0, 3)+"us"; segments++;
- return result;
- }
- result += us+"us ";
- }
-
- if (ns>0) result += ns+"ns";
- return Strings.removeAllFromEnd(result, " ");
- }
-
- public static Function<Long, String> fromLongToTimeStringExact() { return LONG_TO_TIME_STRING_EXACT; }
- private static final Function<Long, String> LONG_TO_TIME_STRING_EXACT = new FunctionLongToTimeStringExact();
- private static final class FunctionLongToTimeStringExact implements Function<Long, String> {
- @Override @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeTimeStringExact(input);
- }
- }
-
- /** @deprecated since 0.7.0 use {@link #fromLongToTimeStringExact()} */ @Deprecated
- public static Function<Long, String> toTimeString() { return timeString; }
- @Deprecated
- private static Function<Long, String> timeString = new Function<Long, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeTimeStringExact(input);
- }
- };
-
- public static Function<Long, String> fromLongToTimeStringRounded() { return LONG_TO_TIME_STRING_ROUNDED; }
- private static final Function<Long, String> LONG_TO_TIME_STRING_ROUNDED = new FunctionLongToTimeStringRounded();
- private static final class FunctionLongToTimeStringRounded implements Function<Long, String> {
- @Override @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeTimeStringRounded(input);
- }
- }
-
- /** @deprecated since 0.7.0 use {@link #fromLongToTimeStringRounded()} */ @Deprecated
- public static Function<Long, String> toTimeStringRounded() { return timeStringRounded; }
- @Deprecated
- private static Function<Long, String> timeStringRounded = new Function<Long, String>() {
- @Override
- @Nullable
- public String apply(@Nullable Long input) {
- if (input == null) return null;
- return Time.makeTimeStringRounded(input);
- }
- };
-
- public static Function<Duration, String> fromDurationToTimeStringRounded() { return DURATION_TO_TIME_STRING_ROUNDED; }
- private static final Function<Duration, String> DURATION_TO_TIME_STRING_ROUNDED = new FunctionDurationToTimeStringRounded();
- private static final class FunctionDurationToTimeStringRounded implements Function<Duration, String> {
- @Override @Nullable
- public String apply(@Nullable Duration input) {
- if (input == null) return null;
- return Time.makeTimeStringRounded(input);
- }
- }
-
- private static String toDecimal(long intPart, double fracPart, int decimalPrecision) {
- long powTen = 1;
- for (int i=0; i<decimalPrecision; i++) powTen *= 10;
- long fpr = Math.round(fracPart * powTen);
- if (fpr==powTen) {
- intPart++;
- fpr = 0;
- }
- return intPart + "." + Strings.makePaddedString(""+fpr, decimalPrecision, "0", "");
- }
-
- /** sleep which propagates Interrupted as unchecked */
- public static void sleep(long millis) {
- try {
- if (millis > 0) Thread.sleep(millis);
- } catch (InterruptedException e) {
- throw Exceptions.propagate(e);
- }
- }
-
- /** as {@link #sleep(long)} */
- public static void sleep(Duration duration) {
- Time.sleep(duration.toMillisecondsRoundingUp());
- }
-
- /**
- * Calculates the number of milliseconds past midnight for a given UTC time.
- */
- public static long getTimeOfDayFromUtc(long timeUtc) {
- GregorianCalendar gregorianCalendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
- gregorianCalendar.setTimeInMillis(timeUtc);
- int hour = gregorianCalendar.get(Calendar.HOUR_OF_DAY);
- int min = gregorianCalendar.get(Calendar.MINUTE);
- int sec = gregorianCalendar.get(Calendar.SECOND);
- int millis = gregorianCalendar.get(Calendar.MILLISECOND);
- return (((((hour * 60) + min) * 60) + sec) * 1000) + millis;
- }
-
- /**
- * Calculates the number of milliseconds past epoch for a given UTC time.
- */
- public static long getTimeUtc(TimeZone zone, int year, int month, int date, int hourOfDay, int minute, int second, int millis) {
- GregorianCalendar time = new GregorianCalendar(zone);
- time.set(year, month, date, hourOfDay, minute, second);
- time.set(Calendar.MILLISECOND, millis);
- return time.getTimeInMillis();
- }
-
- public static long roundFromMillis(long millis, TimeUnit units) {
- if (units.compareTo(TimeUnit.MILLISECONDS) > 0) {
- double result = ((double)millis) / units.toMillis(1);
- return Math.round(result);
- } else {
- return units.convert(millis, TimeUnit.MILLISECONDS);
- }
- }
-
- public static long roundFromMillis(long millis, long millisPerUnit) {
- double result = ((double)millis) / millisPerUnit;
- return Math.round(result);
- }
-
- /**
- * Calculates how long until maxTime has passed since the given startTime.
- * However, maxTime==0 is a special case (e.g. could mean wait forever), so the result is guaranteed
- * to be only 0 if maxTime was 0; otherwise -1 will be returned.
- */
- public static long timeRemaining(long startTime, long maxTime) {
- if (maxTime == 0) {
- return 0;
- }
- long result = (startTime+maxTime) - System.currentTimeMillis();
- return (result == 0) ? -1 : result;
- }
-
- /** Convenience for {@link Duration#parse(String)}. */
- public static Duration parseDuration(String timeString) {
- return Duration.parse(timeString);
- }
-
- /**
- * As {@link #parseElapsedTimeAsDouble(String)}. Consider using {@link #parseDuration(String)} for a more usable return type.
- *
- * @throws NumberFormatException if cannot be parsed (or if null)
- */
- public static long parseElapsedTime(String timeString) {
- return (long) parseElapsedTimeAsDouble(timeString);
- }
- /** @deprecated since 0.7.0 see {@link #parseElapsedTime(String)} */ @Deprecated
- public static long parseTimeString(String timeString) {
- return (long) parseElapsedTime(timeString);
- }
- /** @deprecated since 0.7.0 see {@link #parseElapsedTimeAsDouble(String)} */ @Deprecated
- public static double parseTimeStringAsDouble(String timeString) {
- return parseElapsedTimeAsDouble(timeString);
- }
-
- /**
- * Parses a string eg '5s' or '20m 22.123ms', returning the number of milliseconds it represents;
- * -1 on blank or never or off or false.
- * Assumes unit is millisections if no unit is specified.
- *
- * @throws NumberFormatException if cannot be parsed (or if null)
- */
- public static double parseElapsedTimeAsDouble(String timeString) {
- if (timeString==null)
- throw new NumberFormatException("GeneralHelper.parseTimeString cannot parse a null string");
- try {
- double d = Double.parseDouble(timeString);
- return d;
- } catch (NumberFormatException e) {
- //look for a type marker
- timeString = timeString.trim();
- String s = Strings.getLastWord(timeString).toLowerCase();
- timeString = timeString.substring(0, timeString.length()-s.length()).trim();
- int i=0;
- while (s.length()>i) {
- char c = s.charAt(i);
- if (c=='.' || Character.isDigit(c)) i++;
- else break;
- }
- String num = s.substring(0, i);
- if (i==0) {
- num = Strings.getLastWord(timeString).toLowerCase();
- timeString = timeString.substring(0, timeString.length()-num.length()).trim();
- } else {
- s = s.substring(i);
- }
- long multiplier = 0;
- if (num.length()==0) {
- //must be never or something
- if (s.equalsIgnoreCase("never") || s.equalsIgnoreCase("off") || s.equalsIgnoreCase("false"))
- return -1;
- throw new NumberFormatException("unrecognised word '"+s+"' in time string");
- }
- if (s.equalsIgnoreCase("ms") || s.equalsIgnoreCase("milli") || s.equalsIgnoreCase("millis")
- || s.equalsIgnoreCase("millisec") || s.equalsIgnoreCase("millisecs")
- || s.equalsIgnoreCase("millisecond") || s.equalsIgnoreCase("milliseconds"))
- multiplier = 1;
- else if (s.equalsIgnoreCase("s") || s.equalsIgnoreCase("sec") || s.equalsIgnoreCase("secs")
- || s.equalsIgnoreCase("second") || s.equalsIgnoreCase("seconds"))
- multiplier = 1000;
- else if (s.equalsIgnoreCase("m") || s.equalsIgnoreCase("min") || s.equalsIgnoreCase("mins")
- || s.equalsIgnoreCase("minute") || s.equalsIgnoreCase("minutes"))
- multiplier = 60*1000;
- else if (s.equalsIgnoreCase("h") || s.equalsIgnoreCase("hr") || s.equalsIgnoreCase("hrs")
- || s.equalsIgnoreCase("hour") || s.equalsIgnoreCase("hours"))
- multiplier = 60*60*1000;
- else if (s.equalsIgnoreCase("d") || s.equalsIgnoreCase("day") || s.equalsIgnoreCase("days"))
- multiplier = 24*60*60*1000;
- else
- throw new NumberFormatException("unknown unit '"+s+"' in time string");
- double d = Double.parseDouble(num);
- double dd = 0;
- if (timeString.length()>0) {
- dd = parseElapsedTimeAsDouble(timeString);
- if (dd==-1) {
- throw new NumberFormatException("cannot combine '"+timeString+"' with '"+num+" "+s+"'");
- }
- }
- return d*multiplier + dd;
- }
- }
-
- public static Calendar newCalendarFromMillisSinceEpochUtc(long timestamp) {
- GregorianCalendar cal = new GregorianCalendar();
- cal.setTimeInMillis(timestamp);
- return cal;
- }
-
- public static Calendar newCalendarFromDate(Date date) {
- return newCalendarFromMillisSinceEpochUtc(date.getTime());
- }
-
- /** As {@link #parseCalendar(String)} but returning a {@link Date},
- * (i.e. a record where the time zone has been applied and forgotten). */
- public static Date parseDate(String input) {
- if (input==null) return null;
- return parseCalendarMaybe(input).get().getTime();
- }
-
- /** Parses dates from string, accepting many formats including ISO-8601 and http://yaml.org/type/timestamp.html,
- * e.g. 2015-06-15 16:00:00 +0000.
- * <p>
- * Millis since epoch (1970) is also supported to represent the epoch (0) or dates in this millenium,
- * but to prevent ambiguity of e.g. "20150615", any other dates prior to the year 2001 are not accepted.
- * (However if a type Long is supplied, e.g. from a YAML parse, it will always be treated as millis since epoch.)
- * <p>
- * Other formats including locale-specific variants, e.g. recognising month names,
- * are supported but this may vary from platform to platform and may change between versions. */
- public static Calendar parseCalendar(String input) {
- if (input==null) return null;
- return parseCalendarMaybe(input).get();
- }
-
- /** as {@link #parseCalendar(String)} but returning a {@link Maybe} rather than throwing or returning null */
- public static Maybe<Calendar> parseCalendarMaybe(String input) {
- if (input==null) return Maybe.absent("value is null");
- input = input.trim();
- Maybe<Calendar> result;
-
- result = parseCalendarUtc(input);
- if (result.isPresent()) return result;
-
- result = parseCalendarSimpleFlexibleFormatParser(input);
- if (result.isPresent()) return result;
- // return the error from this method
- Maybe<Calendar> returnResult = result;
-
- result = parseCalendarFormat(input, new SimpleDateFormat(DATE_FORMAT_OF_DATE_TOSTRING, Locale.ROOT));
- if (result.isPresent()) return result;
- result = parseCalendarDefaultParse(input);
- if (result.isPresent()) return result;
-
- return returnResult;
- }
-
- @SuppressWarnings("deprecation")
- private static Maybe<Calendar> parseCalendarDefaultParse(String input) {
- try {
- long ms = Date.parse(input);
- if (ms>=new Date(1999, 12, 25).getTime() && ms <= new Date(2200, 1, 2).getTime()) {
- // accept default date parse for this century and next
- GregorianCalendar c = new GregorianCalendar();
- c.setTimeInMillis(ms);
- return Maybe.of((Calendar)c);
- }
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- }
- return Maybe.absent();
- }
-
- private static Maybe<Calendar> parseCalendarUtc(String input) {
- input = input.trim();
- if (input.matches("\\d+")) {
- if ("0".equals(input)) {
- // accept 0 as epoch UTC
- return Maybe.of(newCalendarFromMillisSinceEpochUtc(0));
- }
- Maybe<Calendar> result = Maybe.of(newCalendarFromMillisSinceEpochUtc(Long.parseLong(input)));
- if (result.isPresent()) {
- int year = result.get().get(Calendar.YEAR);
- if (year >= 2000 && year < 2200) {
- // only applicable for dates in this century
- return result;
- } else {
- return Maybe.absent("long is probably not millis since epoch UTC; millis as string is not in acceptable range");
- }
- }
- }
- return Maybe.absent("not long millis since epoch UTC");
- }
-
- private final static String DIGIT = "\\d";
- private final static String LETTER = "\\p{L}";
- private final static String COMMON_SEPARATORS = "-\\.";
- private final static String TIME_SEPARATOR = COMMON_SEPARATORS+":";
- private final static String DATE_SEPARATOR = COMMON_SEPARATORS+"/ ";
- private final static String DATE_TIME_ANY_ORDER_GROUP_SEPARATOR = COMMON_SEPARATORS+":/ ";
-
- private final static String DATE_ONLY_WITH_INNER_SEPARATORS =
- namedGroup("year", DIGIT+DIGIT+DIGIT+DIGIT) +
- anyChar(DATE_SEPARATOR) +
- namedGroup("month", options(optionally(DIGIT)+DIGIT, anyChar(LETTER)+"+")) +
- anyChar(DATE_SEPARATOR) +
- namedGroup("day", optionally(DIGIT)+DIGIT);
- private final static String DATE_WORDS_2 =
- namedGroup("month", anyChar(LETTER)+"+") +
- anyChar(DATE_SEPARATOR) +
- namedGroup("day", optionally(DIGIT)+DIGIT) +
- ",?"+anyChar(DATE_SEPARATOR)+"+" +
- namedGroup("year", DIGIT+DIGIT+DIGIT+DIGIT);
- // we could parse NN-NN-NNNN as DD-MM-YYYY always, but could be confusing for MM-DD-YYYY oriented people, so require month named
- private final static String DATE_WORDS_3 =
- namedGroup("day", optionally(DIGIT)+DIGIT) +
- anyChar(DATE_SEPARATOR) +
- namedGroup("month", anyChar(LETTER)+"+") +
- ",?"+anyChar(DATE_SEPARATOR)+"+" +
- namedGroup("year", DIGIT+DIGIT+DIGIT+DIGIT);
-
- private final static String DATE_ONLY_NO_SEPARATORS =
- namedGroup("year", DIGIT+DIGIT+DIGIT+DIGIT) +
- namedGroup("month", DIGIT+DIGIT) +
- namedGroup("day", DIGIT+DIGIT);
-
- private final static String MERIDIAN = anyChar("aApP")+optionally(anyChar("mM"));
- private final static String TIME_ONLY_WITH_INNER_SEPARATORS =
- namedGroup("hours", optionally(DIGIT)+DIGIT)+
- optionally(
- anyChar(TIME_SEPARATOR)+
- namedGroup("mins", DIGIT+DIGIT)+
- optionally(
- anyChar(TIME_SEPARATOR)+
- namedGroup("secs", DIGIT+DIGIT+optionally( optionally("\\.")+DIGIT+"+"))))+
- optionally(" *" + namedGroup("meridian", notMatching(LETTER+LETTER+LETTER)+MERIDIAN));
- private final static String TIME_ONLY_NO_SEPARATORS =
- namedGroup("hours", DIGIT+DIGIT)+
- namedGroup("mins", DIGIT+DIGIT)+
- optionally(
- namedGroup("secs", DIGIT+DIGIT+optionally( optionally("\\.")+DIGIT+"+")))+
- namedGroup("meridian", "");
-
- private final static String TZ_CODE =
- namedGroup("tzCode",
- notMatching(MERIDIAN+options("$", anyChar("^"+LETTER))) + // not AM or PM
- anyChar(LETTER)+"+"+anyChar(LETTER+DIGIT+"\\/\\-\\' _")+"*");
- private final static String TIME_ZONE_SIGNED_OFFSET =
- namedGroup("tz",
- options(
- namedGroup("tzOffset", options("\\+", "-")+
- DIGIT+optionally(DIGIT)+optionally(optionally(":")+DIGIT+DIGIT)),
- optionally("\\+")+TZ_CODE));
- private final static String TIME_ZONE_OPTIONALLY_SIGNED_OFFSET =
- namedGroup("tz",
- options(
- namedGroup("tzOffset", options("\\+", "-", " ")+
- options("0"+DIGIT, "10", "11", "12")+optionally(optionally(":")+DIGIT+DIGIT)),
- TZ_CODE));
-
- private static String getDateTimeSeparatorPattern(String extraChars) {
- return
- options(
- " +"+optionally(anyChar(DATE_TIME_ANY_ORDER_GROUP_SEPARATOR+extraChars+",")),
- anyChar(DATE_TIME_ANY_ORDER_GROUP_SEPARATOR+extraChars+",")) +
- anyChar(DATE_TIME_ANY_ORDER_GROUP_SEPARATOR+extraChars)+"*";
- }
-
- @SuppressWarnings("deprecation")
- // we have written our own parsing because the alternatives were either too specific or too general
- // java and apache and even joda-time are too specific, and would require explosion of patterns to be flexible;
- // Natty - https://github.com/joestelmach/natty - is very cool, but it drags in ANTLR,
- // it doesn't support dashes between date and time, and
- // it encourages relative time which would be awesome but only if we resolved it on read
- // (however there is natty code to parseDateNatty in the git history if we did want to use it)
- private static Maybe<Calendar> parseCalendarSimpleFlexibleFormatParser(String input) {
- input = input.trim();
-
- String[] DATE_PATTERNS = new String[] {
- DATE_ONLY_WITH_INNER_SEPARATORS,
- DATE_ONLY_NO_SEPARATORS,
- DATE_WORDS_2,
- DATE_WORDS_3,
- };
- String[] TIME_PATTERNS = new String[] {
- TIME_ONLY_WITH_INNER_SEPARATORS,
- TIME_ONLY_NO_SEPARATORS
- };
- String[] TZ_PATTERNS = new String[] {
- // space then time zone with sign (+-) or code is preferred
- optionally(getDateTimeSeparatorPattern("")) + " " + TIME_ZONE_SIGNED_OFFSET,
- // then no TZ - but declare the named groups
- namedGroup("tz", namedGroup("tzOffset", "")+namedGroup("tzCode", "")),
- // then any separator then offset with sign
- getDateTimeSeparatorPattern("") + TIME_ZONE_SIGNED_OFFSET,
-
- // try parsing with enforced separators before TZ first
- // (so e.g. in the case of DATE-0100, the -0100 is the time, not the timezone)
- // then relax below (e.g. in the case of DATE-TIME+0100)
-
- // finally match DATE-TIME-1000 as time zone -1000
- // or DATE-TIME 1000 as TZ +1000 in case a + was supplied but converted to ' ' by web
- // (but be stricter about the format, two or four digits required, and hours <= 12 so as not to confuse with a year)
- optionally(getDateTimeSeparatorPattern("")) + TIME_ZONE_OPTIONALLY_SIGNED_OFFSET
- };
-
- List<String> basePatterns = MutableList.of();
-
- // patterns with date first
- String[] DATE_PATTERNS_UNCLOSED = new String[] {
- // separator before time *required* if date had separators
- DATE_ONLY_WITH_INNER_SEPARATORS + "("+getDateTimeSeparatorPattern("Tt"),
- // separator before time optional if date did not have separators
- DATE_ONLY_NO_SEPARATORS + "("+optionally(getDateTimeSeparatorPattern("Tt")),
- // separator before time required if date has words
- DATE_WORDS_2 + "("+getDateTimeSeparatorPattern("Tt"),
- DATE_WORDS_3 + "("+getDateTimeSeparatorPattern("Tt"),
- };
- for (String tzP: TZ_PATTERNS)
- for (String dateP: DATE_PATTERNS_UNCLOSED)
- for (String timeP: TIME_PATTERNS)
- basePatterns.add(dateP + timeP+")?" + tzP);
-
- // also allow time first, with TZ after, then before
- for (String tzP: TZ_PATTERNS)
- for (String dateP: DATE_PATTERNS)
- for (String timeP: TIME_PATTERNS)
- basePatterns.add(timeP + getDateTimeSeparatorPattern("") + dateP + tzP);
- // also allow time first, with TZ after, then before
- for (String tzP: TZ_PATTERNS)
- for (String dateP: DATE_PATTERNS)
- for (String timeP: TIME_PATTERNS)
- basePatterns.add(timeP + tzP + getDateTimeSeparatorPattern("") + dateP);
-
- Maybe<Matcher> mm = Maybe.absent();
- for (String p: basePatterns) {
- mm = match(p, input);
- if (mm.isPresent()) break;
- }
- if (mm.isPresent()) {
- Matcher m = mm.get();
- Calendar result;
-
- String tz = m.group("tz");
-
- int year = Integer.parseInt(m.group("year"));
- int day = Integer.parseInt(m.group("day"));
-
- String monthS = m.group("month");
- int month;
- if (monthS.matches(DIGIT+"+")) {
- month = Integer.parseInt(monthS)-1;
- } else {
- try {
- month = new SimpleDateFormat("yyyy-MMM-dd", Locale.ROOT).parse("2015-"+monthS+"-15").getMonth();
- } catch (ParseException e) {
- return Maybe.absent("Unknown date format '"+input+"': invalid month '"+monthS+"'; try http://yaml.org/type/timestamp.html format e.g. 2015-06-15 16:00:00 +0000");
- }
- }
-
- if (Strings.isNonBlank(tz)) {
- TimeZone tzz = null;
- String tzCode = m.group("tzCode");
- if (Strings.isNonBlank(tzCode)) {
- tz = tzCode;
- }
- if (tz.matches(DIGIT+"+")) {
- // stick a plus in front in case it was submitted by a web form and turned into a space
- tz = "+"+tz;
- } else {
- tzz = getTimeZone(tz);
- }
- if (tzz==null) {
- Maybe<Matcher> tmm = match(" ?(?<tzH>(\\+|\\-||)"+DIGIT+optionally(DIGIT)+")"+optionally(optionally(":")+namedGroup("tzM", DIGIT+DIGIT)), tz);
- if (tmm.isAbsent()) {
- return Maybe.absent("Unknown date format '"+input+"': invalid timezone '"+tz+"'; try http://yaml.org/type/timestamp.html format e.g. 2015-06-15 16:00:00 +0000");
- }
- Matcher tm = tmm.get();
- String tzM = tm.group("tzM");
- int offset = (60*Integer.parseInt(tm.group("tzH")) + Integer.parseInt("0"+(tzM!=null ? tzM : "")))*60;
- tzz = new SimpleTimeZone(offset*1000, tz);
- }
- tz = getTimeZoneOffsetString(tzz, year, month, day);
- result = new GregorianCalendar(tzz);
- } else {
- result = new GregorianCalendar();
- }
- result.clear();
-
- result.set(Calendar.YEAR, year);
- result.set(Calendar.MONTH, month);
- result.set(Calendar.DAY_OF_MONTH, day);
- if (m.group("hours")!=null) {
- int hours = Integer.parseInt(m.group("hours"));
- String meridian = m.group("meridian");
- if (Strings.isNonBlank(meridian) && meridian.toLowerCase().startsWith("p")) {
- if (hours>12) {
- return Maybe.absent("Unknown date format '"+input+"': can't be "+hours+" PM; try http://yaml.org/type/timestamp.html format e.g. 2015-06-15 16:00:00 +0000");
- }
- hours += 12;
- }
- result.set(Calendar.HOUR_OF_DAY, hours);
- String minsS = m.group("mins");
- if (Strings.isNonBlank(minsS)) {
- result.set(Calendar.MINUTE, Integer.parseInt(minsS));
- }
- String secsS = m.group("secs");
- if (Strings.isBlank(secsS)) {
- // leave at zero
- } else if (secsS.matches(DIGIT+DIGIT+"?")) {
- result.set(Calendar.SECOND, Integer.parseInt(secsS));
- } else {
- double s = Double.parseDouble(secsS);
- if (secsS.indexOf('.')>=0) {
- // accept
- } else if (secsS.length()==5) {
- // allow ssSSS with no punctuation
- s = s/=1000;
- } else {
- return Maybe.absent("Unknown date format '"+input+"': invalid seconds '"+secsS+"'; try http://yaml.org/type/timestamp.html format e.g. 2015-06-15 16:00:00 +0000");
- }
- result.set(Calendar.SECOND, (int)s);
- result.set(Calendar.MILLISECOND, (int)((s*1000) % 1000));
- }
- }
-
- return Maybe.of(result);
- }
- return Maybe.absent("Unknown date format '"+input+"'; try http://yaml.org/type/timestamp.html format e.g. 2015-06-15 16:00:00 +0000");
- }
-
- public static TimeZone getTimeZone(String code) {
- if (code.indexOf('/')==-1) {
- if ("Z".equals(code)) return TIME_ZONE_UTC;
- if ("UTC".equals(code)) return TIME_ZONE_UTC;
- if ("GMT".equals(code)) return TIME_ZONE_UTC;
-
- // get the time zone -- most short codes aren't accepted, so accept (and prefer) certain common codes
- if ("EST".equals(code)) return getTimeZone("America/New_York");
- if ("EDT".equals(code)) return getTimeZone("America/New_York");
- if ("PST".equals(code)) return getTimeZone("America/Los_Angeles");
- if ("PDT".equals(code)) return getTimeZone("America/Los_Angeles");
- if ("CST".equals(code)) return getTimeZone("America/Chicago");
- if ("CDT".equals(code)) return getTimeZone("America/Chicago");
- if ("MST".equals(code)) return getTimeZone("America/Denver");
- if ("MDT".equals(code)) return getTimeZone("America/Denver");
-
- if ("BST".equals(code)) return getTimeZone("Europe/London"); // otherwise BST is Bangladesh!
- if ("CEST".equals(code)) return getTimeZone("Europe/Paris");
- // IST falls through to below, where it is treated as India (not Irish); IDT not recognised
- }
-
- TimeZone tz = TimeZone.getTimeZone(code);
- if (tz!=null && !tz.equals(TimeZone.getTimeZone("GMT"))) {
- // recognized
- return tz;
- }
- // possibly unrecognized -- GMT returned if not known, bad TimeZone API!
- String timeZones[] = TimeZone.getAvailableIDs();
- for (String tzs: timeZones) {
- if (tzs.equals(code)) return tz;
- }
- // definitely unrecognized
- return null;
- }
-
- /** convert a TimeZone e.g. Europe/London to an offset string as at the given day, e.g. +0100 or +0000 depending daylight savings,
- * absent with nice error if zone unknown */
- public static Maybe<String> getTimeZoneOffsetString(String tz, int year, int month, int day) {
- TimeZone tzz = getTimeZone(tz);
- if (tzz==null) return Maybe.absent("Unknown time zone code: "+tz);
- return Maybe.of(getTimeZoneOffsetString(tzz, year, month, day));
- }
-
- /** as {@link #getTimeZoneOffsetString(String, int, int, int)} where the {@link TimeZone} is already instantiated */
- @SuppressWarnings("deprecation")
- public static String getTimeZoneOffsetString(TimeZone tz, int year, int month, int day) {
- int tzMins = tz.getOffset(new Date(year, month, day).getTime())/60/1000;
- String tzStr = (tzMins<0 ? "-" : "+") + Strings.makePaddedString(""+(Math.abs(tzMins)/60), 2, "0", "")+Strings.makePaddedString(""+(Math.abs(tzMins)%60), 2, "0", "");
- return tzStr;
- }
-
- private static String namedGroup(String name, String pattern) {
- return "(?<"+name+">"+pattern+")";
- }
- private static String anyChar(String charSet) {
- return "["+charSet+"]";
- }
- private static String optionally(String pattern) {
- return "("+pattern+")?";
- }
- private static String options(String ...patterns) {
- return "("+Strings.join(patterns,"|")+")";
- }
- private static String notMatching(String pattern) {
- return "(?!"+pattern+")";
- }
-
- private static Maybe<Matcher> match(String pattern, String input) {
- Matcher m = Pattern.compile("^"+pattern+"$").matcher(input);
- if (m.find()) return Maybe.of(m);
- return Maybe.absent();
- }
-
- /**
- * Parses the given date, accepting either a UTC timestamp (i.e. a long), or a formatted date.
- * <p>
- * If no time zone supplied, this defaults to the TZ configured at the brooklyn server.
- *
- * @deprecated since 0.7.0 use {@link #parseCalendar(String)} for general or {@link #parseCalendarFormat(String, DateFormat)} for a format,
- * plus {@link #parseCalendarUtc(String)} if you want to accept UTC
- */
- public static Date parseDateString(String dateString, DateFormat format) {
- Maybe<Calendar> r = parseCalendarFormat(dateString, format);
- if (r.isPresent()) return r.get().getTime();
-
- r = parseCalendarUtc(dateString);
- if (r.isPresent()) return r.get().getTime();
-
- throw new IllegalArgumentException("Date " + dateString + " cannot be parsed as UTC millis or using format " + format);
- }
- public static Maybe<Calendar> parseCalendarFormat(String dateString, String format) {
- return parseCalendarFormat(dateString, new SimpleDateFormat(format, Locale.ROOT));
- }
- public static Maybe<Calendar> parseCalendarFormat(String dateString, DateFormat format) {
- if (dateString == null) {
- throw new NumberFormatException("GeneralHelper.parseDateString cannot parse a null string");
- }
- Preconditions.checkNotNull(format, "date format");
- dateString = dateString.trim();
-
- ParsePosition p = new ParsePosition(0);
- Date result = format.parse(dateString, p);
- if (result!=null) {
- // accept results even if the entire thing wasn't parsed, as enough was to match the requested format
- return Maybe.of(newCalendarFromDate(result));
- }
- if (log.isTraceEnabled()) log.trace("Could not parse date "+dateString+" using format "+format+": "+p);
- return Maybe.absent();
- }
-
- /** removes milliseconds from the date object; needed if serializing to ISO-8601 format
- * and want to serialize back and get the same data */
- public static Date dropMilliseconds(Date date) {
- return date==null ? null : date.getTime()%1000!=0 ? new Date(date.getTime() - (date.getTime()%1000)) : date;
- }
-
- /** returns the duration elapsed since the given timestamp (UTC) */
- public static Duration elapsedSince(long timestamp) {
- return Duration.millis(System.currentTimeMillis() - timestamp);
- }
-
- /** true iff it has been longer than the given duration since the given timestamp */
- public static boolean hasElapsedSince(long timestamp, Duration duration) {
- return elapsedSince(timestamp).compareTo(duration) > 0;
- }
-
- /** more readable and shorter convenience for System.currentTimeMillis() */
- public static long now() {
- return System.currentTimeMillis();
- }
-
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java b/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
deleted file mode 100644
index b46e9d1..0000000
--- a/utils/common/src/main/java/brooklyn/util/yaml/Yamls.java
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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 brooklyn.util.yaml;
-
-import java.io.Reader;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import javax.annotation.Nullable;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.yaml.snakeyaml.Yaml;
-import org.yaml.snakeyaml.error.Mark;
-import org.yaml.snakeyaml.nodes.MappingNode;
-import org.yaml.snakeyaml.nodes.Node;
-import org.yaml.snakeyaml.nodes.NodeId;
-import org.yaml.snakeyaml.nodes.NodeTuple;
-import org.yaml.snakeyaml.nodes.ScalarNode;
-import org.yaml.snakeyaml.nodes.SequenceNode;
-
-import brooklyn.util.collections.Jsonya;
-import brooklyn.util.collections.MutableList;
-import brooklyn.util.exceptions.Exceptions;
-import brooklyn.util.exceptions.UserFacingException;
-import brooklyn.util.text.Strings;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.Iterables;
-
-public class Yamls {
-
- private static final Logger log = LoggerFactory.getLogger(Yamls.class);
-
- /** returns the given (yaml-parsed) object as the given yaml type.
- * <p>
- * if the object is an iterable or iterator this method will fully expand it as a list.
- * if the requested type is not an iterable or iterator, and the list contains a single item, this will take that single item.
- * <p>
- * in other cases this method simply does a type-check and cast (no other type coercion).
- * <p>
- * @throws IllegalArgumentException if the input is an iterable not containing a single element,
- * and the cast is requested to a non-iterable type
- * @throws ClassCastException if cannot be casted */
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public static <T> T getAs(Object x, Class<T> type) {
- if (x==null) return null;
- if (x instanceof Iterable || x instanceof Iterator) {
- List result = new ArrayList();
- Iterator xi;
- if (Iterator.class.isAssignableFrom(x.getClass())) {
- xi = (Iterator)x;
- } else {
- xi = ((Iterable)x).iterator();
- }
- while (xi.hasNext()) {
- result.add( xi.next() );
- }
- if (type.isAssignableFrom(List.class)) return (T)result;
- if (type.isAssignableFrom(Iterator.class)) return (T)result.iterator();
- x = Iterables.getOnlyElement(result);
- }
- if (type.isInstance(x)) return (T)x;
- throw new ClassCastException("Cannot convert "+x+" ("+x.getClass()+") to "+type);
- }
-
- /**
- * Parses the given yaml, and walks the given path to return the referenced object.
- *
- * @see #getAt(Object, List)
- */
- @Beta
- public static Object getAt(String yaml, List<String> path) {
- Iterable<Object> result = new org.yaml.snakeyaml.Yaml().loadAll(yaml);
- Object current = result.iterator().next();
- return getAtPreParsed(current, path);
- }
-
- /**
- * For pre-parsed yaml, walks the maps/lists to return the given sub-item.
- * In the given path:
- * <ul>
- * <li>A vanilla string is assumed to be a key into a map.
- * <li>A string in the form like "[0]" is assumed to be an index into a list
- * </ul>
- *
- * Also see {@link Jsonya}, such as {@code Jsonya.of(current).at(path).get()}.
- *
- * @return The object at the given path, or {@code null} if that path does not exist.
- */
- @Beta
- @SuppressWarnings("unchecked")
- public static Object getAtPreParsed(Object current, List<String> path) {
- for (String pathPart : path) {
- if (pathPart.startsWith("[") && pathPart.endsWith("]")) {
- String index = pathPart.substring(1, pathPart.length()-1);
- try {
- current = Iterables.get((Iterable<?>)current, Integer.parseInt(index));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Invalid index '"+index+"', in path "+path);
- } catch (IndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Invalid index '"+index+"', in path "+path);
- }
- } else {
- current = ((Map<String, ?>)current).get(pathPart);
- }
- if (current == null) return null;
- }
- return current;
- }
-
- @SuppressWarnings("rawtypes")
- public static void dump(int depth, Object r) {
- if (r instanceof Iterable) {
- for (Object ri : ((Iterable)r))
- dump(depth+1, ri);
- } else if (r instanceof Map) {
- for (Object re: ((Map)r).entrySet()) {
- for (int i=0; i<depth; i++) System.out.print(" ");
- System.out.println(((Entry)re).getKey()+":");
- dump(depth+1, ((Entry)re).getValue());
- }
- } else {
- for (int i=0; i<depth; i++) System.out.print(" ");
- if (r==null) System.out.println("<null>");
- else System.out.println("<"+r.getClass().getSimpleName()+">"+" "+r);
- }
- }
-
- /** simplifies new Yaml().loadAll, and converts to list to prevent single-use iterable bug in yaml */
- @SuppressWarnings("unchecked")
- public static Iterable<Object> parseAll(String yaml) {
- Iterable<Object> result = new org.yaml.snakeyaml.Yaml().loadAll(yaml);
- return (List<Object>) getAs(result, List.class);
- }
-
- /** as {@link #parseAll(String)} */
- @SuppressWarnings("unchecked")
- public static Iterable<Object> parseAll(Reader yaml) {
- Iterable<Object> result = new org.yaml.snakeyaml.Yaml().loadAll(yaml);
- return (List<Object>) getAs(result, List.class);
- }
-
- public static Object removeMultinameAttribute(Map<String,Object> obj, String ...equivalentNames) {
- Object result = null;
- for (String name: equivalentNames) {
- Object candidate = obj.remove(name);
- if (candidate!=null) {
- if (result==null) result = candidate;
- else if (!result.equals(candidate)) {
- log.warn("Different values for attributes "+Arrays.toString(equivalentNames)+"; " +
- "preferring '"+result+"' to '"+candidate+"'");
- }
- }
- }
- return result;
- }
-
- public static Object getMultinameAttribute(Map<String,Object> obj, String ...equivalentNames) {
- Object result = null;
- for (String name: equivalentNames) {
- Object candidate = obj.get(name);
- if (candidate!=null) {
- if (result==null) result = candidate;
- else if (!result.equals(candidate)) {
- log.warn("Different values for attributes "+Arrays.toString(equivalentNames)+"; " +
- "preferring '"+result+"' to '"+candidate+"'");
- }
- }
- }
- return result;
- }
-
- @Beta
- public static class YamlExtract {
- String yaml;
- NodeTuple focusTuple;
- Node prev, key, focus, next;
- Exception error;
- boolean includeKey = false, includePrecedingComments = true, includeOriginalIndentation = false;
-
- private int indexStart(Node node, boolean defaultIsYamlEnd) {
- if (node==null) return defaultIsYamlEnd ? yaml.length() : 0;
- return index(node.getStartMark());
- }
- private int indexEnd(Node node, boolean defaultIsYamlEnd) {
- if (!found() || node==null) return defaultIsYamlEnd ? yaml.length() : 0;
- return index(node.getEndMark());
- }
- private int index(Mark mark) {
- try {
- return mark.getIndex();
- } catch (NoSuchMethodError e) {
- try {
- getClass().getClassLoader().loadClass("org.testng.TestNG");
- } catch (ClassNotFoundException e1) {
- // not using TestNG
- Exceptions.propagateIfFatal(e1);
- throw e;
- }
- if (!LOGGED_TESTNG_WARNING.getAndSet(true)) {
- log.warn("Detected TestNG/SnakeYAML version incompatibilities: "
- + "some YAML source reconstruction will be unavailable. "
- + "This can happen with TestNG plugins which force an older version of SnakeYAML "
- + "which does not support Mark.getIndex. "
- + "It should not occur from maven CLI runs. "
- + "(Subsequent occurrences will be silently dropped, and source code reconstructed from YAML.)");
- }
- // using TestNG
- throw new KnownClassVersionException(e);
- }
- }
-
- static AtomicBoolean LOGGED_TESTNG_WARNING = new AtomicBoolean();
- static class KnownClassVersionException extends IllegalStateException {
- private static final long serialVersionUID = -1620847775786753301L;
- public KnownClassVersionException(Throwable e) {
- super("Class version error. This can happen if using a TestNG plugin in your IDE "
- + "which is an older version, dragging in an older version of SnakeYAML which does not support Mark.getIndex.", e);
- }
- }
-
- public int getEndOfPrevious() {
- return indexEnd(prev, false);
- }
- @Nullable public Node getKey() {
- return key;
- }
- public Node getResult() {
- return focus;
- }
- public int getStartOfThis() {
- if (includeKey && focusTuple!=null) return indexStart(focusTuple.getKeyNode(), false);
- return indexStart(focus, false);
- }
- private int getStartColumnOfThis() {
- if (includeKey && focusTuple!=null) return focusTuple.getKeyNode().getStartMark().getColumn();
- return focus.getStartMark().getColumn();
- }
- public int getEndOfThis() {
- return getEndOfThis(false);
- }
- private int getEndOfThis(boolean goToEndIfNoNext) {
- if (next==null && goToEndIfNoNext) return yaml.length();
- return indexEnd(focus, false);
- }
- public int getStartOfNext() {
- return indexStart(next, true);
- }
-
- private static int initialWhitespaceLength(String x) {
- int i=0;
- while (i < x.length() && x.charAt(i)==' ') i++;
- return i;
- }
-
- public String getFullYamlTextOriginal() {
- return yaml;
- }
-
- /** Returns the original YAML with the found item replaced by the given replacement YAML.
- * @param replacement YAML to put in for the found item;
- * this YAML typically should not have any special indentation -- if required when replacing it will be inserted.
- * <p>
- * if replacing an inline map entry, the supplied entry must follow the structure being replaced;
- * for example, if replacing the value in <code>key: value</code> with a map,
- * supplying a replacement <code>subkey: value</code> would result in invalid yaml;
- * the replacement must be supplied with a newline, either before the subkey or after.
- * (if unsure we believe it is always valid to include an initial newline or comment with newline.)
- */
- public String getFullYamlTextWithExtractReplaced(String replacement) {
- if (!found()) throw new IllegalStateException("Cannot perform replacement when item was not matched.");
- String result = yaml.substring(0, getStartOfThis());
-
- String[] newLines = replacement.split("\n");
- for (int i=1; i<newLines.length; i++)
- newLines[i] = Strings.makePaddedString("", getStartColumnOfThis(), "", " ") + newLines[i];
- result += Strings.lines(newLines);
- if (replacement.endsWith("\n")) result += "\n";
-
- int end = getEndOfThis();
- result += yaml.substring(end);
-
- return result;
- }
-
- /** Specifies whether the key should be included in the found text,
- * when calling {@link #getMatchedYamlText()} or {@link #getFullYamlTextWithExtractReplaced(String)},
- * if the found item is a map entry.
- * Defaults to false.
- * @return this object, for use in a fluent constructions
- */
- public YamlExtract withKeyIncluded(boolean includeKey) {
- this.includeKey = includeKey;
- return this;
- }
-
- /** Specifies whether comments preceding the found item should be included,
- * when calling {@link #getMatchedYamlText()} or {@link #getFullYamlTextWithExtractReplaced(String)}.
- * This will not include comments which are indented further than the item,
- * as those will typically be aligned with the previous item
- * (whereas comments whose indentation is the same or less than the found item
- * will typically be aligned with this item).
- * Defaults to true.
- * @return this object, for use in a fluent constructions
- */
- public YamlExtract withPrecedingCommentsIncluded(boolean includePrecedingComments) {
- this.includePrecedingComments = includePrecedingComments;
- return this;
- }
-
- /** Specifies whether the original indentation should be preserved
- * (and in the case of the first line, whether whitespace should be inserted so its start column is preserved),
- * when calling {@link #getMatchedYamlText()}.
- * Defaults to false, the returned text will be outdented as far as possible.
- * @return this object, for use in a fluent constructions
- */
- public YamlExtract withOriginalIndentation(boolean includeOriginalIndentation) {
- this.includeOriginalIndentation = includeOriginalIndentation;
- return this;
- }
-
- @Beta
- public String getMatchedYamlTextOrWarn() {
- try {
- return getMatchedYamlText();
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (e instanceof KnownClassVersionException) {
- log.debug("Known class version exception; no yaml text being matched for "+this+": "+e);
- } else {
- if (e instanceof UserFacingException) {
- log.warn("Unable to match yaml text in "+this+": "+e.getMessage());
- } else {
- log.warn("Unable to match yaml text in "+this+": "+e, e);
- }
- }
- return null;
- }
- }
-
- @Beta
- public String getMatchedYamlText() {
- if (!found()) return null;
-
- String[] body = yaml.substring(getStartOfThis(), getEndOfThis(true)).split("\n", -1);
-
- int firstLineIndentationOfFirstThing;
- if (focusTuple!=null) {
- firstLineIndentationOfFirstThing = focusTuple.getKeyNode().getStartMark().getColumn();
- } else {
- firstLineIndentationOfFirstThing = focus.getStartMark().getColumn();
- }
- int firstLineIndentationToAdd;
- if (focusTuple!=null && (includeKey || body.length==1)) {
- firstLineIndentationToAdd = focusTuple.getKeyNode().getStartMark().getColumn();
- } else {
- firstLineIndentationToAdd = focus.getStartMark().getColumn();
- }
-
-
- String firstLineIndentationToAddS = Strings.makePaddedString("", firstLineIndentationToAdd, "", " ");
- String subsequentLineIndentationToRemoveS = firstLineIndentationToAddS;
-
-/* complexities of indentation:
-
-x: a
- bc
-
-should become
-
-a
- bc
-
-whereas
-
-- a: 0
- b: 1
-
-selecting 0 should give
-
-a: 0
-b: 1
-
- */
- List<String> result = MutableList.of();
- if (includePrecedingComments) {
- if (getEndOfPrevious() > getStartOfThis()) {
- throw new UserFacingException("YAML not in expected format; when scanning, previous end "+getEndOfPrevious()+" exceeds this start "+getStartOfThis());
- }
- String[] preceding = yaml.substring(getEndOfPrevious(), getStartOfThis()).split("\n");
- // suppress comments which are on the same line as the previous item or indented more than firstLineIndentation,
- // ensuring appropriate whitespace is added to preceding[0] if it starts mid-line
- if (preceding.length>0 && prev!=null) {
- preceding[0] = Strings.makePaddedString("", prev.getEndMark().getColumn(), "", " ") + preceding[0];
- }
- for (String p: preceding) {
- int w = initialWhitespaceLength(p);
- p = p.substring(w);
- if (p.startsWith("#")) {
- // only add if the hash is not indented further than the first line
- if (w <= firstLineIndentationOfFirstThing) {
- if (includeOriginalIndentation) p = firstLineIndentationToAddS + p;
- result.add(p);
- }
- }
- }
- }
-
- boolean doneFirst = false;
- for (String p: body) {
- if (!doneFirst) {
- if (includeOriginalIndentation) {
- // have to insert the right amount of spacing
- p = firstLineIndentationToAddS + p;
- }
- result.add(p);
- doneFirst = true;
- } else {
- if (includeOriginalIndentation) {
- result.add(p);
- } else {
- result.add(Strings.removeFromStart(p, subsequentLineIndentationToRemoveS));
- }
- }
- }
- return Strings.join(result, "\n");
- }
-
- boolean found() {
- return focus != null;
- }
-
- public Exception getError() {
- return error;
- }
-
- @Override
- public String toString() {
- return "Extract["+focus+";prev="+prev+";key="+key+";next="+next+"]";
- }
- }
-
- private static void findTextOfYamlAtPath(YamlExtract result, int pathIndex, Object ...path) {
- if (pathIndex>=path.length) {
- // we're done
- return;
- }
-
- Object pathItem = path[pathIndex];
- Node node = result.focus;
-
- if (node.getNodeId()==NodeId.mapping && pathItem instanceof String) {
- // find key
- Iterator<NodeTuple> ti = ((MappingNode)node).getValue().iterator();
- while (ti.hasNext()) {
- NodeTuple t = ti.next();
- Node key = t.getKeyNode();
- if (key.getNodeId()==NodeId.scalar) {
- if (pathItem.equals( ((ScalarNode)key).getValue() )) {
- result.key = key;
- result.focus = t.getValueNode();
- if (pathIndex+1<path.length) {
- // there are more path items, so the key here is a previous node
- result.prev = key;
- } else {
- result.focusTuple = t;
- }
- findTextOfYamlAtPath(result, pathIndex+1, path);
- if (result.next==null) {
- if (ti.hasNext()) result.next = ti.next().getKeyNode();
- }
- return;
- } else {
- result.prev = t.getValueNode();
- }
- } else {
- throw new IllegalStateException("Key "+key+" is not a scalar, searching for "+pathItem+" at depth "+pathIndex+" of "+Arrays.asList(path));
- }
- }
- throw new IllegalStateException("Did not find "+pathItem+" in "+node+" at depth "+pathIndex+" of "+Arrays.asList(path));
-
- } else if (node.getNodeId()==NodeId.sequence && pathItem instanceof Number) {
- // find list item
- List<Node> nl = ((SequenceNode)node).getValue();
- int i = ((Number)pathItem).intValue();
- if (i>=nl.size())
- throw new IllegalStateException("Index "+i+" is out of bounds in "+node+", searching for "+pathItem+" at depth "+pathIndex+" of "+Arrays.asList(path));
- if (i>0) result.prev = nl.get(i-1);
- result.key = null;
- result.focus = nl.get(i);
- findTextOfYamlAtPath(result, pathIndex+1, path);
- if (result.next==null) {
- if (nl.size()>i+1) result.next = nl.get(i+1);
- }
- return;
-
- } else {
- throw new IllegalStateException("Node "+node+" does not match selector "+pathItem+" at depth "+pathIndex+" of "+Arrays.asList(path));
- }
-
- // unreachable
- }
-
-
- /** Given a path, where each segment consists of a string (key) or number (element in list),
- * this will find the YAML text for that element
- * <p>
- * If not found this will return a {@link YamlExtract}
- * where {@link YamlExtract#isMatch()} is false and {@link YamlExtract#getError()} is set. */
- public static YamlExtract getTextOfYamlAtPath(String yaml, Object ...path) {
- YamlExtract result = new YamlExtract();
- if (yaml==null) return result;
- try {
- int pathIndex = 0;
- result.yaml = yaml;
- result.focus = new Yaml().compose(new StringReader(yaml));
-
- findTextOfYamlAtPath(result, pathIndex, path);
- return result;
- } catch (NoSuchMethodError e) {
- throw new IllegalStateException("Class version error. This can happen if using a TestNG plugin in your IDE "
- + "which is an older version, dragging in an older version of SnakeYAML which does not support Mark.getIndex.", e);
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- log.debug("Unable to find element in yaml (setting in result): "+e);
- result.error = e;
- return result;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/cf2f7a93/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
new file mode 100644
index 0000000..4d581eb
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.brooklyn.config;
+
+import java.io.Serializable;
+
+import com.google.common.annotations.Beta;
+
+@SuppressWarnings("serial")
+public abstract class ConfigInheritance implements Serializable {
+
+ public static final ConfigInheritance ALWAYS = new Always();
+ public static final ConfigInheritance NONE = new None();
+
+ private ConfigInheritance() {}
+
+ @Beta
+ public abstract boolean isInherited(ConfigKey<?> key, Object from, Object to);
+
+ private static class Always extends ConfigInheritance {
+ @Override
+ public boolean isInherited(ConfigKey<?> key, Object from, Object to) {
+ return true;
+ }
+ }
+
+ private static class None extends ConfigInheritance {
+ @Override
+ public boolean isInherited(ConfigKey<?> key, Object from, Object to) {
+ return false;
+ }
+ }
+
+}