diff options
Diffstat (limited to 'third_party/java/dd_plist/java/com/dd/plist/NSDictionary.java')
-rw-r--r-- | third_party/java/dd_plist/java/com/dd/plist/NSDictionary.java | 539 |
1 files changed, 539 insertions, 0 deletions
diff --git a/third_party/java/dd_plist/java/com/dd/plist/NSDictionary.java b/third_party/java/dd_plist/java/com/dd/plist/NSDictionary.java new file mode 100644 index 0000000000..5d432ad1a7 --- /dev/null +++ b/third_party/java/dd_plist/java/com/dd/plist/NSDictionary.java @@ -0,0 +1,539 @@ +/* + * plist - An open source library to parse and generate property lists + * Copyright (C) 2014 Daniel Dreibrodt + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.dd.plist; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * A NSDictionary is a collection of keys and values, essentially a Hashtable. + * The keys are simple Strings whereas the values can be any kind of NSObject. + * <p/> + * You can access the keys through the function <code>allKeys()</code>. Access + * to the objects stored for each key is given through the function + * <code>objectoForKey(String key)</code>. + * + * @author Daniel Dreibrodt + * @see java.util.Hashtable + * @see com.dd.plist.NSObject + */ +public class NSDictionary extends NSObject implements Map<String, NSObject> { + + private HashMap<String, NSObject> dict; + + /** + * Creates a new empty NSDictionary. + */ + public NSDictionary() { + //With a linked HashMap the order of elements in the dictionary is kept. + dict = new LinkedHashMap<String, NSObject>(); + } + + /** + * Gets the hashmap which stores the keys and values of this dictionary. + * Changes to the hashmap's contents are directly reflected in this + * dictionary. + * + * @return The hashmap which is used by this dictionary to store its contents. + */ + public HashMap<String, NSObject> getHashMap() { + return dict; + } + + /** + * Gets the NSObject stored for the given key. + * + * @param key The key. + * @return The object. + */ + public NSObject objectForKey(String key) { + return dict.get(key); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#size() + */ + public int size() { + return dict.size(); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#isEmpty() + */ + public boolean isEmpty() { + return dict.isEmpty(); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#containsKey(java.lang.Object) + */ + public boolean containsKey(Object key) { + return dict.containsKey(key); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#containsValue(java.lang.Object) + */ + public boolean containsValue(Object value) { + if(value == null) + return false; + NSObject wrap = NSObject.wrap(value); + return dict.containsValue(wrap); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#get(java.lang.Object) + */ + public NSObject get(Object key) { + return dict.get(key); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#putAll(java.util.Map) + */ + public void putAll(Map<? extends String, ? extends NSObject> values) { + for (Object object : values.entrySet()) { + @SuppressWarnings("unchecked") + Map.Entry<String, NSObject> entry = (Map.Entry<String, NSObject>) object; + put(entry.getKey(), entry.getValue()); + } + } + + /** + * Puts a new key-value pair into this dictionary. + * If the value is null, no operation will be performed on the dictionary. + * + * @param key The key. + * @param obj The value. + * @return The value previously associated to the given key, + * or null, if no value was associated to it. + */ + public NSObject put(String key, NSObject obj) { + if(obj == null) + return dict.get(key); + return dict.put(key, obj); + } + + /** + * Puts a new key-value pair into this dictionary. + * If the value is null, no operation will be performed on the dictionary. + * + * @param key The key. + * @param obj The value. Supported object types are numbers, byte-arrays, dates, strings and arrays or sets of those. + * @return The value previously associated to the given key, + * or null, if no value was associated to it. + */ + public NSObject put(String key, Object obj) { + if(obj == null) + return dict.get(key); + return put(key, NSObject.wrap(obj)); + } + + /** + * Puts a new key-value pair into this dictionary. + * + * @param key The key. + * @param obj The value. + */ + public NSObject put(String key, long obj) { + return put(key, new NSNumber(obj)); + } + + /** + * Puts a new key-value pair into this dictionary. + * + * @param key The key. + * @param obj The value. + */ + public NSObject put(String key, double obj) { + return put(key, new NSNumber(obj)); + } + + /** + * Puts a new key-value pair into this dictionary. + * + * @param key The key. + * @param obj The value. + */ + public NSObject put(String key, boolean obj) { + return put(key, new NSNumber(obj)); + } + + /** + * Removes a key-value pair from this dictionary. + * + * @param key The key + * @return the value previously associated to the given key. + */ + public NSObject remove(String key) { + return dict.remove(key); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#remove(java.lang.Object) + */ + public NSObject remove(Object key) { + return dict.remove(key); + } + + /** + * Removes all key-value pairs from this dictionary. + * @see java.util.Map#clear() + */ + public void clear() { + dict.clear(); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#keySet() + */ + public Set<String> keySet() { + return dict.keySet(); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#values() + */ + public Collection<NSObject> values() { + return dict.values(); + } + + /* + * (non-Javadoc) + * + * @see java.util.Map#entrySet() + */ + public Set<Entry<String, NSObject>> entrySet() { + return dict.entrySet(); + } + + /** + * Checks whether a given key is contained in this dictionary. + * + * @param key The key that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsKey(String key) { + return dict.containsKey(key); + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(NSObject val) { + return val != null && dict.containsValue(val); + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(String val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSString.class)) { + NSString str = (NSString) o; + if (str.getContent().equals(val)) + return true; + } + } + return false; + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(long val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSNumber.class)) { + NSNumber num = (NSNumber) o; + if (num.isInteger() && num.intValue() == val) + return true; + } + } + return false; + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(double val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSNumber.class)) { + NSNumber num = (NSNumber) o; + if (num.isReal() && num.doubleValue() == val) + return true; + } + } + return false; + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(boolean val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSNumber.class)) { + NSNumber num = (NSNumber) o; + if (num.isBoolean() && num.boolValue() == val) + return true; + } + } + return false; + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(Date val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSDate.class)) { + NSDate dat = (NSDate) o; + if (dat.getDate().equals(val)) + return true; + } + } + return false; + } + + /** + * Checks whether a given value is contained in this dictionary. + * + * @param val The value that will be searched for. + * @return Whether the key is contained in this dictionary. + */ + public boolean containsValue(byte[] val) { + for (NSObject o : dict.values()) { + if (o.getClass().equals(NSData.class)) { + NSData dat = (NSData) o; + if (Arrays.equals(dat.bytes(), val)) + return true; + } + } + return false; + } + + /** + * Counts the number of contained key-value pairs. + * + * @return The size of this NSDictionary. + */ + public int count() { + return dict.size(); + } + + @Override + public boolean equals(Object obj) { + return (obj.getClass().equals(this.getClass()) && ((NSDictionary) obj).dict.equals(dict)); + } + + /** + * Gets a list of all keys used in this NSDictionary. + * + * @return The list of all keys used in this NSDictionary. + */ + public String[] allKeys() { + return dict.keySet().toArray(new String[count()]); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 83 * hash + (this.dict != null ? this.dict.hashCode() : 0); + return hash; + } + + @Override + void toXML(StringBuilder xml, int level) { + indent(xml, level); + xml.append("<dict>"); + xml.append(NSObject.NEWLINE); + for (String key : dict.keySet()) { + NSObject val = objectForKey(key); + indent(xml, level + 1); + xml.append("<key>"); + //According to http://www.w3.org/TR/REC-xml/#syntax node values must not + //contain the characters < or &. Also the > character should be escaped. + if (key.contains("&") || key.contains("<") || key.contains(">")) { + xml.append("<![CDATA["); + xml.append(key.replaceAll("]]>", "]]]]><![CDATA[>")); + xml.append("]]>"); + } else { + xml.append(key); + } + xml.append("</key>"); + xml.append(NSObject.NEWLINE); + val.toXML(xml, level + 1); + xml.append(NSObject.NEWLINE); + } + indent(xml, level); + xml.append("</dict>"); + } + + @Override + void assignIDs(BinaryPropertyListWriter out) { + super.assignIDs(out); + for (Map.Entry<String, NSObject> entry : dict.entrySet()) { + new NSString(entry.getKey()).assignIDs(out); + entry.getValue().assignIDs(out); + } + } + + @Override + void toBinary(BinaryPropertyListWriter out) throws IOException { + out.writeIntHeader(0xD, dict.size()); + Set<Map.Entry<String, NSObject>> entries = dict.entrySet(); + for (Map.Entry<String, NSObject> entry : entries) { + out.writeID(out.getID(new NSString(entry.getKey()))); + } + for (Map.Entry<String, NSObject> entry : entries) { + out.writeID(out.getID(entry.getValue())); + } + } + + /** + * Generates a valid ASCII property list which has this NSDictionary as its + * root object. The generated property list complies with the format as + * described in <a href="https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/PropertyLists/OldStylePlists/OldStylePLists.html"> + * Property List Programming Guide - Old-Style ASCII Property Lists</a>. + * + * @return ASCII representation of this object. + */ + public String toASCIIPropertyList() { + StringBuilder ascii = new StringBuilder(); + toASCII(ascii, 0); + ascii.append(NEWLINE); + return ascii.toString(); + } + + /** + * Generates a valid ASCII property list in GnuStep format which has this + * NSDictionary as its root object. The generated property list complies with + * the format as described in <a href="http://www.gnustep.org/resources/documentation/Developer/Base/Reference/NSPropertyList.html"> + * GnuStep - NSPropertyListSerialization class documentation + * </a> + * + * @return GnuStep ASCII representation of this object. + */ + public String toGnuStepASCIIPropertyList() { + StringBuilder ascii = new StringBuilder(); + toASCIIGnuStep(ascii, 0); + ascii.append(NEWLINE); + return ascii.toString(); + } + + @Override + protected void toASCII(StringBuilder ascii, int level) { + indent(ascii, level); + ascii.append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); + ascii.append(NEWLINE); + String[] keys = allKeys(); + for (String key : keys) { + NSObject val = objectForKey(key); + indent(ascii, level + 1); + ascii.append("\""); + ascii.append(NSString.escapeStringForASCII(key)); + ascii.append("\" ="); + Class<?> objClass = val.getClass(); + if (objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) { + ascii.append(NEWLINE); + val.toASCII(ascii, level + 2); + } else { + ascii.append(" "); + val.toASCII(ascii, 0); + } + ascii.append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); + ascii.append(NEWLINE); + } + indent(ascii, level); + ascii.append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN); + } + + @Override + protected void toASCIIGnuStep(StringBuilder ascii, int level) { + indent(ascii, level); + ascii.append(ASCIIPropertyListParser.DICTIONARY_BEGIN_TOKEN); + ascii.append(NEWLINE); + String[] keys = dict.keySet().toArray(new String[dict.size()]); + for (String key : keys) { + NSObject val = objectForKey(key); + indent(ascii, level + 1); + ascii.append("\""); + ascii.append(NSString.escapeStringForASCII(key)); + ascii.append("\" ="); + Class<?> objClass = val.getClass(); + if (objClass.equals(NSDictionary.class) || objClass.equals(NSArray.class) || objClass.equals(NSData.class)) { + ascii.append(NEWLINE); + val.toASCIIGnuStep(ascii, level + 2); + } else { + ascii.append(" "); + val.toASCIIGnuStep(ascii, 0); + } + ascii.append(ASCIIPropertyListParser.DICTIONARY_ITEM_DELIMITER_TOKEN); + ascii.append(NEWLINE); + } + indent(ascii, level); + ascii.append(ASCIIPropertyListParser.DICTIONARY_END_TOKEN); + } +} |