1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2002,2003-2004 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.impl.xs;
  22 
  23 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  24 import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
  25 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  26 import com.sun.org.apache.xerces.internal.xs.XSModelGroup;
  27 import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
  28 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  29 
  30 /**
  31  * Store schema model group declaration.
  32  *
  33  * @xerces.internal
  34  *
  35  * @author Sandy Gao, IBM
  36  *
  37  */
  38 public class XSModelGroupImpl implements XSModelGroup {
  39 
  40     // types of model groups
  41     // REVISIT: can't use same constants as those for particles, because
  42     // there are place where the constants are used together. For example,
  43     // to check whether the content is an element or a sequence.
  44     public static final short MODELGROUP_CHOICE       = 101;
  45     public static final short MODELGROUP_SEQUENCE     = 102;
  46     public static final short MODELGROUP_ALL          = 103;
  47 
  48     // compositor of the model group
  49     public short fCompositor;
  50 
  51     // particles
  52     public XSParticleDecl[] fParticles = null;
  53     public int fParticleCount = 0;
  54 
  55     // this particle's optional annotations
  56     public XSObjectList fAnnotations = null;
  57 
  58     // whether this model group contains nothing
  59     public boolean isEmpty() {
  60         for (int i = 0; i < fParticleCount; i++) {
  61             if (!fParticles[i].isEmpty())
  62                 return false;
  63         }
  64         return true;
  65     }
  66 
  67     /**
  68      * 3.8.6 Effective Total Range (all and sequence) and
  69      *       Effective Total Range (choice)
  70      * The following methods are used to return min/max range for a particle.
  71      * They are not exactly the same as it's described in the spec, but all the
  72      * values from the spec are retrievable by these methods.
  73      */
  74     public int minEffectiveTotalRange() {
  75         if (fCompositor == MODELGROUP_CHOICE)
  76             return minEffectiveTotalRangeChoice();
  77         else
  78             return minEffectiveTotalRangeAllSeq();
  79     }
  80 
  81     // return the sum of all min values of the particles
  82     private int minEffectiveTotalRangeAllSeq() {
  83         int total = 0;
  84         for (int i = 0; i < fParticleCount; i++)
  85             total += fParticles[i].minEffectiveTotalRange();
  86         return total;
  87     }
  88 
  89     // return the min of all min values of the particles
  90     private int minEffectiveTotalRangeChoice() {
  91         int min = 0, one;
  92         if (fParticleCount > 0)
  93             min = fParticles[0].minEffectiveTotalRange();
  94 
  95         for (int i = 1; i < fParticleCount; i++) {
  96             one = fParticles[i].minEffectiveTotalRange();
  97             if (one < min)
  98                 min = one;
  99         }
 100 
 101         return min;
 102     }
 103 
 104     public int maxEffectiveTotalRange() {
 105         if (fCompositor == MODELGROUP_CHOICE)
 106             return maxEffectiveTotalRangeChoice();
 107         else
 108             return maxEffectiveTotalRangeAllSeq();
 109     }
 110 
 111     // if one of the max value of the particles is unbounded, return unbounded;
 112     // otherwise return the sum of all max values
 113     private int maxEffectiveTotalRangeAllSeq() {
 114         int total = 0, one;
 115         for (int i = 0; i < fParticleCount; i++) {
 116             one = fParticles[i].maxEffectiveTotalRange();
 117             if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
 118                 return SchemaSymbols.OCCURRENCE_UNBOUNDED;
 119             total += one;
 120         }
 121         return total;
 122     }
 123 
 124     // if one of the max value of the particles is unbounded, return unbounded;
 125     // otherwise return the max of all max values
 126     private int maxEffectiveTotalRangeChoice() {
 127         int max = 0, one;
 128         if (fParticleCount > 0) {
 129             max = fParticles[0].maxEffectiveTotalRange();
 130             if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
 131                 return SchemaSymbols.OCCURRENCE_UNBOUNDED;
 132         }
 133 
 134         for (int i = 1; i < fParticleCount; i++) {
 135             one = fParticles[i].maxEffectiveTotalRange();
 136             if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
 137                 return SchemaSymbols.OCCURRENCE_UNBOUNDED;
 138             if (one > max)
 139                 max = one;
 140         }
 141         return max;
 142     }
 143 
 144     /**
 145      * get the string description of this particle
 146      */
 147     private String fDescription = null;
 148     public String toString() {
 149         // REVISIT: Commented code may help to eliminate redundant parentheses (test first before committing)
 150         if (fDescription == null) {
 151             StringBuffer buffer = new StringBuffer();
 152             if (fCompositor == MODELGROUP_ALL)
 153                 buffer.append("all(");
 154             else  //if (fMinOccurs != 1 || fMaxOccurs != 1)
 155                 buffer.append('(');
 156             if (fParticleCount > 0)
 157                 buffer.append(fParticles[0].toString());
 158             for (int i = 1; i < fParticleCount; i++) {
 159                 if (fCompositor == MODELGROUP_CHOICE)
 160                     buffer.append('|');
 161                 else
 162                     buffer.append(',');
 163                 buffer.append(fParticles[i].toString());
 164             }
 165             //if (fCompositor == MODELGROUP_ALL || fMinOccurs != 1 || fMaxOccurs != 1)
 166                   buffer.append(')');
 167             fDescription = buffer.toString();
 168         }
 169         return fDescription;
 170     }
 171 
 172     public void reset(){
 173         fCompositor = MODELGROUP_SEQUENCE;
 174         fParticles = null;
 175         fParticleCount = 0;
 176         fDescription = null;
 177         fAnnotations = null;
 178     }
 179 
 180     /**
 181      * Get the type of the object, i.e ELEMENT_DECLARATION.
 182      */
 183     public short getType() {
 184         return XSConstants.MODEL_GROUP;
 185     }
 186 
 187     /**
 188      * The <code>name</code> of this <code>XSObject</code> depending on the
 189      * <code>XSObject</code> type.
 190      */
 191     public String getName() {
 192         return null;
 193     }
 194 
 195     /**
 196      * The namespace URI of this node, or <code>null</code> if it is
 197      * unspecified.  defines how a namespace URI is attached to schema
 198      * components.
 199      */
 200     public String getNamespace() {
 201         return null;
 202     }
 203 
 204     /**
 205      * {compositor} One of all, choice or sequence. The valid constants values
 206      * are: ALL, CHOICE, SEQUENCE.
 207      */
 208     public short getCompositor() {
 209         if (fCompositor == MODELGROUP_CHOICE)
 210             return XSModelGroup.COMPOSITOR_CHOICE;
 211         else if (fCompositor == MODELGROUP_SEQUENCE)
 212             return XSModelGroup.COMPOSITOR_SEQUENCE;
 213         else
 214             return XSModelGroup.COMPOSITOR_ALL;
 215     }
 216 
 217     /**
 218      * {particles} A list of particles
 219      */
 220     public XSObjectList getParticles() {
 221         return new XSObjectListImpl(fParticles, fParticleCount);
 222     }
 223 
 224     /**
 225      * Optional. Annotation.
 226      */
 227     public XSAnnotation getAnnotation() {
 228         return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
 229     }
 230 
 231     /**
 232      * Optional. Annotations.
 233      */
 234     public XSObjectList getAnnotations() {
 235         return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
 236     }
 237 
 238     /**
 239      * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
 240      */
 241     public XSNamespaceItem getNamespaceItem() {
 242         return null;
 243     }
 244 
 245 } // class XSModelGroupImpl