001package org.javasimon.console.json; 002 003import org.javasimon.console.reflect.Getter; 004import org.javasimon.console.reflect.GetterFactory; 005import org.javasimon.console.text.Stringifier; 006import org.javasimon.console.text.StringifierFactory; 007 008import java.io.IOException; 009import java.io.Writer; 010import java.util.ArrayList; 011import java.util.HashMap; 012import java.util.List; 013import java.util.Map; 014 015/** 016 * JavaScript Object. 017 * 018 * @author gquintana 019 */ 020public class ObjectJS extends AnyJS { 021 022 private List<Attribute> attributes; 023 private Map<String, Attribute> attributesByName; 024 025 public ObjectJS() { 026 this.attributes = new ArrayList<>(); 027 this.attributesByName = new HashMap<>(); 028 } 029 030 public void setAttribute(String name, AnyJS value) { 031 assert name != null; 032 assert value != null; 033 Attribute attribute = attributesByName.get(name); 034 if (attribute == null) { 035 attribute = new Attribute(name, value); 036 attributes.add(attribute); 037 attributesByName.put(name, attribute); 038 } else { 039 attribute.value = value; 040 } 041 } 042 043 public <T> void setSimpleAttribute(String name, T value, Stringifier<T> stringifier) { 044 SimpleJS propertyJS = new SimpleJS<>(value, stringifier); 045 setAttribute(name, propertyJS); 046 } 047 048 public AnyJS getAttribute(String name) { 049 assert name != null; 050 Attribute attribute = attributesByName.get(name); 051 return attribute == null ? null : attribute.value; 052 } 053 054 @Override 055 public void write(Writer writer) throws IOException { 056 writer.write("{"); 057 boolean first = true; 058 for (Attribute attribute : attributes) { 059 if (first) { 060 first = false; 061 } else { 062 writer.write(","); 063 } 064 writeString(writer, attribute.name); 065 writer.write(":"); 066 attribute.value.write(writer); 067 } 068 writer.write("}"); 069 } 070 071 @SuppressWarnings("unchecked") 072 public static ObjectJS create(Object o, StringifierFactory stringifierFactory) { 073 if (o == null) { 074 return null; 075 } else { 076 ObjectJS objectJS = new ObjectJS(); 077 // Export properties using reflection 078 for (Getter getter : GetterFactory.getGetters(o.getClass())) { 079 String propertyName = getter.getName(); 080 Stringifier propertyStringifier = stringifierFactory.getStringifier(getter.getType(), getter.getSubType()); 081 if (propertyStringifier != null) { 082 Object propertyValue = getter.get(o); 083 objectJS.setSimpleAttribute(propertyName, propertyValue, propertyStringifier); 084 } 085 } 086 return objectJS; 087 } 088 } 089 090 /** Export Simon attribute map as a JS object. */ 091 private static class Attribute { 092 093 private final String name; 094 private AnyJS value; 095 096 public Attribute(String name, AnyJS value) { 097 this.name = name; 098 this.value = value; 099 } 100 101 @Override 102 public boolean equals(Object obj) { 103 if (obj == null) { 104 return false; 105 } 106 if (getClass() != obj.getClass()) { 107 return false; 108 } 109 final Attribute other = (Attribute) obj; 110 if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) { 111 return false; 112 } 113 return true; 114 } 115 116 @Override 117 public int hashCode() { 118 return this.name == null ? 0 : this.name.hashCode(); 119 } 120 } 121}