Home » xmlbeans-2.5.0-src » org.apache » xmlbeans » soap » [javadoc | source]

    1   /*   Copyright 2004 The Apache Software Foundation
    2    *
    3    *   Licensed under the Apache License, Version 2.0 (the "License");
    4    *   you may not use this file except in compliance with the License.
    5    *   You may obtain a copy of the License at
    6    *
    7    *       http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    *   Unless required by applicable law or agreed to in writing, software
   10    *   distributed under the License is distributed on an "AS IS" BASIS,
   11    *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12    *   See the License for the specific language governing permissions and
   13    *  limitations under the License.
   14    */
   15   
   16   package org.apache.xmlbeans.soap;
   17   
   18   import javax.xml.namespace.QName;
   19   
   20   import java.util.ArrayList;
   21   import java.util.List;
   22   import java.util.Iterator;
   23   
   24   import org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException;
   25   import org.apache.xmlbeans.impl.common.XmlWhitespace;
   26   import org.apache.xmlbeans.impl.common.QNameHelper;
   27   import org.apache.xmlbeans.impl.common.PrefixResolver;
   28   
   29   public final class SOAPArrayType
   30   {
   31       // Example foo:bar[,][][,,][7,9]
   32       // -> _type = QName(foo:bar)
   33       // -> _ranks = {2,1,3}
   34       // -> _dimensions = {7,9}
   35       private QName _type;
   36       private int[] _ranks; // if ranks is empty, it means there are no nested arrays
   37       private int[] _dimensions; // Any dimension can be -1 to indicate "any".
   38   
   39       /**
   40        * True if the ranks for the passed SOAPArrayType
   41        * are equal to this one.
   42        *
   43        * Does NOT compare the _type fields.
   44        */
   45       public boolean isSameRankAs(SOAPArrayType otherType)
   46       {
   47           if (_ranks.length != otherType._ranks.length)
   48               return false;
   49           for (int i = 0; i < _ranks.length; i++)
   50           {
   51               if (_ranks[i] != otherType._ranks[i])
   52                   return false;
   53           }
   54           if (_dimensions.length != otherType._dimensions.length)
   55               return false;
   56           return true;
   57       }
   58   
   59       /**
   60        * Given SOAP 1.1-formatted index string, returns an array
   61        * index.  For example, given "[4,3,5]", returns an int array
   62        * containing 4, 3, and 5.
   63        */
   64       public static int[] parseSoap11Index(String inbraces)
   65       {
   66           inbraces = XmlWhitespace.collapse(inbraces, XmlWhitespace.WS_COLLAPSE);
   67           if (!inbraces.startsWith("[") || !inbraces.endsWith("]"))
   68               throw new IllegalArgumentException("Misformed SOAP 1.1 index: must be contained in braces []");
   69           return internalParseCommaIntString(inbraces.substring(1, inbraces.length() - 1));
   70       }
   71   
   72       private static int[] internalParseCommaIntString(String csl)
   73       {
   74           List dimStrings = new ArrayList();
   75           int i = 0;
   76           for (;;)
   77           {
   78               int j = csl.indexOf(',', i);
   79               if (j < 0)
   80               {
   81                   dimStrings.add(csl.substring(i));
   82                   break;
   83               }
   84               dimStrings.add(csl.substring(i, j));
   85               i = j + 1;
   86           }
   87   
   88           int[] result = new int[dimStrings.size()];
   89           i = 0;
   90           for (Iterator it = dimStrings.iterator(); it.hasNext(); i++)
   91           {
   92               String dimString = XmlWhitespace.collapse((String)it.next(), XmlWhitespace.WS_COLLAPSE);
   93               if (dimString.equals("*") || dimString.equals(""))
   94               {
   95                   result[i] = -1;
   96               }
   97               else
   98               {
   99                   try
  100                   {
  101                       result[i] = Integer.parseInt(dimString);
  102                   }
  103                   catch (Exception e)
  104                   {
  105                       throw new XmlValueOutOfRangeException("Malformed integer in SOAP array index");
  106                   }
  107               }
  108           }
  109           return result;
  110       }
  111   
  112       /**
  113        * Parses a SOAP 1.1 array type string.
  114        *
  115        * Since an array type string contains a QName, a prefix resolver
  116        * must be passed.
  117        */
  118       public SOAPArrayType(String s, PrefixResolver m)
  119       {
  120           int firstbrace = s.indexOf('[');
  121           if (firstbrace < 0)
  122               throw new XmlValueOutOfRangeException();
  123   
  124           // grab the QName
  125           String firstpart = XmlWhitespace.collapse(s.substring(0, firstbrace), XmlWhitespace.WS_COLLAPSE);
  126           int firstcolon = firstpart.indexOf(':');
  127           String prefix = "";
  128           if (firstcolon >= 0)
  129               prefix = firstpart.substring(0, firstcolon);
  130   
  131           String uri = m.getNamespaceForPrefix(prefix);
  132           if (uri == null)
  133               throw new XmlValueOutOfRangeException();
  134   
  135           _type = QNameHelper.forLNS(firstpart.substring(firstcolon + 1), uri);
  136   
  137           initDimensions(s, firstbrace);
  138       }
  139   
  140       private static int[] EMPTY_INT_ARRAY = new int[0];
  141   
  142       /**
  143        * Parses SOAP 1.1(advanced) array type strings.
  144        *
  145        * Since in SOAP 1.1(advanced) the dimension specification is separated from the
  146        * QName for the underlying type, these are passed in separate
  147        * arguments.
  148        */
  149       public SOAPArrayType(QName name, String dimensions)
  150       {
  151           int firstbrace = dimensions.indexOf('[');
  152           if (firstbrace < 0)
  153           {
  154               _type = name;
  155               _ranks = EMPTY_INT_ARRAY;
  156               dimensions = XmlWhitespace.collapse(dimensions, XmlWhitespace.WS_COLLAPSE);
  157               String[] dimStrings = dimensions.split(" ");
  158               for (int i = 0; i < dimStrings.length; i++)
  159               {
  160                   String dimString = dimStrings[i];
  161                   if (dimString.equals("*"))
  162                   {
  163                       _dimensions[i] = -1;
  164                       // _hasIndeterminateDimensions = true;
  165                   }
  166                   else
  167                   {
  168                       try
  169                       {
  170                           _dimensions[i] = Integer.parseInt(dimStrings[i]);
  171                       }
  172                       catch (Exception e)
  173                       {
  174                           throw new XmlValueOutOfRangeException();
  175                       }
  176                   }
  177               }
  178           }
  179           else
  180           {
  181               _type = name;
  182               initDimensions(dimensions, firstbrace);
  183           }
  184       }
  185   
  186       /**
  187        * Given a nested SOAPArrayType and a set of dimensions for the outermost
  188        * array, comes up with the right SOAPArrayType for the whole thing.
  189        *
  190        * E.g.,
  191        * Nested foo:bar[,][][,,][1,2]
  192        * Dimensions [6,7,8]
  193        * Result -> foo:bar[,][][,,][,][6,7,8]
  194        */
  195       public SOAPArrayType(SOAPArrayType nested, int[] dimensions)
  196       {
  197           _type = nested._type;
  198   
  199           _ranks = new int[nested._ranks.length + 1];
  200           System.arraycopy(nested._ranks, 0, _ranks, 0, nested._ranks.length);
  201           _ranks[_ranks.length - 1] = nested._dimensions.length;
  202   
  203           _dimensions = new int[dimensions.length];
  204           System.arraycopy(dimensions, 0, _dimensions, 0, dimensions.length);
  205       }
  206   
  207       /**
  208        * Initialize dimensions based on SOAP11 parsed dimension substring
  209        */
  210       private void initDimensions(String s, int firstbrace)
  211       {
  212           List braces = new ArrayList();
  213           int lastbrace = -1;
  214           for (int i = firstbrace; i >= 0; )
  215           {
  216               lastbrace = s.indexOf(']', i);
  217               if (lastbrace < 0)
  218                   throw new XmlValueOutOfRangeException();
  219               braces.add(s.substring(i + 1, lastbrace));
  220               i = s.indexOf('[', lastbrace);
  221           }
  222   
  223           String trailer = s.substring(lastbrace + 1);
  224           if (!XmlWhitespace.isAllSpace(trailer))
  225               throw new XmlValueOutOfRangeException();
  226   
  227           // now fill in rank array
  228           _ranks = new int[braces.size() - 1];
  229           for (int i = 0; i < _ranks.length; i++)
  230           {
  231               String commas = (String)braces.get(i);
  232               int commacount = 0;
  233               for (int j = 0; j < commas.length(); j++)
  234               {
  235                   char ch = commas.charAt(j);
  236                   if (ch == ',')
  237                       commacount += 1;
  238                   else if (!XmlWhitespace.isSpace(ch))
  239                       throw new XmlValueOutOfRangeException();
  240               }
  241               _ranks[i] = commacount + 1;
  242           }
  243   
  244           // finally fill in dimension array
  245           _dimensions = internalParseCommaIntString((String)braces.get(braces.size() - 1));
  246   
  247           /*
  248           for (int i = 0; i < _dimensions.length; i++)
  249           {
  250               if (_dimensions[i] < 0)
  251                   _hasIndeterminateDimensions = true;
  252           }
  253           */
  254       }
  255   
  256       /**
  257        * Returns the QName for the referenced type.
  258        */
  259       public QName getQName()
  260       {
  261           return _type;
  262       }
  263   
  264       /**
  265        * Returns the array of ranks for inner nested arrays.
  266        * In SOAP 1.1-advanced, this is always an array of length zero.
  267        * In SOAP 1.1, this array reflects the ranks of nested
  268        * arrays. For example foo:bar[,][,,][][5,6] will produce
  269        * a ranks result of 2, 3, 1.
  270        */
  271       public int[] getRanks()
  272       {
  273           int[] result = new int[_ranks.length];
  274           System.arraycopy(_ranks, 0, result, 0, result.length);
  275           return result;
  276       }
  277   
  278       /**
  279        * Returns the array of dimensions.
  280        */
  281       public int[] getDimensions()
  282       {
  283           int[] result = new int[_dimensions.length];
  284           System.arraycopy(_dimensions, 0, result, 0, result.length);
  285           return result;
  286       }
  287   
  288       /**
  289        * True if this array contains nested arrays. Equivalent
  290        * to (getRanks().length > 0).
  291        */
  292       public boolean containsNestedArrays()
  293       {
  294           return (_ranks.length > 0);
  295       }
  296   
  297       /**
  298        * Returns the dimensions as a string, e.g., [,][2,3,4]
  299        */
  300       public String soap11DimensionString()
  301       {
  302           return soap11DimensionString(_dimensions);
  303       }
  304   
  305       /**
  306        * Given an actual set of dimensions that may differ from
  307        * the default that is stored, outputs the soap arrayType
  308        * string.
  309        */
  310       public String soap11DimensionString(int[] actualDimensions)
  311       {
  312           StringBuffer sb = new StringBuffer();
  313           for (int i = 0; i < _ranks.length; i++)
  314           {
  315               sb.append('[');
  316               for (int j = 1; j < _ranks[i]; j++)
  317                   sb.append(',');
  318               sb.append(']');
  319           }
  320   
  321           sb.append('[');
  322           for (int i = 0; i < actualDimensions.length; i++)
  323           {
  324               if (i > 0)
  325                   sb.append(',');
  326               if (actualDimensions[i] >= 0)
  327                   sb.append(actualDimensions[i]);
  328           }
  329           sb.append(']');
  330           return sb.toString();
  331       }
  332   
  333       private SOAPArrayType()
  334       {
  335       }
  336   
  337       /**
  338        * SOAP 1.2
  339        * Constructs a SOAPArrayType from soap-enc:itemType and
  340        * soap-enc:arraySize attributes
  341        * @param itemType the item type QName
  342        * @param arraySize a string with dimentions like: * 3 4
  343        * @return a SOAPArrayType to represent this
  344        */
  345       public static SOAPArrayType newSoap12Array(QName itemType, String arraySize)
  346       {
  347           int [] ranks = EMPTY_INT_ARRAY;
  348           arraySize = XmlWhitespace.collapse(arraySize, XmlWhitespace.WS_COLLAPSE);
  349           String[] dimStrings = arraySize.split(" ");
  350           int[] dimensions = new int[dimStrings.length];
  351           for (int i = 0; i < dimStrings.length; i++)
  352           {
  353               String dimString = dimStrings[i];
  354               if (i==0 && dimString.equals("*"))
  355               {
  356                   dimensions[i] = -1;
  357                   // _hasIndeterminateDimensions = true;
  358               }
  359               else
  360               {
  361                   try
  362                   {
  363                       dimensions[i] = Integer.parseInt(dimStrings[i]);
  364                   }
  365                   catch (Exception e)
  366                   {
  367                       throw new XmlValueOutOfRangeException();
  368                   }
  369               }
  370           }
  371           SOAPArrayType sot = new SOAPArrayType();
  372           sot._ranks = ranks;
  373           sot._type = itemType;
  374           sot._dimensions = dimensions;
  375           return sot;
  376       }
  377   
  378       /**
  379        * SOAP 1.2
  380        * Given an actual set of dimensions that may differ from
  381        * the default that is stored, outputs the soap arraySize
  382        * string.
  383        */
  384       public String soap12DimensionString(int[] actualDimensions)
  385       {
  386           StringBuffer sb = new StringBuffer();
  387   
  388           for (int i = 0; i < actualDimensions.length; i++)
  389           {
  390               if (i > 0)
  391                   sb.append(' ');
  392               if (actualDimensions[i] >= 0)
  393                   sb.append(actualDimensions[i]);
  394           }
  395           return sb.toString();
  396       }
  397   
  398       /**
  399        * Constructs a SOAPArrayType reflecting the dimensions
  400        * of the next nested array.
  401        */
  402       public SOAPArrayType nestedArrayType()
  403       {
  404           if (!containsNestedArrays())
  405               throw new IllegalStateException();
  406   
  407           SOAPArrayType result = new SOAPArrayType();
  408   
  409           result._type = _type;
  410   
  411           result._ranks = new int[_ranks.length - 1];
  412           System.arraycopy(_ranks, 0, result._ranks, 0, result._ranks.length);
  413   
  414           result._dimensions = new int[_ranks[_ranks.length - 1]];
  415           for (int i = 0; i < result._dimensions.length; i++)
  416               result._dimensions[i] = -1;
  417   
  418           // result._hasIndeterminateDimensions = (result._dimensions.length > 0);
  419   
  420           return result;
  421       }
  422   
  423       public int hashCode()
  424       {
  425           return (_type.hashCode() + _dimensions.length + _ranks.length + (_dimensions.length == 0 ? 0 : _dimensions[0]));
  426       }
  427   
  428       public boolean equals(Object obj)
  429       {
  430           if (obj == this)
  431               return true;
  432   
  433           if (!obj.getClass().equals(getClass()))
  434               return false;
  435   
  436           SOAPArrayType sat = (SOAPArrayType)obj;
  437   
  438           if (!_type.equals(sat._type))
  439               return false;
  440   
  441           if (_ranks.length != sat._ranks.length)
  442               return false;
  443   
  444           if (_dimensions.length != sat._dimensions.length)
  445               return false;
  446   
  447           for (int i = 0; i < _ranks.length; i++)
  448               if (_ranks[i] != sat._ranks[i])
  449                   return false;
  450   
  451           for (int i = 0; i < _dimensions.length; i++)
  452               if (_dimensions[i] != sat._dimensions[i])
  453                   return false;
  454   
  455           return true;
  456       }
  457   }

Home » xmlbeans-2.5.0-src » org.apache » xmlbeans » soap » [javadoc | source]