1 28 package org.jvyamlb; 29 30 import java.io.IOException ; 31 import java.io.Serializable ; 32 33 import java.lang.reflect.Method ; 34 35 import java.text.DateFormat ; 36 import java.text.SimpleDateFormat ; 37 38 import java.util.Iterator ; 39 import java.util.Map ; 40 import java.util.HashMap ; 41 import java.util.List ; 42 import java.util.ArrayList ; 43 import java.util.LinkedList ; 44 import java.util.Set ; 45 import java.util.Date ; 46 import java.util.Calendar ; 47 48 import org.jvyamlb.nodes.Node; 49 import org.jvyamlb.nodes.CollectionNode; 50 import org.jvyamlb.nodes.MappingNode; 51 import org.jvyamlb.nodes.ScalarNode; 52 import org.jvyamlb.nodes.SequenceNode; 53 54 import org.jruby.util.ByteList; 55 56 59 public class RepresenterImpl implements Representer { 60 private final Serializer serializer; 61 private final char defaultStyle; 62 private final Map representedObjects; 63 64 public RepresenterImpl(final Serializer serializer, final YAMLConfig opts) { 65 this.serializer = serializer; 66 this.defaultStyle = opts.useDouble() ? '"' : (opts.useSingle() ? '\'' : 0); 67 this.representedObjects = new HashMap (); 68 } 69 70 private Node representData(final Object data) throws IOException { 71 String aliasKey = null; 72 Node node = null; 73 74 if(!ignoreAliases(data)) { 75 aliasKey = ""+System.identityHashCode(data); 76 } 77 78 if(null != aliasKey) { 79 if(this.representedObjects.containsKey(aliasKey)) { 80 node = (Node)this.representedObjects.get(aliasKey); 81 if(null == node) { 82 throw new RepresenterException("recursive objects are not allowed: " + data); 83 } 84 return node; 85 } 86 this.representedObjects.put(aliasKey,null); 87 } 88 89 node = getNodeCreatorFor(data).toYamlNode(this); 90 91 if(aliasKey != null) { 92 this.representedObjects.put(aliasKey,node); 93 } 94 95 return node; 96 } 97 98 public Node scalar(final String tag, final ByteList value, char style) throws IOException { 99 return representScalar(tag,value,style); 100 } 101 102 public Node representScalar(final String tag, final ByteList value, char style) throws IOException { 103 char realStyle = style == 0 ? this.defaultStyle : style; 104 return new ScalarNode(tag,value,style); 105 } 106 107 public Node seq(final String tag, final List sequence, final boolean flowStyle) throws IOException { 108 return representSequence(tag,sequence,flowStyle); 109 } 110 111 public Node representSequence(final String tag, final List sequence, final boolean flowStyle) throws IOException { 112 List value = new ArrayList (sequence.size()); 113 for(final Iterator iter = sequence.iterator();iter.hasNext();) { 114 value.add(representData(iter.next())); 115 } 116 return new SequenceNode(tag,value,flowStyle); 117 } 118 119 public Node map(final String tag, final Map mapping, final boolean flowStyle) throws IOException { 120 return representMapping(tag,mapping,flowStyle); 121 } 122 123 public Node representMapping(final String tag, final Map mapping, final boolean flowStyle) throws IOException { 124 Map value = new HashMap (); 125 for(final Iterator iter = mapping.keySet().iterator();iter.hasNext();) { 126 final Object itemKey = iter.next(); 127 final Object itemValue = mapping.get(itemKey); 128 value.put(representData(itemKey),representData(itemValue)); 129 } 130 return new MappingNode(tag,value,flowStyle); 131 } 132 133 public void represent(final Object data) throws IOException { 134 Node node = representData(data); 135 this.serializer.serialize(node); 136 this.representedObjects.clear(); 137 } 138 139 protected boolean ignoreAliases(final Object data) { 140 return false; 141 } 142 143 protected YAMLNodeCreator getNodeCreatorFor(final Object data) { 144 if(data instanceof YAMLNodeCreator) { 145 return (YAMLNodeCreator)data; 146 } else if(data instanceof Map ) { 147 return new MappingYAMLNodeCreator(data); 148 } else if(data instanceof List ) { 149 return new SequenceYAMLNodeCreator(data); 150 } else if(data instanceof Set ) { 151 return new SetYAMLNodeCreator(data); 152 } else if(data instanceof Date ) { 153 return new DateYAMLNodeCreator(data); 154 } else if(data instanceof String ) { 155 return new StringYAMLNodeCreator(data); 156 } else if(data instanceof ByteList) { 157 return new ByteListYAMLNodeCreator(data); 158 } else if(data instanceof Number ) { 159 return new NumberYAMLNodeCreator(data); 160 } else if(data instanceof Boolean ) { 161 return new ScalarYAMLNodeCreator("tag:yaml.org,2002:bool",data); 162 } else if(data == null) { 163 return new ScalarYAMLNodeCreator("tag:yaml.org,2002:null",""); 164 } else if(data.getClass().isArray()) { 165 return new ArrayYAMLNodeCreator(data); 166 } else { return new JavaBeanYAMLNodeCreator(data); 168 } 169 } 170 171 public static class DateYAMLNodeCreator implements YAMLNodeCreator { 172 private final Date data; 173 public DateYAMLNodeCreator(final Object data) { 174 this.data = (Date )data; 175 } 176 177 public String taguri() { 178 return "tag:yaml.org,2002:timestamp"; 179 } 180 181 private static DateFormat dateOutput = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss Z"); 182 private static DateFormat dateOutputUsec = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss.SSS Z"); 183 public Node toYamlNode(final Representer representer) throws IOException { 184 final Calendar c = Calendar.getInstance(); 185 c.setTime(data); 186 String out = null; 187 if(c.get(Calendar.MILLISECOND) != 0) { 188 out = dateOutputUsec.format(data); 189 } else { 190 out = dateOutput.format(data); 191 } 192 out = out.substring(0, 23) + ":" + out.substring(23); 193 return representer.scalar(taguri(), ByteList.create(out), (char)0); 194 } 195 } 196 197 public static class SetYAMLNodeCreator implements YAMLNodeCreator { 198 private final Set data; 199 public SetYAMLNodeCreator(final Object data) { 200 this.data = (Set )data; 201 } 202 203 public String taguri() { 204 return "tag:yaml.org,2002:set"; 205 } 206 207 public Node toYamlNode(final Representer representer) throws IOException { 208 final Map entries = new HashMap (); 209 for(final Iterator iter = data.iterator();iter.hasNext();) { 210 entries.put(iter.next(),null); 211 } 212 return representer.map(taguri(), entries, false); 213 } 214 } 215 216 public static class ArrayYAMLNodeCreator implements YAMLNodeCreator { 217 private final Object data; 218 public ArrayYAMLNodeCreator(final Object data) { 219 this.data = data; 220 } 221 222 public String taguri() { 223 return "tag:yaml.org,2002:seq"; 224 } 225 226 public Node toYamlNode(final Representer representer) throws IOException { 227 final int l = java.lang.reflect.Array.getLength(data); 228 final List lst = new ArrayList (l); 229 for(int i=0;i<l;i++) { 230 lst.add(java.lang.reflect.Array.get(data,i)); 231 } 232 return representer.seq(taguri(), lst, false); 233 } 234 } 235 236 public static class NumberYAMLNodeCreator implements YAMLNodeCreator { 237 private final Number data; 238 public NumberYAMLNodeCreator(final Object data) { 239 this.data = (Number )data; 240 } 241 242 public String taguri() { 243 if(data instanceof Float || data instanceof Double || data instanceof java.math.BigDecimal ) { 244 return "tag:yaml.org,2002:float"; 245 } else { 246 return "tag:yaml.org,2002:int"; 247 } 248 } 249 250 public Node toYamlNode(Representer representer) throws IOException { 251 String str = data.toString(); 252 if(str.equals("Infinity")) { 253 str = ".inf"; 254 } else if(str.equals("-Infinity")) { 255 str = "-.inf"; 256 } else if(str.equals("NaN")) { 257 str = ".nan"; 258 } 259 return representer.scalar(taguri(), ByteList.create(str), (char)0); 260 } 261 } 262 263 public static class ScalarYAMLNodeCreator implements YAMLNodeCreator { 264 private final String tag; 265 private final Object data; 266 public ScalarYAMLNodeCreator(final String tag, final Object data) { 267 this.tag = tag; 268 this.data = data; 269 } 270 271 public String taguri() { 272 return this.tag; 273 } 274 275 public Node toYamlNode(Representer representer) throws IOException { 276 return representer.scalar(taguri(), ByteList.create(data.toString()), (char)0); 277 } 278 } 279 280 public static class StringYAMLNodeCreator implements YAMLNodeCreator { 281 private final Object data; 282 public StringYAMLNodeCreator(final Object data) { 283 this.data = data; 284 } 285 286 public String taguri() { 287 if(data instanceof String ) { 288 return "tag:yaml.org,2002:str"; 289 } else { 290 return "tag:yaml.org,2002:str:"+data.getClass().getName(); 291 } 292 } 293 294 public Node toYamlNode(Representer representer) throws IOException { 295 return representer.scalar(taguri(), ByteList.create(data.toString()), (char)0); 296 } 297 } 298 299 public static class ByteListYAMLNodeCreator implements YAMLNodeCreator { 300 private final Object data; 301 public ByteListYAMLNodeCreator(final Object data) { 302 this.data = data; 303 } 304 305 public String taguri() { 306 return "tag:yaml.org,2002:str"; 307 } 308 309 public Node toYamlNode(Representer representer) throws IOException { 310 return representer.scalar(taguri(), (ByteList)data, (char)0); 311 } 312 } 313 314 public static class SequenceYAMLNodeCreator implements YAMLNodeCreator { 315 private final List data; 316 public SequenceYAMLNodeCreator(final Object data) { 317 this.data = (List )data; 318 } 319 320 public String taguri() { 321 if(data instanceof ArrayList ) { 322 return "tag:yaml.org,2002:seq"; 323 } else { 324 return "tag:yaml.org,2002:seq:"+data.getClass().getName(); 325 } 326 } 327 328 public Node toYamlNode(Representer representer) throws IOException { 329 return representer.seq(taguri(), data, false); 330 } 331 } 332 333 public static class MappingYAMLNodeCreator implements YAMLNodeCreator { 334 private final Map data; 335 public MappingYAMLNodeCreator(final Object data) { 336 this.data = (Map )data; 337 } 338 339 public String taguri() { 340 if(data instanceof HashMap ) { 341 return "tag:yaml.org,2002:map"; 342 } else { 343 return "tag:yaml.org,2002:map:"+data.getClass().getName(); 344 } 345 } 346 347 public Node toYamlNode(Representer representer) throws IOException { 348 return representer.map(taguri(), data, false); 349 } 350 } 351 352 public static class JavaBeanYAMLNodeCreator implements YAMLNodeCreator { 353 private final Object data; 354 public JavaBeanYAMLNodeCreator(final Object data) { 355 this.data = data; 356 } 357 358 public String taguri() { 359 return "!java/object:" + data.getClass().getName(); 360 } 361 362 public Node toYamlNode(Representer representer) throws IOException { 363 final Map values = new HashMap (); 364 final Method [] ems = data.getClass().getMethods(); 365 for(int i=0,j=ems.length;i<j;i++) { 366 if(ems[i].getParameterTypes().length == 0) { 367 final String name = ems[i].getName(); 368 if(name.equals("getClass")) { 369 continue; 370 } 371 String pname = null; 372 if(name.startsWith("get")) { 373 pname = "" + Character.toLowerCase(name.charAt(3)) + name.substring(4); 374 } else if(name.startsWith("is")) { 375 pname = "" + Character.toLowerCase(name.charAt(2)) + name.substring(3); 376 } 377 if(null != pname) { 378 try { 379 values.put(pname, ems[i].invoke(data,null)); 380 } catch(final Exception exe) { 381 values.put(pname, null); 382 } 383 } 384 } 385 } 386 return representer.map(taguri(),values,false); 387 } 388 } 389 390 public static void main(final String [] args) throws IOException { 391 final YAMLConfig cfg = YAML.config(); 392 final Serializer s = new SerializerImpl(new EmitterImpl(System.out,cfg),new ResolverImpl(),cfg); 393 s.open(); 394 final Representer r = new RepresenterImpl(s, cfg); 395 final Map test1 = new HashMap (); 396 final List test1Val = new LinkedList (); 397 test1Val.add("hello"); 398 test1Val.add(Boolean.TRUE); 399 test1Val.add(new Integer (31337)); 400 test1.put("val1",test1Val); 401 final List test2Val = new ArrayList (); 402 test2Val.add("hello"); 403 test2Val.add(Boolean.FALSE); 404 test2Val.add(new Integer (31337)); 405 test1.put("val2",test2Val); 406 test1.put("afsdf", "hmm"); 407 TestJavaBean bean1 = new TestJavaBean(); 408 bean1.setName("Ola"); 409 bean1.setSurName("Bini"); 410 bean1.setAge(24); 411 test1.put(new Integer (25),bean1); 412 r.represent(test1); 413 s.close(); 414 } 415 private static class TestJavaBean implements Serializable { 416 private String val1; 417 private String val2; 418 private int val3; 419 public TestJavaBean() { 420 } 421 public void setName(final String name) { 422 this.val1 = name; 423 } 424 public String getName() { 425 return this.val1; 426 } 427 428 public void setSurName(final String sname) { 429 this.val2 = sname; 430 } 431 public String getSurName() { 432 return this.val2; 433 } 434 435 public void setAge(final int age) { 436 this.val3 = age; 437 } 438 public int getAge() { 439 return this.val3; 440 } 441 } 442 } 444 | Popular Tags |