Skip to content

Commit 4715a21

Browse files
authored
Merge pull request #16 from asdf-format/eslavich-convenience-getters
Add convenience methods for fetching nodes deep in the tree
2 parents dfcc997 + 9dbd7b1 commit 4715a21

10 files changed

Lines changed: 1023 additions & 63 deletions

File tree

asdf-core/src/main/java/org/asdfformat/asdf/node/AsdfNode.java

Lines changed: 236 additions & 0 deletions
Large diffs are not rendered by default.

asdf-core/src/main/java/org/asdfformat/asdf/node/impl/AsdfNodeBase.java

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.math.BigDecimal;
88
import java.math.BigInteger;
99
import java.time.Instant;
10+
import java.util.Arrays;
1011
import java.util.Collections;
1112
import java.util.Iterator;
1213
import java.util.List;
@@ -75,6 +76,18 @@ public boolean containsKey(final AsdfNode key) {
7576
return false;
7677
}
7778

79+
@Override
80+
public boolean containsKey(final Object... keys) {
81+
if (keys.length == 0) {
82+
return true;
83+
}
84+
85+
final AsdfNode currentKey = constructKeyNode(keys[0]);
86+
87+
return getOptional(currentKey).map(node -> node.containsKey(Arrays.copyOfRange(keys, 1, keys.length)))
88+
.orElse(false);
89+
}
90+
7891
@Override
7992
public int size() {
8093
return 0;
@@ -100,6 +113,17 @@ public AsdfNode get(final AsdfNode key) {
100113
throw new IllegalStateException(makeGetErrorMessage("AsdfNode"));
101114
}
102115

116+
@Override
117+
public AsdfNode get(final Object... keys) {
118+
if (keys.length == 0) {
119+
return this;
120+
}
121+
122+
final AsdfNode currentKey = constructKeyNode(keys[0]);
123+
124+
return get(currentKey).get(Arrays.copyOfRange(keys, 1, keys.length));
125+
}
126+
103127
@Override
104128
public Optional<AsdfNode> getOptional(final String key) {
105129
if (containsKey(key)) {
@@ -156,6 +180,17 @@ public Optional<AsdfNode> getOptional(final AsdfNode key) {
156180
}
157181
}
158182

183+
@Override
184+
public Optional<AsdfNode> getOptional(final Object... keys) {
185+
if (keys.length == 0) {
186+
return Optional.of(this);
187+
}
188+
189+
final AsdfNode currentKey = constructKeyNode(keys[0]);
190+
191+
return getOptional(currentKey).flatMap(node -> node.getOptional(Arrays.copyOfRange(keys, 1, keys.length)));
192+
}
193+
159194
@Override
160195
public BigDecimal getBigDecimal(final String key) {
161196
return get(key).asBigDecimal();
@@ -176,6 +211,11 @@ public BigDecimal getBigDecimal(final AsdfNode key) {
176211
return get(key).asBigDecimal();
177212
}
178213

214+
@Override
215+
public BigDecimal getBigDecimal(final Object... keys) {
216+
return get(keys).asBigDecimal();
217+
}
218+
179219
@Override
180220
public BigInteger getBigInteger(final String key) {
181221
return get(key).asBigInteger();
@@ -196,6 +236,11 @@ public BigInteger getBigInteger(final AsdfNode key) {
196236
return get(key).asBigInteger();
197237
}
198238

239+
@Override
240+
public BigInteger getBigInteger(final Object... keys) {
241+
return get(keys).asBigInteger();
242+
}
243+
199244
@Override
200245
public boolean getBoolean(final String key) {
201246
return get(key).asBoolean();
@@ -216,6 +261,11 @@ public boolean getBoolean(final AsdfNode key) {
216261
return get(key).asBoolean();
217262
}
218263

264+
@Override
265+
public boolean getBoolean(final Object... keys) {
266+
return get(keys).asBoolean();
267+
}
268+
219269
@Override
220270
public byte getByte(final String key) {
221271
return get(key).asByte();
@@ -236,6 +286,11 @@ public byte getByte(final AsdfNode key) {
236286
return get(key).asByte();
237287
}
238288

289+
@Override
290+
public byte getByte(final Object... keys) {
291+
return get(keys).asByte();
292+
}
293+
239294
@Override
240295
public double getDouble(final String key) {
241296
return get(key).asDouble();
@@ -256,6 +311,11 @@ public double getDouble(final AsdfNode key) {
256311
return get(key).asDouble();
257312
}
258313

314+
@Override
315+
public double getDouble(final Object... keys) {
316+
return get(keys).asDouble();
317+
}
318+
259319
@Override
260320
public float getFloat(final String key) {
261321
return get(key).asFloat();
@@ -276,6 +336,11 @@ public float getFloat(final AsdfNode key) {
276336
return get(key).asFloat();
277337
}
278338

339+
@Override
340+
public float getFloat(final Object... keys) {
341+
return get(keys).asFloat();
342+
}
343+
279344
@Override
280345
public Instant getInstant(final String key) {
281346
return get(key).asInstant();
@@ -296,6 +361,11 @@ public Instant getInstant(final AsdfNode key) {
296361
return get(key).asInstant();
297362
}
298363

364+
@Override
365+
public Instant getInstant(final Object... keys) {
366+
return get(keys).asInstant();
367+
}
368+
299369
@Override
300370
public int getInt(final String key) {
301371
return get(key).asInt();
@@ -316,6 +386,11 @@ public int getInt(final AsdfNode key) {
316386
return get(key).asInt();
317387
}
318388

389+
@Override
390+
public int getInt(final Object... keys) {
391+
return get(keys).asInt();
392+
}
393+
319394
@Override
320395
public <T> List<T> getList(final String key, final Class<T> elementClass) {
321396
return get(key).asList(elementClass);
@@ -336,6 +411,31 @@ public <T> List<T> getList(final AsdfNode key, final Class<T> elementClass) {
336411
return get(key).asList(elementClass);
337412
}
338413

414+
@Override
415+
public <T> List<T> getList(final Class<T> elementClass, final String key) {
416+
return get(key).asList(elementClass);
417+
}
418+
419+
@Override
420+
public <T> List<T> getList(final Class<T> elementClass, final long key) {
421+
return get(key).asList(elementClass);
422+
}
423+
424+
@Override
425+
public <T> List<T> getList(final Class<T> elementClass, final boolean key) {
426+
return get(key).asList(elementClass);
427+
}
428+
429+
@Override
430+
public <T> List<T> getList(final Class<T> elementClass, final AsdfNode key) {
431+
return get(key).asList(elementClass);
432+
}
433+
434+
@Override
435+
public <T> List<T> getList(final Class<T> elementClass, final Object... keys) {
436+
return get(keys).asList(elementClass);
437+
}
438+
339439
@Override
340440
public long getLong(final String key) {
341441
return get(key).asLong();
@@ -356,6 +456,11 @@ public long getLong(final AsdfNode key) {
356456
return get(key).asLong();
357457
}
358458

459+
@Override
460+
public long getLong(final Object... keys) {
461+
return get(keys).asLong();
462+
}
463+
359464
@Override
360465
public Number getNumber(final String key) {
361466
return get(key).asNumber();
@@ -376,6 +481,11 @@ public Number getNumber(final AsdfNode key) {
376481
return get(key).asNumber();
377482
}
378483

484+
@Override
485+
public Number getNumber(final Object... keys) {
486+
return get(keys).asNumber();
487+
}
488+
379489
@Override
380490
public <K, V> Map<K, V> getMap(final String key, final Class<K> keyClass, final Class<V> valueClass) {
381491
return get(key).asMap(keyClass, valueClass);
@@ -396,6 +506,31 @@ public <K, V> Map<K, V> getMap(final AsdfNode key, final Class<K> keyClass, fina
396506
return get(key).asMap(keyClass, valueClass);
397507
}
398508

509+
@Override
510+
public <K, V> Map<K, V> getMap(final Class<K> keyClass, final Class<V> valueClass, final String key) {
511+
return get(key).asMap(keyClass, valueClass);
512+
}
513+
514+
@Override
515+
public <K, V> Map<K, V> getMap(final Class<K> keyClass, final Class<V> valueClass, final long key) {
516+
return get(key).asMap(keyClass, valueClass);
517+
}
518+
519+
@Override
520+
public <K, V> Map<K, V> getMap(final Class<K> keyClass, final Class<V> valueClass, final boolean key) {
521+
return get(key).asMap(keyClass, valueClass);
522+
}
523+
524+
@Override
525+
public <K, V> Map<K, V> getMap(final Class<K> keyClass, final Class<V> valueClass, final AsdfNode key) {
526+
return get(key).asMap(keyClass, valueClass);
527+
}
528+
529+
@Override
530+
public <K, V> Map<K, V> getMap(final Class<K> keyClass, final Class<V> valueClass, final Object... keys) {
531+
return get(keys).asMap(keyClass, valueClass);
532+
}
533+
399534
@Override
400535
public NdArray<?> getNdArray(final String key) {
401536
return get(key).asNdArray();
@@ -416,6 +551,11 @@ public NdArray<?> getNdArray(final AsdfNode key) {
416551
return get(key).asNdArray();
417552
}
418553

554+
@Override
555+
public NdArray<?> getNdArray(final Object... keys) {
556+
return get(keys).asNdArray();
557+
}
558+
419559
@Override
420560
public short getShort(final String key) {
421561
return get(key).asShort();
@@ -436,6 +576,11 @@ public short getShort(final AsdfNode key) {
436576
return get(key).asShort();
437577
}
438578

579+
@Override
580+
public short getShort(final Object... keys) {
581+
return get(keys).asShort();
582+
}
583+
439584
@Override
440585
public String getString(final String key) {
441586
return get(key).asString();
@@ -456,6 +601,11 @@ public String getString(final AsdfNode key) {
456601
return get(key).asString();
457602
}
458603

604+
@Override
605+
public String getString(final Object... keys) {
606+
return get(keys).asString();
607+
}
608+
459609
@Override
460610
public BigDecimal asBigDecimal() {
461611
throw new IllegalStateException(makeAsErrorMessage("BigDecimal"));
@@ -552,4 +702,18 @@ protected String makeGetErrorMessage(final String keyType) {
552702
protected String makeAsErrorMessage(final String asType) {
553703
return String.format("%s node cannot be represented as %s", getNodeType(), asType);
554704
}
705+
706+
protected AsdfNode constructKeyNode(final Object key) {
707+
if (key instanceof String) {
708+
return StringAsdfNode.of((String)key);
709+
} else if (key instanceof AsdfNode) {
710+
return (AsdfNode)key;
711+
} else if (key instanceof Number) {
712+
return NumberAsdfNode.of((Number)key);
713+
} else if (key instanceof Boolean) {
714+
return BooleanAsdfNode.of((Boolean)key);
715+
} else {
716+
throw new IllegalArgumentException("Unhandled key class: " + key.getClass().getSimpleName());
717+
}
718+
}
555719
}

asdf-core/src/main/java/org/asdfformat/asdf/node/impl/NumberAsdfNode.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ public BigInteger asBigInteger() {
109109
@Override
110110
public byte asByte() {
111111
if (value instanceof Byte) {
112-
return (Byte)value;
112+
return (Byte) value;
113+
} else if (value instanceof Integer && (int)value >= Byte.MIN_VALUE && (int)value <= Byte.MAX_VALUE) {
114+
return value.byteValue();
113115
} else {
114116
throw new IllegalStateException("Node cannot be represented as byte");
115117
}
@@ -152,7 +154,9 @@ public Number asNumber() {
152154
public short asShort() {
153155
if (value instanceof Byte || value instanceof Short) {
154156
return value.shortValue();
155-
} else {
157+
} else if (value instanceof Integer && (int)value >= Short.MIN_VALUE && (int)value <= Short.MAX_VALUE) {
158+
return value.shortValue();
159+
}else {
156160
throw new IllegalStateException("Node cannot be represented as short");
157161
}
158162
}
@@ -162,16 +166,39 @@ public boolean equals(final Object other) {
162166
if (this == other) {
163167
return true;
164168
}
165-
if (other == null || getClass() != other.getClass()) {
169+
170+
if (!(other instanceof NumberAsdfNode)) {
171+
return false;
172+
}
173+
174+
final NumberAsdfNode otherNode = (NumberAsdfNode)other;
175+
176+
if (!Objects.equals(this.tag, otherNode.tag)) {
166177
return false;
167178
}
168-
final NumberAsdfNode typedOther = (NumberAsdfNode) other;
169-
return Objects.equals(tag, typedOther.tag) && Objects.equals(value, typedOther.value);
179+
180+
if (this.value == null || otherNode.value == null) {
181+
return this.value == otherNode.value;
182+
}
183+
184+
if (this.value.getClass() == otherNode.value.getClass() && this.value.equals(otherNode.value)) {
185+
return true;
186+
}
187+
188+
if (isSpecialFloatingPointValue(this.value) || isSpecialFloatingPointValue(otherNode.value)) {
189+
return Double.compare(this.value.doubleValue(), otherNode.value.doubleValue()) == 0;
190+
}
191+
192+
return asBigDecimal().compareTo(otherNode.asBigDecimal()) == 0;
170193
}
171194

172195
@Override
173196
public int hashCode() {
174-
return Objects.hash(tag, value);
197+
if (isSpecialFloatingPointValue(value)) {
198+
return Double.hashCode(value.doubleValue());
199+
}
200+
201+
return asBigDecimal().stripTrailingZeros().hashCode();
175202
}
176203

177204
@Override
@@ -188,4 +215,9 @@ public String toString() {
188215

189216
return NodeUtils.nodeToString(this, fields);
190217
}
218+
219+
private boolean isSpecialFloatingPointValue(final Number number) {
220+
return (number instanceof Double && (((Double)number).isInfinite() || ((Double)number).isNaN())) ||
221+
(number instanceof Float && (((Float)number).isInfinite() || ((Float)number).isNaN()));
222+
}
191223
}

0 commit comments

Comments
 (0)