001
002package net.filebot.format;
003
004import java.util.AbstractMap;
005import java.util.AbstractSet;
006import java.util.Iterator;
007import java.util.Map;
008import java.util.Set;
009import java.util.function.Function;
010
011public class AssociativeScriptObject extends AbstractMap<String, Object> {
012
013        private final LazyLookup lookup;
014        private final Function<String, Object> defaultValue;
015        private final Function<Object, Object> normalize;
016
017        public AssociativeScriptObject(Map<?, ?> properties, Function<String, Object> defaultValue) {
018                this(new LazyLookup(properties), defaultValue, Function.identity());
019        }
020
021        private AssociativeScriptObject(LazyLookup properties, Function<String, Object> defaultValue, Function<Object, Object> normalize) {
022                this.lookup = properties;
023                this.defaultValue = defaultValue;
024                this.normalize = normalize;
025        }
026
027        public AssociativeScriptObject normalize(Function<Object, Object> normalize) {
028                return new AssociativeScriptObject(lookup, defaultValue, normalize);
029        }
030
031        @Override
032        public Object get(Object key) {
033                if (key == null) {
034                        return null;
035                }
036
037                try {
038                        Object value = lookup.get(key);
039                        if (value != null) {
040                                return normalize.apply(value);
041                        }
042                } catch (BindingException e) {
043                        // ignore binding errors
044                }
045
046                return defaultValue.apply(key.toString());
047        }
048
049        @Override
050        public boolean containsKey(Object key) {
051                return lookup.contains(key);
052        }
053
054        @Override
055        public boolean containsValue(Object value) {
056                return false;
057        }
058
059        @Override
060        public Set<Entry<String, Object>> entrySet() {
061                return new AbstractSet<Map.Entry<String, Object>>() {
062
063                        @Override
064                        public Iterator<Entry<String, Object>> iterator() {
065                                return lookup.stream().iterator();
066                        }
067
068                        @Override
069                        public int size() {
070                                return lookup.size();
071                        }
072                };
073        }
074
075        @Override
076        public int hashCode() {
077                return lookup.hashCode();
078        }
079
080        @Override
081        public boolean equals(Object other) {
082                return lookup.equals(other);
083        }
084
085        @Override
086        public String toString() {
087                // all properties in original order
088                return lookup.toString();
089        }
090
091}