1 28 package org.jruby.yaml; 29 30 import java.util.Date ; 31 import java.util.Calendar ; 32 import java.util.HashMap ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 import java.util.Map ; 36 import java.util.Set ; 37 38 import java.util.regex.Pattern ; 39 40 import org.jvyamlb.Composer; 41 import org.jvyamlb.Constructor; 42 import org.jvyamlb.ConstructorException; 43 import org.jvyamlb.ConstructorImpl; 44 import org.jvyamlb.SafeConstructorImpl; 45 46 import org.jvyamlb.nodes.Node; 47 48 import org.jruby.Ruby; 49 import org.jruby.RubyClass; 50 import org.jruby.RubyModule; 51 import org.jruby.RubyObject; 52 import org.jruby.RubyHash; 53 import org.jruby.RubyString; 54 import org.jruby.runtime.builtin.IRubyObject; 55 56 import org.jruby.util.ByteList; 57 58 61 public class JRubyConstructor extends ConstructorImpl { 62 private final static Map yamlConstructors = new HashMap (); 63 private final static Map yamlMultiConstructors = new HashMap (); 64 private final static Map yamlMultiRegexps = new HashMap (); 65 public YamlConstructor getYamlConstructor(final Object key) { 66 return (YamlConstructor)yamlConstructors.get(key); 67 } 68 69 public YamlMultiConstructor getYamlMultiConstructor(final Object key) { 70 return (YamlMultiConstructor)yamlMultiConstructors.get(key); 71 } 72 73 public Pattern getYamlMultiRegexp(final Object key) { 74 return (Pattern )yamlMultiRegexps.get(key); 75 } 76 77 public Set getYamlMultiRegexps() { 78 return yamlMultiRegexps.keySet(); 79 } 80 81 public static void addConstructor(final String tag, final YamlConstructor ctor) { 82 yamlConstructors.put(tag,ctor); 83 } 84 85 public static void addMultiConstructor(final String tagPrefix, final YamlMultiConstructor ctor) { 86 yamlMultiConstructors.put(tagPrefix,ctor); 87 yamlMultiRegexps.put(tagPrefix,Pattern.compile("^"+tagPrefix)); 88 } 89 90 private final Ruby runtime; 91 92 public JRubyConstructor(final IRubyObject receiver, final Composer composer) { 93 super(composer); 94 this.runtime = receiver.getRuntime(); 95 } 96 97 public Object constructRubyScalar(final Node node) { 98 return RubyString.newString(runtime,(ByteList)super.constructScalar(node)); 99 } 100 101 public Object constructRubySequence(final Node node) { 102 return runtime.newArray((List )super.constructSequence(node)); 103 } 104 105 public Object constructRubyMapping(final Node node) { 106 return RubyHash.newHash(runtime,(Map )super.constructMapping(node),runtime.getNil()); 107 } 108 109 public Object constructRubyPairs(final Node node) { 110 return runtime.newArray((List )super.constructPairs(node)); 111 } 112 113 public static Object constructYamlNull(final Constructor ctor, final Node node) { 114 return ((JRubyConstructor)ctor).runtime.getNil(); 115 } 116 117 public static Object constructYamlBool(final Constructor ctor, final Node node) { 118 return SafeConstructorImpl.constructYamlBool(ctor,node) == Boolean.TRUE ? ((JRubyConstructor)ctor).runtime.getTrue() : ((JRubyConstructor)ctor).runtime.getFalse(); 119 } 120 121 public static Object constructYamlOmap(final Constructor ctor, final Node node) { 122 return ((JRubyConstructor)ctor).constructRubyPairs(node); 123 } 124 125 public static Object constructYamlPairs(final Constructor ctor, final Node node) { 126 return constructYamlOmap(ctor,node); 127 } 128 129 public static Object constructYamlSet(final Constructor ctor, final Node node) { 130 return SafeConstructorImpl.constructYamlSet(ctor,node); 131 } 132 133 public static Object constructYamlStr(final Constructor ctor, final Node node) { 134 final org.jruby.RubyString str = (org.jruby.RubyString)((JRubyConstructor)ctor).constructRubyScalar(node); 135 return (str.getValue().length() == 0 && ((org.jvyamlb.nodes.ScalarNode)node).getStyle() == 0) ? str.getRuntime().getNil() : str; 136 } 137 138 public static Object constructYamlSeq(final Constructor ctor, final Node node) { 139 return ((JRubyConstructor)ctor).constructRubySequence(node); 140 } 141 142 public static Object constructYamlMap(final Constructor ctor, final Node node) { 143 return ((JRubyConstructor)ctor).constructRubyMapping(node); 144 } 145 146 public static Object constructUndefined(final Constructor ctor, final Node node) { 147 throw new ConstructorException(null,"could not determine a constructor for the tag " + node.getTag(),null); 148 } 149 150 public static Object constructYamlTimestamp(final Constructor ctor, final Node node) { 151 return ((JRubyConstructor)ctor).runtime.newTime(((Date )SafeConstructorImpl.constructYamlTimestamp(ctor,node)).getTime()).callMethod(((JRubyConstructor)ctor).runtime.getCurrentContext(),"utc"); 152 } 153 154 public static Object constructYamlTimestampYMD(final Constructor ctor, final Node node) { 155 Date d = (Date )SafeConstructorImpl.constructYamlTimestamp(ctor,node); 156 Calendar c = Calendar.getInstance(); 157 c.setTime(d); 158 Ruby runtime = ((JRubyConstructor)ctor).runtime; 159 return runtime.getClass("Date").callMethod(runtime.getCurrentContext(),"new",new IRubyObject[]{runtime.newFixnum(c.get(Calendar.YEAR)),runtime.newFixnum(c.get(Calendar.MONTH)+1),runtime.newFixnum(c.get(Calendar.DAY_OF_MONTH)),}); 160 } 161 162 public static Object constructYamlInt(final Constructor ctor, final Node node) { 163 return ((JRubyConstructor)ctor).runtime.newFixnum(((Long )SafeConstructorImpl.constructYamlInt(ctor,node)).longValue()); 164 } 165 public static Object constructYamlFloat(final Constructor ctor, final Node node) { 166 return ((JRubyConstructor)ctor).runtime.newFloat(((Double )SafeConstructorImpl.constructYamlFloat(ctor,node)).doubleValue()); 167 } 168 public static Object constructYamlBinary(final Constructor ctor, final Node node) { 169 return ((JRubyConstructor)ctor).runtime.newString(((String )SafeConstructorImpl.constructYamlBinary(ctor,node))); 170 } 171 public static Object constructJava(final Constructor ctor, final String pref, final Node node) { 172 return SafeConstructorImpl.constructJava(ctor,pref,node); 173 } 174 public static Object constructRuby(final Constructor ctor, final String tag, final Node node) { 175 final Ruby runtime = ((JRubyConstructor)ctor).runtime; 176 RubyModule objClass = runtime.getModule("Object"); 177 if(tag != null) { 178 final String [] nms = tag.split("::"); 179 for(int i=0,j=nms.length;i<j;i++) { 180 objClass = (RubyModule)objClass.getConstant(nms[i]); 181 } 182 } 183 final RubyClass theCls = (RubyClass)objClass; 184 final RubyObject oo = (RubyObject)theCls.getAllocator().allocate(runtime, theCls); 185 final Map vars = (Map )(ctor.constructMapping(node)); 186 for(final Iterator iter = vars.keySet().iterator();iter.hasNext();) { 187 final IRubyObject key = (IRubyObject)iter.next(); 188 oo.setInstanceVariable("@" + key.toString(),(IRubyObject)vars.get(key)); 189 } 190 return oo; 191 } 192 193 public static Object constructRubyMap(final Constructor ctor, final String tag, final Node node) { 194 final Ruby runtime = ((JRubyConstructor)ctor).runtime; 195 RubyModule objClass = runtime.getModule("Object"); 196 if(tag != null) { 197 final String [] nms = tag.split("::"); 198 for(int i=0,j=nms.length;i<j;i++) { 199 objClass = (RubyModule)objClass.getConstant(nms[i]); 200 } 201 } 202 final RubyClass theCls = (RubyClass)objClass; 203 final RubyObject oo = (RubyObject)theCls.getAllocator().allocate(runtime, theCls); 204 final Map vars = (Map )(ctor.constructMapping(node)); 205 for(final Iterator iter = vars.keySet().iterator();iter.hasNext();) { 206 final IRubyObject key = (IRubyObject)iter.next(); 207 oo.callMethod(oo.getRuntime().getCurrentContext(),"[]=", new IRubyObject[]{key,(IRubyObject)vars.get(key)}); 208 } 209 return oo; 210 } 211 212 public static Object constructRubySequence(final Constructor ctor, final String tag, final Node node) { 213 final Ruby runtime = ((JRubyConstructor)ctor).runtime; 214 RubyModule objClass = runtime.getModule("Object"); 215 if(tag != null) { 216 final String [] nms = tag.split("::"); 217 for(int i=0,j=nms.length;i<j;i++) { 218 objClass = (RubyModule)objClass.getConstant(nms[i]); 219 } 220 } 221 final RubyClass theCls = (RubyClass)objClass; 222 final RubyObject oo = (RubyObject)theCls.getAllocator().allocate(runtime, theCls); 223 final List vars = (List )(ctor.constructSequence(node)); 224 for(final Iterator iter = vars.iterator();iter.hasNext();) { 225 oo.callMethod(oo.getRuntime().getCurrentContext(),"<<", new IRubyObject[]{(IRubyObject)iter.next()});; 226 } 227 return oo; 228 } 229 230 static { 231 addConstructor("tag:yaml.org,2002:null",new YamlConstructor() { 232 public Object call(final Constructor self, final Node node) { 233 return constructYamlNull(self,node); 234 } 235 }); 236 addConstructor("tag:yaml.org,2002:bool",new YamlConstructor() { 237 public Object call(final Constructor self, final Node node) { 238 return constructYamlBool(self,node); 239 } 240 }); 241 addConstructor("tag:yaml.org,2002:omap",new YamlConstructor() { 242 public Object call(final Constructor self, final Node node) { 243 return constructYamlOmap(self,node); 244 } 245 }); 246 addConstructor("tag:yaml.org,2002:pairs",new YamlConstructor() { 247 public Object call(final Constructor self, final Node node) { 248 return constructYamlPairs(self,node); 249 } 250 }); 251 addConstructor("tag:yaml.org,2002:set",new YamlConstructor() { 252 public Object call(final Constructor self, final Node node) { 253 return constructYamlSet(self,node); 254 } 255 }); 256 addConstructor("tag:yaml.org,2002:int",new YamlConstructor() { 257 public Object call(final Constructor self, final Node node) { 258 return constructYamlInt(self,node); 259 } 260 }); 261 addConstructor("tag:yaml.org,2002:float",new YamlConstructor() { 262 public Object call(final Constructor self, final Node node) { 263 return constructYamlFloat(self,node); 264 } 265 }); 266 addConstructor("tag:yaml.org,2002:timestamp",new YamlConstructor() { 267 public Object call(final Constructor self, final Node node) { 268 return constructYamlTimestamp(self,node); 269 } 270 }); 271 addConstructor("tag:yaml.org,2002:timestamp#ymd",new YamlConstructor() { 272 public Object call(final Constructor self, final Node node) { 273 return constructYamlTimestampYMD(self,node); 274 } 275 }); 276 addConstructor("tag:yaml.org,2002:str",new YamlConstructor() { 277 public Object call(final Constructor self, final Node node) { 278 return constructYamlStr(self,node); 279 } 280 }); 281 addConstructor("tag:yaml.org,2002:binary",new YamlConstructor() { 282 public Object call(final Constructor self, final Node node) { 283 return constructYamlBinary(self,node); 284 } 285 }); 286 addConstructor("tag:yaml.org,2002:seq",new YamlConstructor() { 287 public Object call(final Constructor self, final Node node) { 288 return constructYamlSeq(self,node); 289 } 290 }); 291 addConstructor("tag:yaml.org,2002:map",new YamlConstructor() { 292 public Object call(final Constructor self, final Node node) { 293 return constructYamlMap(self,node); 294 } 295 }); 296 addConstructor(null,new YamlConstructor() { 297 public Object call(final Constructor self, final Node node) { 298 return self.constructPrivateType(node); 299 } 300 }); 301 addMultiConstructor("tag:yaml.org,2002:map:",new YamlMultiConstructor() { 302 public Object call(final Constructor self, final String pref, final Node node) { 303 return constructRubyMap(self,pref,node); 304 } 305 }); 306 addMultiConstructor("tag:yaml.org,2002:seq:",new YamlMultiConstructor() { 307 public Object call(final Constructor self, final String pref, final Node node) { 308 return constructRubySequence(self,pref,node); 309 } 310 }); 311 addMultiConstructor("tag:yaml.org,2002:ruby/object:",new YamlMultiConstructor() { 312 public Object call(final Constructor self, final String pref, final Node node) { 313 return constructRuby(self,pref,node); 314 } 315 }); 316 addMultiConstructor("tag:yaml.org,2002:java/object:",new YamlMultiConstructor() { 317 public Object call(final Constructor self, final String pref, final Node node) { 318 return constructJava(self,pref,node); 319 } 320 }); 321 } 322 } 324 | Popular Tags |