docs: @JRubyMethod
      public static IRubyObject transfer(IRubyObject self, IRubyObject type, IRubyObject val) {
          final Ruby runtime = self.getRuntime();
          ThreadContext ctx = runtime.getCurrentContext();
          if(type.isNil() || type.convertToString().getByteList().realSize == 0) {
              type = self.callMethod(ctx, "detect_implicit", val);
          }
              
          if(!(type.isNil() || type.convertToString().getByteList().realSize == 0)) {
              IRubyObject colon = runtime.newString(":");
              IRubyObject tags = self.callMethod(ctx, "tags");
              IRubyObject target_class = ((RubyHash)tags).op_aref(ctx, type);
              IRubyObject subclass = target_class;
              IRubyObject obj = runtime.getNil();
                  
              if(target_class.isNil()) {
                  RubyArray subclass_parts = runtime.newArray();
                  RubyArray parts = ((RubyString)type).split(ctx, colon);
                  while(parts.getLength() > 1) {
                      subclass_parts.unshift(parts.pop(ctx));
                      IRubyObject partial = parts.join(ctx, colon);
                      target_class = ((RubyHash)tags).op_aref(ctx, partial);
                      if(target_class.isNil()) {
                          ((RubyString)partial).append(colon);
                          target_class = ((RubyHash)tags).op_aref(ctx, partial);
                      }
                      if(!target_class.isNil()) {
                          subclass = target_class;
                          if(subclass_parts.getLength() > 0 && target_class.respondsTo("yaml_tag_subclasses?") && target_class.callMethod(ctx, "yaml_tag_subclasses?").isTrue()) {
                              subclass = subclass_parts.join(ctx, colon);
                              subclass = target_class.callMethod(ctx, "yaml_tag_read_class", subclass);
                              IRubyObject subclass_v = const_find(self, subclass);
                              if(subclass_v != runtime.getNil()) {
                                  subclass = subclass_v;
                              } else if(target_class == runtime.getObject() && subclass_v == runtime.getNil()) {
                                  target_class = ((RubyModule)runtime.getModule("YAML")).getConstant("Object");
                                  type = subclass;
                                  subclass = target_class;
                              } else {
                                  throw runtime.newTypeError("invalid subclass");
                              }
                          }
                          break;
                      }
                  }
              }
  
              if(target_class.respondsTo("call")) {
                  obj = target_class.callMethod(ctx, "call", new IRubyObject[]{type, val});
              } else {
                  if(target_class.respondsTo("yaml_new")) {
                      obj = target_class.callMethod(ctx, "yaml_new", new IRubyObject[]{subclass, type, val});
                  } else if(!target_class.isNil()) {
                      if(subclass == runtime.getBignum()) {
                          obj = RubyNumeric.str2inum(runtime, val.convertToString(), 10);
                      } else {
                          obj = ((RubyClass)subclass).allocate();
                      }
                          
                      if(obj.respondsTo("yaml_initialize")) {
                          obj.callMethod(ctx, "yaml_initialize", new IRubyObject[]{type, val});
                      } else if(!obj.isNil() && val instanceof RubyHash) {
                          final IRubyObject _obj = obj;
                          final IRubyObject _val = val;
                          RubyEnumerable.callEach(runtime, ctx, val, new BlockCallback() {
                                  public IRubyObject call(ThreadContext _ctx, IRubyObject[] largs, Block blk) {
                                      IRubyObject ivname = ((RubyArray)largs[0]).entry(0);
                                      String ivn = "@" + ivname.convertToString().toString();
                                      IRubyObject valueToSet = ((RubyArray)largs[0]).entry(1);
                                      if(valueToSet instanceof PossibleLinkNode) {
                                          List<StorageLink> sls = ((PossibleLinkNode)valueToSet).getLinks();
                                          for(int i=0, j=sls.size(); i<j; i++) {
                                              StorageLink sl = sls.get(i);
                                              if(sl instanceof HashStorageLink) {
                                                  if(((HashStorageLink)sl).hash == _val) {
                                                      sls.set(i, new ObjectStorageLink(_obj, ivn, valueToSet));
                                                  }
                                              }
                                          }
                                      }
                                      _obj.getInstanceVariables().setInstanceVariable(ivn, valueToSet);
                                      return runtime.getNil();
                                  }
                              });
                      }
                  } else {
                      RubyArray parts = ((RubyString)type).split(ctx, colon);
                      IRubyObject scheme = parts.shift(ctx);
                      if(scheme.convertToString().toString().equals("x-private")) {
                          IRubyObject name = parts.join(ctx, colon);
                          obj = ((RubyModule)((RubyModule)runtime.getModule("YAML")).getConstant("Yecht")).getConstant("PrivateType").callMethod(ctx, "new", new IRubyObject[]{name, val});
                      } else {
                          IRubyObject domain = parts.shift(ctx);
                          IRubyObject name = parts.join(ctx, colon);
                          obj = ((RubyModule)((RubyModule)runtime.getModule("YAML")).getConstant("Yecht")).getConstant("DomainType").callMethod(ctx, "new", new IRubyObject[]{domain, name, val});
                      }
                  }
              }
                  
              val = obj;
          }
  
          return val;
  
      }