001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /* $Id: PageNumberGenerator.java 426576 2006-07-28 15:44:37Z jeremias $ */
019:
020: package org.apache.fop.fo.pagination;
021:
022: /**
023: * This class uses the 'format', 'groupingSeparator', 'groupingSize',
024: * and 'letterValue' properties on fo:page-sequence to return a String
025: * corresponding to the supplied integer page number.
026: */
027: public class PageNumberGenerator {
028:
029: private String format;
030: private char groupingSeparator;
031: private int groupingSize;
032: private int letterValue;
033:
034: // constants
035: private static final int DECIMAL = 1; // '0*1'
036: private static final int LOWERALPHA = 2; // 'a'
037: private static final int UPPERALPHA = 3; // 'A'
038: private static final int LOWERROMAN = 4; // 'i'
039: private static final int UPPERROMAN = 5; // 'I'
040:
041: // flags
042: private int formatType = DECIMAL;
043: private int minPadding = 0; // for decimal formats
044:
045: // preloaded strings of zeros
046: private String zeros[] = { "", "0", "00", "000", "0000", "00000" };
047:
048: /**
049: * Main constructor. For further information on the parameters see the XSLT
050: * specs (Number to String Conversion Attributes).
051: * @param format format for the page number
052: * @param groupingSeparator grouping separator
053: * @param groupingSize grouping size
054: * @param letterValue letter value
055: */
056: public PageNumberGenerator(String format, char groupingSeparator,
057: int groupingSize, int letterValue) {
058: this .format = format;
059: this .groupingSeparator = groupingSeparator;
060: this .groupingSize = groupingSize;
061: this .letterValue = letterValue;
062:
063: // the only accepted format strings are currently '0*1' 'a', 'A', 'i'
064: // and 'I'
065: int fmtLen = format.length();
066: if (fmtLen == 1) {
067: if (format.equals("1")) {
068: formatType = DECIMAL;
069: minPadding = 0;
070: } else if (format.equals("a")) {
071: formatType = LOWERALPHA;
072: } else if (format.equals("A")) {
073: formatType = UPPERALPHA;
074: } else if (format.equals("i")) {
075: formatType = LOWERROMAN;
076: } else if (format.equals("I")) {
077: formatType = UPPERROMAN;
078: } else {
079: // token not handled
080: //getLogger().debug("'format' token not recognized; using '1'");
081: formatType = DECIMAL;
082: minPadding = 0;
083: }
084: } else {
085: // only accepted token is '0+1'at this stage. Because of the
086: // wonderful regular expression support in Java, we will resort to a
087: // loop
088: for (int i = 0; i < fmtLen - 1; i++) {
089: if (format.charAt(i) != '0') {
090: //getLogger().debug("'format' token not recognized; using '1'");
091: formatType = DECIMAL;
092: minPadding = 0;
093: } else {
094: minPadding = fmtLen - 1;
095: }
096: }
097: }
098: }
099:
100: /**
101: * Formats a page number.
102: * @param number page number to format
103: * @return the formatted page number as a String
104: */
105: public String makeFormattedPageNumber(int number) {
106: String pn = null;
107: if (formatType == DECIMAL) {
108: pn = Integer.toString(number);
109: if (minPadding >= pn.length()) {
110: int nz = minPadding - pn.length() + 1;
111: pn = zeros[nz] + pn;
112: }
113: } else if ((formatType == LOWERROMAN)
114: || (formatType == UPPERROMAN)) {
115: pn = makeRoman(number);
116: if (formatType == UPPERROMAN) {
117: pn = pn.toUpperCase();
118: }
119: } else {
120: // alphabetic
121: pn = makeAlpha(number);
122: if (formatType == UPPERALPHA) {
123: pn = pn.toUpperCase();
124: }
125: }
126: return pn;
127: }
128:
129: private String makeRoman(int num) {
130: int arabic[] = { 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9,
131: 5, 4, 1 };
132: String roman[] = { "m", "cm", "d", "cd", "c", "xc", "l", "xl",
133: "x", "ix", "v", "iv", "i" };
134:
135: int i = 0;
136: StringBuffer romanNumber = new StringBuffer();
137:
138: while (num > 0) {
139: while (num >= arabic[i]) {
140: num = num - arabic[i];
141: romanNumber.append(roman[i]);
142: }
143: i = i + 1;
144: }
145: return romanNumber.toString();
146: }
147:
148: private String makeAlpha(int num) {
149: String letters = "abcdefghijklmnopqrstuvwxyz";
150: StringBuffer alphaNumber = new StringBuffer();
151:
152: int base = 26;
153: int rem = 0;
154:
155: num--;
156: if (num < base) {
157: alphaNumber.append(letters.charAt(num));
158: } else {
159: while (num >= base) {
160: rem = num % base;
161: alphaNumber.append(letters.charAt(rem));
162: num = num / base;
163: }
164: alphaNumber.append(letters.charAt(num - 1));
165: }
166: return alphaNumber.reverse().toString();
167: }
168: }
|