ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Poitras Christian" <Christian.Poit...@ircm.qc.ca>
Subject Re: Nested iterate tags
Date Thu, 30 Mar 2006 16:36:15 GMT
I've in front of this problem myself.
It seems that in a future version of iBatis, this bug will be corrected
by adding a "var" attribute in iterate tag.
 
If you wan't a patch to apply now, here's how I modified the code from
iBatis.
(you most likely downloaded the source code with the binary)
 
I can send a patch to someone who ask (in a .jar file replacing
ibatis-sqlmap-2.jar), but I would prefer that someone makes a real
modification to the framework. I have an idea of how things should be
changed to support nested iterate in a proper way.
 
To use my patch, do the following.
<iterate property="list">
    table.someFiled = #list[].value#
    <iterate property="list[].list">
        table.narrowField = #list[].list[].value#
    </iterate>
</iterate>
 
 
Please note that this modification was made on the iBatis 2.1.7.
A bug still remains in my modifcations. I can make a new patch if anyone
asks. This bug will make iBatis crash in this case.
<iterate property="list">
    <iterate property="list[].list">
        <!-- suppose here you always want the value of element 4 in
first list>
        table.field = #list[4].list[].value#
    </iterate>
</iterate>
 
 
 
// Mofications made to 3 files. Modifcations begin with comment "//
Added code" and ends with "// End of added code". Some code is replaced
to surrunded by "// Replaced code" and "// End of replaced code"
// classes modified :
com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSQL,
com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.IterateTagHandler,
com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.ConditionnalTagHan
dler
 
 
In com.ibatis.sqlmap.engine.mapping.sql.dynamic.DynamicSQL
 
  protected void iteratePropertyReplace(StringBuffer bodyContent,
IterateContext iterate) {
    if(iterate!=null) {
      String find = iterate.getProperty() + "[]";
      // Added code.
      find = find.replaceAll("\\[\\d+\\]", "[]");
      // End of added code.
      String replace = iterate.getProperty() + "[" + iterate.getIndex()
+ "]";
      replace(bodyContent, find, replace);
    }
  }
  private void processBodyChildren(RequestScope request, SqlTagContext
ctx, Object parameterObject, Iterator localChildren, PrintWriter out) {
    while (localChildren.hasNext()) {
      SqlChild child = (SqlChild) localChildren.next();
      if (child instanceof SqlText) {
        SqlText sqlText = (SqlText) child;
        String sqlStatement = sqlText.getText();
        if (sqlText.isWhiteSpace()) {
          out.print(sqlStatement);
        } else if (!sqlText.isPostParseRequired()) {
 
          // BODY OUT
          out.print(sqlStatement);
 
          ParameterMapping[] mappings = sqlText.getParameterMappings();
          if (mappings != null) {
            for (int i = 0, n = mappings.length; i < n; i++) {
              ctx.addParameterMapping(mappings[i]);
            }
          }
        } else {
 
          IterateContext itCtx = ctx.peekIterateContext();
 
          if(null != itCtx && itCtx.isAllowNext()){
            itCtx.next();
            itCtx.setAllowNext(false);
            if(!itCtx.hasNext()) {
              itCtx.setFinal(true);
            }
          }
 
          if(itCtx!=null) {
            StringBuffer sqlStatementBuffer = new
StringBuffer(sqlStatement);
            iteratePropertyReplace(sqlStatementBuffer, itCtx);
            sqlStatement = sqlStatementBuffer.toString();
          }
 
          sqlText =
PARAM_PARSER.parseInlineParameterMap(delegate.getTypeHandlerFactory(),
sqlStatement);
 
          ParameterMapping[] mappings = sqlText.getParameterMappings();
          out.print(sqlText.getText());
          if (mappings != null) {
             for (int i = 0, n = mappings.length; i < n; i++) {
               ctx.addParameterMapping(mappings[i]);
             }
          }
        }
      } else if (child instanceof SqlTag) {
        SqlTag tag = (SqlTag) child;
        SqlTagHandler handler = tag.getHandler();
        int response = SqlTagHandler.INCLUDE_BODY;
        do {
          StringWriter sw = new StringWriter();
          PrintWriter pw = new PrintWriter(sw);
          
          response = handler.doStartFragment(ctx, tag, parameterObject);
          if (response != SqlTagHandler.SKIP_BODY) {
 
            processBodyChildren(request, ctx, parameterObject,
tag.getChildren(), pw);
            pw.flush();
            pw.close();
            StringBuffer body = sw.getBuffer();
            response = handler.doEndFragment(ctx, tag, parameterObject,
body);
            handler.doPrepend(ctx, tag, parameterObject, body);
            
            if (response != SqlTagHandler.SKIP_BODY) {
              if (body.length() > 0) {
                out.print(body.toString());
              }
            }
 
          }
        } while (response == SqlTagHandler.REPEAT_BODY);
 
        ctx.popRemoveFirstPrependMarker(tag);
 
        if(ctx.peekIterateContext()!= null &&
ctx.peekIterateContext().getTag() == tag) {
            // Added code.
            ctx.setAttribute(ctx.peekIterateContext().getTag(), null);
            // End of added code.
          ctx.popIterateContext();
        }
 
      }
    }
  }
 
 
 

In
com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.IterateTagHandler
 
  public int doStartFragment(SqlTagContext ctx, SqlTag tag, Object
parameterObject) {
    IterateContext iterate = (IterateContext) ctx.getAttribute(tag);
    if (iterate == null) {
      
      ctx.pushRemoveFirstPrependMarker(tag);
      
      Object collection;
      String prop = tag.getPropertyAttr();
      if (prop != null) {
          // Added code.
          {
              // Increase index if the first tag is another iterate.
              IterateContext itCtx = ctx.peekIterateContext();
              if(null != itCtx && itCtx.isAllowNext()){
                  itCtx.next();
                  itCtx.setAllowNext(false);
                  if(!itCtx.hasNext()) {
                      itCtx.setFinal(true);
                  }
              }
          }
          SqlTag parentTag = tag.getParent();
          int listIndex = prop.lastIndexOf('[');
          while (listIndex > -1) {
              if (Character.isDigit(prop.charAt(listIndex + 1))) {
                  // Skip to next list.
                  if (listIndex > 0) {
                      listIndex = prop.lastIndexOf('[', listIndex - 1);
                  }
                  else {
                      listIndex = -1;
                  }
              }
              else {
                  // Add iteration number to property.
                  Object parentContext = ctx.getAttribute(parentTag);
                  while (!(parentContext instanceof IterateContext)) {
                      parentTag = parentTag.getParent();
                      parentContext = ctx.getAttribute(parentTag);
                  }
                  IterateContext parentIterateContext = (IterateContext)
parentContext;
                  prop = prop.substring(0, listIndex + 1) +
parentIterateContext.getIndex() + prop.substring(listIndex + 1);
                  // Skip to next list.
                  if (listIndex > 0) {
                      listIndex = prop.lastIndexOf('[', listIndex - 1);
                  }
                  else {
                      listIndex = -1;
                  }
                  parentTag = parentTag.getParent();
              }
          }
          // End of added code.
        collection = PROBE.getObject(parameterObject, prop);
      } else {
        collection = parameterObject;
      }
      iterate = new IterateContext(collection,tag);
      
      iterate.setProperty( null == prop ? "" : prop );
      
      ctx.setAttribute(tag, iterate);
      ctx.pushIterateContext(iterate);
    }
    if (iterate != null && iterate.hasNext()) {
      return INCLUDE_BODY;
    } else {
      return SKIP_BODY;
    }
  }
 
 
 

In
com.ibatis.sqlmap.engine.mapping.sql.dynamic.elements.ConditionnalTagHan
dler
  protected long compare(SqlTagContext ctx, SqlTag tag, Object
parameterObject) {
    String propertyName = tag.getPropertyAttr();
    String comparePropertyName = tag.getComparePropertyAttr();
    String compareValue = tag.getCompareValueAttr();
 
    String prop = tag.getPropertyAttr();
    Object value1;
    Class type;
    IterateContext itCtx = ctx.peekIterateContext();
 
    if (prop != null) {
 
      if(null != itCtx && itCtx.isAllowNext()){
        itCtx.next();
        itCtx.setAllowNext(false);
        if(!itCtx.hasNext()) {
          itCtx.setFinal(true);
        }
      }
 
      if(prop.indexOf(START_INDEX) > -1) {
          // Replaced code.
          propertyName = new StringBuffer(propertyName).insert(
 
propertyName.lastIndexOf(END_INDEX),itCtx.getIndex()).toString();
          // End of replaced code.
          // Added code.
          SqlTag parentTag = itCtx.getTag().getParent();
          int listIndex = propertyName.lastIndexOf('[');
          while (listIndex > -1) {
              if (Character.isDigit(propertyName.charAt(listIndex + 1)))
{
                  // Skip to next list.
                  if (listIndex > 0) {
                      listIndex = propertyName.lastIndexOf('[',
listIndex - 1);
                  }
                  else {
                      listIndex = -1;
                  }
              }
              else {
                  // Add iteration number to property.
                  Object parentContext = ctx.getAttribute(parentTag);
                  while (!(parentContext instanceof IterateContext)) {
                      parentTag = parentTag.getParent();
                      parentContext = ctx.getAttribute(parentTag);
                  }
                  IterateContext parentIterateContext = (IterateContext)
parentContext;
                  propertyName = propertyName.substring(0, listIndex +
1) + parentIterateContext.getIndex() + propertyName.substring(listIndex
+ 1);
                  // Skip to next list.
                  if (listIndex > 0) {
                      listIndex = propertyName.lastIndexOf('[',
listIndex - 1);
                  }
                  else {
                      listIndex = -1;
                  }
                  parentTag = parentTag.getParent();
              }
          }
          // End of added code.
      }
 
      value1 = PROBE.getObject(parameterObject, propertyName);
      type = PROBE.getPropertyTypeForGetter(parameterObject,
propertyName);
    } else {
      value1 = parameterObject;
      if (value1 != null) {
        type = parameterObject.getClass();
      } else {
        type = Object.class;
      }
    }
    if (comparePropertyName != null) {
      Object value2 = PROBE.getObject(parameterObject,
comparePropertyName);
      return compareValues(type, value1, value2);
    } else if (compareValue != null) {
      return compareValues(type, value1, compareValue);
    } else {
      throw new NestedRuntimeException("Error comparing in conditional
fragment.  Uknown 'compare to' values.");
    }
  }


Mime
View raw message