1 28 package org.jvyamlb; 29 30 import java.io.IOException ; 31 32 import java.text.MessageFormat ; 33 34 import java.util.Iterator ; 35 import java.util.List ; 36 import java.util.Map ; 37 import java.util.HashMap ; 38 import java.util.Set ; 39 import java.util.HashSet ; 40 41 import org.jvyamlb.events.AliasEvent; 42 import org.jvyamlb.events.DocumentEndEvent; 43 import org.jvyamlb.events.DocumentStartEvent; 44 import org.jvyamlb.events.ScalarEvent; 45 import org.jvyamlb.events.MappingEndEvent; 46 import org.jvyamlb.events.MappingStartEvent; 47 import org.jvyamlb.events.SequenceEndEvent; 48 import org.jvyamlb.events.SequenceStartEvent; 49 import org.jvyamlb.events.StreamEndEvent; 50 import org.jvyamlb.events.StreamStartEvent; 51 52 import org.jvyamlb.nodes.Node; 53 import org.jvyamlb.nodes.CollectionNode; 54 import org.jvyamlb.nodes.MappingNode; 55 import org.jvyamlb.nodes.ScalarNode; 56 import org.jvyamlb.nodes.SequenceNode; 57 58 import org.jruby.util.ByteList; 59 60 63 public class SerializerImpl implements Serializer { 64 private Emitter emitter; 65 private Resolver resolver; 66 private YAMLConfig options; 67 private boolean useExplicitStart; 68 private boolean useExplicitEnd; 69 private int[] useVersion; 70 private boolean useTags; 71 private String anchorTemplate; 72 private Set serializedNodes; 73 private Map anchors; 74 private int lastAnchorId; 75 private boolean closed; 76 private boolean opened; 77 78 public SerializerImpl(final Emitter emitter, final Resolver resolver, final YAMLConfig opts) { 79 this.emitter = emitter; 80 this.resolver = resolver; 81 this.options = opts; 82 this.useExplicitStart = opts.explicitStart(); 83 this.useExplicitEnd = opts.explicitEnd(); 84 int[] version = new int[2]; 85 if(opts.useVersion()) { 86 final String v1 = opts.version(); 87 final int index = v1.indexOf('.'); 88 version[0] = Integer.parseInt(v1.substring(0,index)); 89 version[1] = Integer.parseInt(v1.substring(index+1)); 90 } else { 91 version = null; 92 } 93 this.useVersion = version; 94 this.useTags = opts.useHeader(); 95 this.anchorTemplate = opts.anchorFormat() == null ? "id{0,number,####}" : opts.anchorFormat(); 96 this.serializedNodes = new HashSet (); 97 this.anchors = new HashMap (); 98 this.lastAnchorId = 0; 99 this.closed = false; 100 this.opened = false; 101 } 102 103 protected boolean ignoreAnchor(final Node node) { 104 return false; 105 } 106 107 public void open() throws IOException { 108 if(!closed && !opened) { 109 this.emitter.emit(new StreamStartEvent()); 110 this.opened = true; 111 } else if(closed) { 112 throw new SerializerException("serializer is closed"); 113 } else { 114 throw new SerializerException("serializer is already opened"); 115 } 116 } 117 118 public void close() throws IOException { 119 if(!opened) { 120 throw new SerializerException("serializer is not opened"); 121 } else if(!closed) { 122 this.emitter.emit(new StreamEndEvent()); 123 this.closed = true; 124 this.opened = false; 125 } 126 } 127 128 public void serialize(final Node node) throws IOException { 129 if(!this.closed && !this.opened) { 130 throw new SerializerException("serializer is not opened"); 131 } else if(this.closed) { 132 throw new SerializerException("serializer is closed"); 133 } 134 this.emitter.emit(new DocumentStartEvent(this.useExplicitStart,this.useVersion,null)); 135 anchorNode(node); 136 serializeNode(node,null,null); 137 this.emitter.emit(new DocumentEndEvent(this.useExplicitEnd)); 138 this.serializedNodes = new HashSet (); 139 this.anchors = new HashMap (); 140 this.lastAnchorId = 0; 141 } 142 143 private void anchorNode(final Node node) { 144 if(!ignoreAnchor(node)) { 145 if(this.anchors.containsKey(node)) { 146 String anchor = (String )this.anchors.get(node); 147 if(null == anchor) { 148 anchor = generateAnchor(node); 149 this.anchors.put(node,anchor); 150 } 151 } else { 152 this.anchors.put(node,null); 153 if(node instanceof SequenceNode) { 154 for(final Iterator iter = ((List )node.getValue()).iterator();iter.hasNext();) { 155 anchorNode((Node)iter.next()); 156 } 157 } else if(node instanceof MappingNode) { 158 final Map value = (Map )node.getValue(); 159 for(final Iterator iter = value.keySet().iterator();iter.hasNext();) { 160 final Node key = (Node)iter.next(); 161 anchorNode(key); 162 anchorNode((Node)value.get(key)); 163 } 164 } 165 } 166 } 167 } 168 169 private String generateAnchor(final Node node) { 170 this.lastAnchorId++; 171 return new MessageFormat (this.anchorTemplate).format(new Object []{new Integer (this.lastAnchorId)}); 172 } 173 174 private void serializeNode(final Node node, final Node parent, final Object index) throws IOException { 175 final String tAlias = (String )this.anchors.get(node); 176 if(this.serializedNodes.contains(node) && tAlias != null) { 177 this.emitter.emit(new AliasEvent(tAlias)); 178 } else { 179 this.serializedNodes.add(node); 180 this.resolver.descendResolver(parent,index); 181 if(node instanceof ScalarNode) { 182 final String detectedTag = this.resolver.resolve(ScalarNode.class,(ByteList)node.getValue(),new boolean[]{true,false}); 183 final String defaultTag = this.resolver.resolve(ScalarNode.class,(ByteList)node.getValue(),new boolean[]{false,true}); 184 final boolean[] implicit = new boolean[] {false,false}; 185 if(!options.explicitTypes()) { 186 implicit[0] = node.getTag().equals(detectedTag); 187 implicit[1] = node.getTag().equals(defaultTag); 188 } 189 this.emitter.emit(new ScalarEvent(tAlias,node.getTag(),implicit,(ByteList)node.getValue(),((ScalarNode)node).getStyle())); 190 } else if(node instanceof SequenceNode) { 191 final boolean implicit = !options.explicitTypes() && (node.getTag().equals(this.resolver.resolve(SequenceNode.class,null,new boolean[]{true,true}))); 192 this.emitter.emit(new SequenceStartEvent(tAlias,node.getTag(),implicit,((CollectionNode)node).getFlowStyle())); 193 int ix = 0; 194 for(final Iterator iter = ((List )node.getValue()).iterator();iter.hasNext();) { 195 serializeNode((Node)iter.next(),node,new Integer (ix++)); 196 } 197 this.emitter.emit(new SequenceEndEvent()); 198 } else if(node instanceof MappingNode) { 199 final boolean implicit = !options.explicitTypes() && (node.getTag().equals(this.resolver.resolve(MappingNode.class,null,new boolean[]{true,true}))); 200 this.emitter.emit(new MappingStartEvent(tAlias,node.getTag(),implicit,((CollectionNode)node).getFlowStyle())); 201 final Map value = (Map )node.getValue(); 202 for(final Iterator iter = value.keySet().iterator();iter.hasNext();) { 203 final Node key = (Node)iter.next(); 204 serializeNode(key,node,null); 205 serializeNode((Node)value.get(key),node,key); 206 } 207 this.emitter.emit(new MappingEndEvent()); 208 } 209 } 210 } 211 } | Popular Tags |