This is an automated email from the ASF dual-hosted git repository.
iuliana pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
The following commit(s) were added to refs/heads/master by this push:
new 97f0c96 add a variety of units useful for blueprints
new 89a5f94 Merge pull request #1146 from ahgittin/more-units
97f0c96 is described below
commit 97f0c96f2ce5a1a76c941ab28aed69a4b827372a
Author: Alex Heneveld <[email protected]>
AuthorDate: Thu Feb 4 17:18:43 2021 +0000
add a variety of units useful for blueprints
---
.../jackson/JsonSymbolDependentDeserializer.java | 93 ++++++++++++++++++++++
.../apache/brooklyn/util/core/task/BasicTask.java | 2 +
.../brooklyn/util/core/units/AbstractUnit.java | 80 +++++++++++++++++++
.../apache/brooklyn/util/core/units/ByteSize.java | 51 ++++++++++++
.../util/core/units/DurationOrBoolean.java | 72 +++++++++++++++++
.../apache/brooklyn/util/core/units/Frequency.java | 53 ++++++++++++
.../org/apache/brooklyn/util/core/units/Range.java | 69 ++++++++++++++++
7 files changed, 420 insertions(+)
diff --git
a/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/JsonSymbolDependentDeserializer.java
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/JsonSymbolDependentDeserializer.java
new file mode 100644
index 0000000..1fa30a6
--- /dev/null
+++
b/core/src/main/java/org/apache/brooklyn/core/resolve/jackson/JsonSymbolDependentDeserializer.java
@@ -0,0 +1,93 @@
+/*
+ * 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.core.resolve.jackson;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
+import java.io.IOException;
+import java.util.function.Function;
+
+public class JsonSymbolDependentDeserializer extends JsonDeserializer<Object>
implements ContextualDeserializer {
+
+ protected DeserializationContext ctxt;
+ protected BeanProperty beanProp;
+ private BeanDescription beanDesc;
+ protected JavaType type;
+
+ public BeanDescription getBeanDescription() {
+ if (beanDesc!=null) return beanDesc;
+ return beanDesc = ctxt.getConfig().introspect(type);
+ }
+
+ @Override
+ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException {
+ this.ctxt = ctxt;
+ beanProp = property;
+ if (property!=null) {
+ type = property.getType();
+ }
+ if (type==null) {
+ // this is normally set during contextualization but not during
deserialization (although not if we're the ones contextualizing it)
+ type = ctxt.getContextualType();
+ }
+
+ return this;
+ }
+
+ @Override
+ public Object deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
+ JsonDeserializer<?> deser;
+ Function<Object,Object> post = x -> x;
+
+ if (p.getCurrentToken() == JsonToken.START_ARRAY) {
+ return deserializeArray(p);
+ } else {
+ // (primitives, string, etc not yet supported)
+
+ // assume object
+ return deserializeObject(p);
+ }
+ }
+
+ protected JsonDeserializer<?> contextualize(JsonDeserializer<?> deser)
throws IOException, JsonProcessingException {
+ if (deser instanceof ContextualDeserializer) {
+ // collection requires this initialization (beanProp seems usually
to be null / irrelevant, but capture and pass it for good measure)
+ return ((ContextualDeserializer)deser).createContextual(ctxt,
beanProp);
+ }
+ return deser;
+ }
+
+ protected Object deserializeArray(JsonParser p) throws IOException,
JsonProcessingException {
+ return contextualize(getArrayDeserializer()).deserialize(p, ctxt);
+ }
+ protected JsonDeserializer<?> getArrayDeserializer() throws IOException,
JsonProcessingException {
+ throw new IllegalStateException("List input not supported for "+type);
+ }
+
+ protected Object deserializeObject(JsonParser p) throws IOException,
JsonProcessingException {
+ return contextualize(getObjectDeserializer()).deserialize(p, ctxt);
+ }
+ protected JsonDeserializer<?> getObjectDeserializer() throws IOException,
JsonProcessingException {
+ return ctxt.getFactory().createBeanDeserializer(ctxt, type,
getBeanDescription());
+ }
+
+}
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
index e7278912..b5304e1 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/task/BasicTask.java
@@ -87,6 +87,8 @@ public class BasicTask<T> implements TaskInternal<T> {
public final String displayName;
public final String description;
+ // TODO would be nice to make this linked to preserve order, as well as
concurrent;
+ // but need to take care to support deserialization
protected final Set<Object> tags = Sets.newConcurrentHashSet();
// for debugging, to record where tasks were created
// { tags.add(new Throwable("Creation stack trace")); }
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/units/AbstractUnit.java
b/core/src/main/java/org/apache/brooklyn/util/core/units/AbstractUnit.java
new file mode 100644
index 0000000..624851b
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/units/AbstractUnit.java
@@ -0,0 +1,80 @@
+/*
+ * 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.util.core.units;
+
+import org.apache.brooklyn.util.guava.Maybe;
+
+import java.util.Objects;
+import java.util.function.Function;
+
+/** a unit of size, eg "1 gb" */
+public abstract class AbstractUnit {
+
+ protected final long value;
+ private static final String[] PREFIXES = { "", "K", "M", "G", "T" };
+
+ /** json constructor */
+ protected AbstractUnit() { this(0); }
+
+ public AbstractUnit(long v) {
+ value = v;
+ }
+
+ protected String[] prefixes() { return PREFIXES; }
+ protected abstract String unit();
+ protected abstract String binaryUnit();
+
+ public String toString() {
+ if (value==0) return "0 "+unit();
+ return toString(1000, s -> s+unit())
+ .orMaybe(() -> binaryUnit()==null ? Maybe.absent() :
toString(1024, s -> s+binaryUnit()))
+ .or(() -> value + " " + unit());
+ }
+
+ private Maybe<String> toString(int modulus, Function<String,String>
unitFn) {
+ if (value % modulus == 0) {
+ long v = value;
+ int unit = 0;
+ while (v % modulus == 0 && unit+1 < PREFIXES.length) {
+ v /= modulus;
+ unit++;
+ }
+ return Maybe.of(v + " " + unitFn.apply(PREFIXES[unit]));
+ }
+ return Maybe.absent();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ AbstractUnit other = (AbstractUnit) o;
+ return value == other.value;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(value);
+ }
+
+ public int compareTo(AbstractUnit o) {
+ return Long.compare(value, o.value);
+ }
+
+}
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/units/ByteSize.java
b/core/src/main/java/org/apache/brooklyn/util/core/units/ByteSize.java
new file mode 100644
index 0000000..5280eec
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/units/ByteSize.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util.core.units;
+
+import org.apache.brooklyn.util.text.ByteSizeStrings;
+
+/** a unit of size, eg "1 gb" */
+public class ByteSize extends AbstractUnit implements Comparable<ByteSize> {
+
+ /** json constructor */
+ private ByteSize() {}
+
+ public ByteSize(String s) { super(ByteSizeStrings.parse(s, null,
ByteSizeStrings.metric())); }
+
+ public static ByteSize fromString(String s) { return new ByteSize(s); }
+
+ @Override
+ protected String unit() {
+ return "B";
+ }
+
+ @Override
+ protected String binaryUnit() {
+ return "iB";
+ }
+
+ public long getBytes() {
+ return value;
+ }
+
+ @Override
+ public int compareTo(ByteSize o) {
+ return super.compareTo(o);
+ }
+}
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/units/DurationOrBoolean.java
b/core/src/main/java/org/apache/brooklyn/util/core/units/DurationOrBoolean.java
new file mode 100644
index 0000000..c99a84b
--- /dev/null
+++
b/core/src/main/java/org/apache/brooklyn/util/core/units/DurationOrBoolean.java
@@ -0,0 +1,72 @@
+/*
+ * 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.util.core.units;
+
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.time.Duration;
+
+public class DurationOrBoolean {
+
+ static {
+ TypeCoercions.registerAdapter(DurationOrBoolean.class, Duration.class,
DurationOrBoolean::asDuration);
+ TypeCoercions.registerAdapter(Boolean.class, DurationOrBoolean.class,
DurationOrBoolean::new);
+ TypeCoercions.registerAdapter(Duration.class, DurationOrBoolean.class,
DurationOrBoolean::new);
+ TypeCoercions.registerAdapter(String.class, DurationOrBoolean.class,
DurationOrBoolean::fromString);
+ }
+
+ private DurationOrBoolean() {
+ this(null);
+ }
+
+ public DurationOrBoolean(Duration d) {
+ this.durationSupplied = d;
+ this.booleanSupplied = null;
+ }
+
+ public DurationOrBoolean(boolean b) {
+ this.booleanSupplied = b;
+ this.durationSupplied = null;
+ }
+
+ public static DurationOrBoolean fromString(String s) {
+ if (s==null) return null;
+ if (s.equalsIgnoreCase("true")) return new DurationOrBoolean(true);
+ if (s.equalsIgnoreCase("false")) return new DurationOrBoolean(false);
+ return new DurationOrBoolean(Duration.parse(s));
+ }
+
+ /** Takes true as forver, false as zero, otherwise returns the duration
(or null) */
+ public Duration asDuration() {
+ return durationSupplied != null ? durationSupplied :
+ booleanSupplied == null ? null :
+ booleanSupplied ? Duration.PRACTICALLY_FOREVER :
Duration.ZERO;
+ }
+
+ final Duration durationSupplied;
+ final Boolean booleanSupplied;
+
+ public Duration getDurationSupplied() {
+ return durationSupplied;
+ }
+
+ public Boolean getBooleanSupplied() {
+ return booleanSupplied;
+ }
+
+}
diff --git
a/core/src/main/java/org/apache/brooklyn/util/core/units/Frequency.java
b/core/src/main/java/org/apache/brooklyn/util/core/units/Frequency.java
new file mode 100644
index 0000000..e420632
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/units/Frequency.java
@@ -0,0 +1,53 @@
+/*
+ * 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.util.core.units;
+
+import org.apache.brooklyn.util.text.ByteSizeStrings;
+
+/** a unit of frequency, esp CPU speed, eg "2.6 GHz" */
+public class Frequency extends AbstractUnit implements Comparable<Frequency> {
+
+ /** json constructor */
+ private Frequency() {}
+
+ public Frequency(String s) {
+ super(ByteSizeStrings.parse(s.replaceAll("Hz", "B"), null,
ByteSizeStrings.metric()));
+ }
+
+ public static Frequency fromString(String s) { return new Frequency(s); }
+
+ @Override
+ protected String unit() {
+ return "Hz";
+ }
+
+ @Override
+ protected String binaryUnit() {
+ return null;
+ }
+
+ public long getHertz() {
+ return value;
+ }
+
+ @Override
+ public int compareTo(Frequency o) {
+ return super.compareTo(o);
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/units/Range.java
b/core/src/main/java/org/apache/brooklyn/util/core/units/Range.java
new file mode 100644
index 0000000..cb691f7
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/util/core/units/Range.java
@@ -0,0 +1,69 @@
+/*
+ * 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.util.core.units;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import java.io.IOException;
+import java.util.List;
+import
org.apache.brooklyn.core.resolve.jackson.JsonSymbolDependentDeserializer;
+import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.core.units.Range.RangeDeserializer;
+
+@JsonDeserialize(using = RangeDeserializer.class)
+public class Range extends MutableList<Object> {
+
+ public Range() {}
+ public Range(List<Object> l) {
+ setValue(l);
+ }
+
+ public boolean add(Object o) {
+ if (size() >= 2) throw new IllegalStateException("Range must be of
size 2; cannot add '"+o+"' when currently "+this);
+ if (o instanceof String && "unbounded".equalsIgnoreCase((String)o)) {
+ o = isEmpty() ? Integer.MIN_VALUE : Integer.MAX_VALUE;
+ }
+ if (!(o instanceof Integer)) throw new IllegalStateException("Invalid
value for range; must be an integer or 'UNBOUNDED'");
+ return super.add((Integer)o);
+ }
+
+ public int min() { return (Integer) get(0); }
+ public int max() { return (Integer) get(1); }
+
+ private void setValue(List<Object> l) {
+ if (l.size() != 2) throw new IllegalStateException("Range must be of
size 2; cannot create from "+l);
+ l.forEach(this::add);
+ }
+
+ // TODO this could be replaced by a
ConstructorMatchingSymbolDependentDeserializer
+ public static class RangeDeserializer extends
JsonSymbolDependentDeserializer {
+ @Override
+ protected Object deserializeArray(JsonParser p) throws IOException {
+ return new Range( (List<Object>) super.deserializeArray(p) );
+ }
+ @Override
+ protected JsonDeserializer<?> getArrayDeserializer() throws
IOException {
+ return ctxt.getFactory().createCollectionDeserializer(ctxt,
+
ctxt.getTypeFactory().constructCollectionType(List.class, Object.class),
+ getBeanDescription());
+ }
+ }
+
+}