Source for gnu.xml.transform.Bindings

   1: /* Bindings.java -- 
   2:    Copyright (C) 2004 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.xml.transform;
  39: 
  40: import java.util.Collection;
  41: import java.util.Collections;
  42: import java.util.HashMap;
  43: import java.util.HashSet;
  44: import java.util.Iterator;
  45: import java.util.LinkedList;
  46: import java.util.Map;
  47: import javax.xml.namespace.QName;
  48: import javax.xml.xpath.XPathVariableResolver;
  49: import org.w3c.dom.Node;
  50: 
  51: /**
  52:  * The set of variable bindings in effect for a stylesheet.
  53:  *
  54:  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  55:  */
  56: public class Bindings
  57:   implements XPathVariableResolver, Cloneable
  58: {
  59: 
  60:   static final int VARIABLE = 0;
  61:   static final int PARAM = 1;
  62:   static final int WITH_PARAM = 2;
  63: 
  64:   final Stylesheet stylesheet;
  65: 
  66:   /**
  67:    * Global variables.
  68:    */
  69:   final LinkedList variables;
  70: 
  71:   /**
  72:    * Parameter value stack.
  73:    */
  74:   final LinkedList parameters;
  75: 
  76:   /**
  77:    * Argument (with-param) value stack.
  78:    */
  79:   final LinkedList withParameters;
  80: 
  81:   Bindings(Stylesheet stylesheet)
  82:   {
  83:     this.stylesheet = stylesheet;
  84:     variables = new LinkedList();
  85:     parameters = new LinkedList();
  86:     withParameters = new LinkedList();
  87:     for (int i = 0; i < 3; i++)
  88:       {
  89:         push(i);
  90:       }
  91:   }
  92: 
  93:   public Object clone()
  94:   {
  95:     try
  96:       {
  97:         return (Bindings) super.clone();
  98:       }
  99:     catch (CloneNotSupportedException e)
 100:       {
 101:         throw new Error(e.getMessage());
 102:       }
 103:   }
 104: 
 105:   void push(int type)
 106:   {
 107:     switch (type)
 108:       {
 109:       case VARIABLE:
 110:         variables.addFirst(new HashMap());
 111:         break;
 112:       case PARAM:
 113:         parameters.addFirst(new HashMap());
 114:         break;
 115:       case WITH_PARAM:
 116:         withParameters.addFirst(new HashMap());
 117:         break;
 118:       }
 119:   }
 120: 
 121:   void pop(int type)
 122:   {
 123:     switch (type)
 124:       {
 125:       case VARIABLE:
 126:         variables.removeFirst();
 127:         break;
 128:       case PARAM:
 129:         parameters.removeFirst();
 130:         break;
 131:       case WITH_PARAM:
 132:         withParameters.removeFirst();
 133:         break;
 134:       }
 135:   }
 136: 
 137:   public boolean containsKey(QName name, int type)
 138:   {
 139:     Iterator i = null;
 140:     switch (type)
 141:       {
 142:       case VARIABLE:
 143:         i = variables.iterator();
 144:         break;
 145:       case PARAM:
 146:         i = parameters.iterator();
 147:         break;
 148:       case WITH_PARAM:
 149:         Map ctx = (Map) withParameters.getFirst();
 150:         return ctx.containsKey(name);
 151:       }
 152:     if (i != null)
 153:       {
 154:         while (i.hasNext())
 155:           {
 156:             Map ctx = (Map) i.next();
 157:             if (ctx.containsKey(name))
 158:               {
 159:                 return true;
 160:               }
 161:           }
 162:       }
 163:     return false;
 164:   }
 165: 
 166:   public Object get(QName name, Node context, int pos, int len)
 167:   {
 168:     //System.err.println("bindings.get: "+name);
 169:     //System.err.println("\t"+toString());
 170:     Object ret = null;
 171:     //if (parameters.size() > 1 && containsKey(name, PARAM))
 172:       // check that template defines parameter
 173:       {
 174:         Map cwp = (Map) withParameters.getFirst();
 175:         ret = cwp.get(name);
 176:         //System.err.println("\twith-param: ret="+ret);
 177:       }
 178:     if (ret == null)
 179:       {
 180:         for (Iterator i = variables.iterator(); i.hasNext() && ret == null; )
 181:           {
 182:             Map vctx = (Map) i.next();
 183:             ret = vctx.get(name);
 184:           }
 185:         //System.err.println("\tvariable: ret="+ret);
 186:       }
 187:     if (ret == null)
 188:       {
 189:         for (Iterator i = parameters.iterator(); i.hasNext() && ret == null; )
 190:           {
 191:             Map pctx = (Map) i.next();
 192:             ret = pctx.get(name);
 193:           }
 194:         //System.err.println("\tparam: ret="+ret);
 195:       }
 196:     /*if (ret instanceof Expr && context != null)
 197:       {
 198:         Expr expr = (Expr) ret;
 199:         ret = expr.evaluate(context, 1, 1);
 200:       }*/
 201:     if (ret instanceof Node)
 202:       {
 203:         ret = Collections.singleton(ret);
 204:       }
 205:     if (ret == null)
 206:       {
 207:         ret = "";
 208:       }
 209:     //System.err.println("\tret="+ret);
 210:     return ret;
 211:   }
 212: 
 213:   void set(QName name, Object value, int type)
 214:   {
 215:     switch (type)
 216:       {
 217:       case VARIABLE:
 218:         Map vctx = (Map) variables.getFirst();
 219:         vctx.put(name, value);
 220:         break;
 221:       case PARAM:
 222:         Map pctx = (Map) parameters.getFirst();
 223:         pctx.put(name, value);
 224:         break;
 225:       case WITH_PARAM:
 226:         Map wctx = (Map) withParameters.getFirst();
 227:         wctx.put(name, value);
 228:         break;
 229:       }
 230:     //System.err.println("Set "+name+"="+value);
 231:   }
 232: 
 233:   public Object resolveVariable(QName qName)
 234:   {
 235:     return get(qName, null, 1, 1);
 236:   }
 237:   
 238:   public String toString()
 239:   {
 240:     StringBuffer buf = new StringBuffer();
 241:     boolean next = false;
 242:     Collection seen = new HashSet();
 243:     Map wctx = (Map) withParameters.getFirst();
 244:     buf.append('(');
 245:     for (Iterator i = wctx.entrySet().iterator(); i.hasNext(); )
 246:       {
 247:         if (next)
 248:           {
 249:             buf.append(',');
 250:           }
 251:         else
 252:           {
 253:             next = true;
 254:           }
 255:         Map.Entry entry = (Map.Entry) i.next();
 256:         Object key = entry.getKey();
 257:         if (!seen.contains(key))
 258:           {
 259:             buf.append(key);
 260:             buf.append('=');
 261:             buf.append(entry.getValue());
 262:             seen.add(key);
 263:           }
 264:       }
 265:     buf.append(')');
 266:     next = false;
 267:     seen.clear();
 268:     buf.append('{');
 269:     for (Iterator i = variables.iterator(); i.hasNext(); )
 270:       {
 271:         Map ctx = (Map) i.next();
 272:         for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
 273:           {
 274:             if (next)
 275:               {
 276:                 buf.append(',');
 277:               }
 278:             else
 279:               {
 280:                 next = true;
 281:               }
 282:             Map.Entry entry = (Map.Entry) j.next();
 283:             Object key = entry.getKey();
 284:             if (!seen.contains(key))
 285:               {
 286:                 buf.append(key);
 287:                 buf.append('=');
 288:                 buf.append(entry.getValue());
 289:                 seen.add(key);
 290:               }
 291:           } 
 292:       }
 293:     buf.append('}');
 294:     next = false;
 295:     seen.clear();
 296:     buf.append('[');
 297:     for (Iterator i = parameters.iterator(); i.hasNext(); )
 298:       {
 299:         Map ctx = (Map) i.next();
 300:         for (Iterator j = ctx.entrySet().iterator(); j.hasNext(); )
 301:           {
 302:             if (next)
 303:               {
 304:                 buf.append(',');
 305:               }
 306:             else
 307:               {
 308:                 next = true;
 309:               }
 310:             Map.Entry entry = (Map.Entry) j.next();
 311:             Object key = entry.getKey();
 312:             if (!seen.contains(key))
 313:               {
 314:                 buf.append(key);
 315:                 buf.append('=');
 316:                 buf.append(entry.getValue());
 317:                 seen.add(key);
 318:               }
 319:           } 
 320:       }
 321:     buf.append(']');
 322:     return buf.toString();
 323:   }
 324: 
 325: }