OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [xml/] [transform/] [AbstractNumberNode.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* AbstractNumberNode.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 gnu.java.lang.CPStringBuilder;
41
 
42
import java.util.ArrayList;
43
import java.util.Collections;
44
import java.util.List;
45
import javax.xml.namespace.QName;
46
import javax.xml.transform.TransformerException;
47
import org.w3c.dom.Document;
48
import org.w3c.dom.DocumentFragment;
49
import org.w3c.dom.Node;
50
import org.w3c.dom.Text;
51
import gnu.xml.xpath.Expr;
52
 
53
/**
54
 * A template node representing the XSL <code>number</code> instruction.
55
 *
56
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
57
 */
58
abstract class AbstractNumberNode
59
  extends TemplateNode
60
{
61
 
62
  static final int ALPHABETIC = 0;
63
  static final int TRADITIONAL = 1;
64
 
65
  final TemplateNode format;
66
  final String lang;
67
  final int letterValue;
68
  final String groupingSeparator;
69
  final int groupingSize;
70
 
71
  AbstractNumberNode(TemplateNode format, String lang,
72
                     int letterValue, String groupingSeparator,
73
                     int groupingSize)
74
  {
75
    this.format = format;
76
    this.lang = lang;
77
    this.letterValue = letterValue;
78
    this.groupingSeparator = groupingSeparator;
79
    this.groupingSize = groupingSize;
80
  }
81
 
82
  void doApply(Stylesheet stylesheet, QName mode,
83
               Node context, int pos, int len,
84
               Node parent, Node nextSibling)
85
    throws TransformerException
86
  {
87
    Document doc = (parent instanceof Document) ? (Document) parent :
88
      parent.getOwnerDocument();
89
    DocumentFragment fragment = doc.createDocumentFragment();
90
    format.apply(stylesheet, mode, context, pos, len, fragment, null);
91
    String f = Expr._string(context, Collections.singleton(fragment));
92
    String value = format(f, compute(stylesheet, context, pos, len));
93
    Text text = doc.createTextNode(value);
94
    if (nextSibling != null)
95
      {
96
        parent.insertBefore(text, nextSibling);
97
      }
98
    else
99
      {
100
        parent.appendChild(text);
101
      }
102
    // xsl:number doesn't process children
103
    if (next != null)
104
      {
105
        next.apply(stylesheet, mode,
106
                   context, pos, len,
107
                   parent, nextSibling);
108
      }
109
  }
110
 
111
  String format(String format, int[] number)
112
  {
113
    if (number.length == 0)
114
      {
115
        return "";
116
      }
117
    int start = 0, end = 0, len = format.length(); // region of format
118
    // Tokenize
119
    List tokens = new ArrayList((number.length * 2) + 1);
120
    List types = new ArrayList(tokens.size());
121
    while (end < len)
122
      {
123
        while (end < len && !isAlphanumeric(format.charAt(end)))
124
          {
125
            end++;
126
          }
127
        if (end > start)
128
          {
129
            tokens.add(format.substring(start, end));
130
            types.add(Boolean.FALSE);
131
          }
132
        start = end;
133
        while (end < len && isAlphanumeric(format.charAt(end)))
134
          {
135
            end++;
136
          }
137
        if (end > start)
138
          {
139
            tokens.add(format.substring(start, end));
140
            types.add(Boolean.TRUE);
141
          }
142
        start = end;
143
      }
144
    // Process tokens
145
    CPStringBuilder buf = new CPStringBuilder();
146
    len = tokens.size();
147
    int pos = 0;
148
    for (int i = 0; i < len; i++)
149
      {
150
        String token = (i < 0) ? "." : (String) tokens.get(i);
151
        boolean alpha = (i < 0) ? true :
152
          ((Boolean) types.get(i)).booleanValue();
153
        if (!alpha)
154
          {
155
            buf.append(token);
156
          }
157
        else
158
          {
159
            if (pos < number.length)
160
              {
161
                format(buf, number[pos++], token);
162
                if (((i + 1 == len) || (i + 2 == len)) &&
163
                    (pos < number.length))
164
                  {
165
                    // More numbers than tokens, reuse last token
166
                    i -= 2;
167
                  }
168
              }
169
            if (pos == number.length && i < (len - 2))
170
              {
171
                // No more numbers. Skip to the end...
172
                i = len - 2;
173
                if (((Boolean) types.get(i + 1)).booleanValue())
174
                  {
175
                    // number formatting token, ignore
176
                    i++;
177
                  }
178
              }
179
          }
180
      }
181
    //System.err.println("format: '"+format+"' "+asList(number)+" = '"+buf.toString()+"'");
182
    return buf.toString();
183
  }
184
 
185
  /*List asList(int[] number)
186
    {
187
      List l = new ArrayList();
188
      for (int i = 0; i < number.length; i++)
189
        l.add(new Integer(number[i]));
190
      return l;
191
    }*/
192
 
193
  void format(CPStringBuilder buf, int number, String formatToken)
194
  {
195
    int len = formatToken.length();
196
    char c = formatToken.charAt(len - 1);
197
    if (Character.digit(c, 10) == 1)
198
      {
199
        // Check preceding characters
200
        for (int i = len - 2; i >= 0; i--)
201
          {
202
            if (formatToken.charAt(i) != (c - 1))
203
              {
204
                format(buf, number, "1");
205
                return;
206
              }
207
          }
208
        // Decimal representation
209
        String val = Integer.toString(number);
210
        for (int d = len - val.length(); d > 0; d--)
211
          {
212
            buf.append('0');
213
          }
214
        buf.append(val);
215
      }
216
    else if ("A".equals(formatToken))
217
      {
218
        buf.append(alphabetic('@', number));
219
      }
220
    else if ("a".equals(formatToken))
221
      {
222
        buf.append(alphabetic('`', number));
223
      }
224
    else if ("i".equals(formatToken))
225
      {
226
        buf.append(roman(false, number));
227
      }
228
    else if ("I".equals(formatToken))
229
      {
230
        buf.append(roman(true, number));
231
      }
232
    else
233
      {
234
        // Unknown numbering sequence
235
        format(buf, number, "1");
236
      }
237
  }
238
 
239
  static final boolean isAlphanumeric(char c)
240
  {
241
    switch (Character.getType(c))
242
      {
243
      case Character.DECIMAL_DIGIT_NUMBER: // Nd
244
      case Character.LETTER_NUMBER: // Nl
245
      case Character.OTHER_NUMBER: // No
246
      case Character.UPPERCASE_LETTER: // Lu
247
      case Character.LOWERCASE_LETTER: // Ll
248
      case Character.TITLECASE_LETTER: // Lt
249
      case Character.MODIFIER_LETTER: // Lm
250
      case Character.OTHER_LETTER: // Lo
251
        return true;
252
      default:
253
        return false;
254
      }
255
  }
256
 
257
  static final String alphabetic(char offset, int number)
258
  {
259
    CPStringBuilder buf = new CPStringBuilder();
260
    while (number > 0)
261
      {
262
        int r = number % 26;
263
        number = number / 26;
264
        buf.insert(0, (char) (offset + r));
265
      }
266
    return buf.toString();
267
  }
268
 
269
  static final int[] roman_numbers = {1, 5, 10, 50, 100, 500, 1000};
270
  static final char[] roman_chars = {'i', 'v', 'x', 'l', 'c', 'd', 'm'};
271
 
272
  static final String roman(boolean upper, int number)
273
  {
274
    CPStringBuilder buf = new CPStringBuilder();
275
    for (int pos = roman_numbers.length - 1; pos >= 0; pos -= 2)
276
      {
277
        int f = number / roman_numbers[pos];
278
        if (f != 0)
279
          {
280
            number = number % (f * roman_numbers[pos]);
281
          }
282
        if (f > 4 && f < 9)
283
          {
284
            buf.append(roman_chars[pos + 1]);
285
            f -= 5;
286
          }
287
        if (f == 4)
288
          {
289
            buf.append(roman_chars[pos]);
290
            buf.append(roman_chars[pos + 1]);
291
          }
292
        else if (f == 9)
293
          {
294
            buf.append(roman_chars[pos]);
295
            buf.append(roman_chars[pos + 2]);
296
          }
297
        else
298
          {
299
            for (; f > 0; f--)
300
              {
301
                buf.append(roman_chars[pos]);
302
              }
303
          }
304
      }
305
    return upper ? buf.toString().toUpperCase() : buf.toString();
306
  }
307
 
308
  abstract int[] compute(Stylesheet stylesheet, Node context, int pos, int len)
309
    throws TransformerException;
310
 
311
  public boolean references(QName var)
312
  {
313
    if (format.references(var))
314
      {
315
        return true;
316
      }
317
    return super.references(var);
318
  }
319
 
320
  public String toString()
321
  {
322
    CPStringBuilder buf = new CPStringBuilder("number");
323
    buf.append('[');
324
    buf.append("format=");
325
    buf.append(format);
326
    buf.append(']');
327
    return buf.toString();
328
  }
329
 
330
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.