ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Brandon Goodin" <brandon.goo...@gmail.com>
Subject Re: Nested iterate tags
Date Fri, 31 Mar 2006 14:25:59 GMT
Is there a JIRA issue associated with this? I'll be happy to look at
it over the weekend.

On 3/30/06, Poitras Christian <Christian.Poitras@ircm.qc.ca> wrote:
> 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