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}