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());
+        }
+    }
+
+}

Reply via email to