001: package org.apache.lucene.document;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: /**
021: * Provides support for converting longs to Strings, and back again. The strings
022: * are structured so that lexicographic sorting order is preserved.
023: *
024: * <p>
025: * That is, if l1 is less than l2 for any two longs l1 and l2, then
026: * NumberTools.longToString(l1) is lexicographically less than
027: * NumberTools.longToString(l2). (Similarly for "greater than" and "equals".)
028: *
029: * <p>
030: * This class handles <b>all</b> long values (unlike
031: * {@link org.apache.lucene.document.DateField}).
032: *
033: *
034: */
035: public class NumberTools {
036:
037: private static final int RADIX = 36;
038:
039: private static final char NEGATIVE_PREFIX = '-';
040:
041: // NB: NEGATIVE_PREFIX must be < POSITIVE_PREFIX
042: private static final char POSITIVE_PREFIX = '0';
043:
044: //NB: this must be less than
045: /**
046: * Equivalent to longToString(Long.MIN_VALUE)
047: */
048: public static final String MIN_STRING_VALUE = NEGATIVE_PREFIX
049: + "0000000000000";
050:
051: /**
052: * Equivalent to longToString(Long.MAX_VALUE)
053: */
054: public static final String MAX_STRING_VALUE = POSITIVE_PREFIX
055: + "1y2p0ij32e8e7";
056:
057: /**
058: * The length of (all) strings returned by {@link #longToString}
059: */
060: public static final int STR_SIZE = MIN_STRING_VALUE.length();
061:
062: /**
063: * Converts a long to a String suitable for indexing.
064: */
065: public static String longToString(long l) {
066:
067: if (l == Long.MIN_VALUE) {
068: // special case, because long is not symetric around zero
069: return MIN_STRING_VALUE;
070: }
071:
072: StringBuffer buf = new StringBuffer(STR_SIZE);
073:
074: if (l < 0) {
075: buf.append(NEGATIVE_PREFIX);
076: l = Long.MAX_VALUE + l + 1;
077: } else {
078: buf.append(POSITIVE_PREFIX);
079: }
080: String num = Long.toString(l, RADIX);
081:
082: int padLen = STR_SIZE - num.length() - buf.length();
083: while (padLen-- > 0) {
084: buf.append('0');
085: }
086: buf.append(num);
087:
088: return buf.toString();
089: }
090:
091: /**
092: * Converts a String that was returned by {@link #longToString} back to a
093: * long.
094: *
095: * @throws IllegalArgumentException
096: * if the input is null
097: * @throws NumberFormatException
098: * if the input does not parse (it was not a String returned by
099: * longToString()).
100: */
101: public static long stringToLong(String str) {
102: if (str == null) {
103: throw new NullPointerException("string cannot be null");
104: }
105: if (str.length() != STR_SIZE) {
106: throw new NumberFormatException("string is the wrong size");
107: }
108:
109: if (str.equals(MIN_STRING_VALUE)) {
110: return Long.MIN_VALUE;
111: }
112:
113: char prefix = str.charAt(0);
114: long l = Long.parseLong(str.substring(1), RADIX);
115:
116: if (prefix == POSITIVE_PREFIX) {
117: // nop
118: } else if (prefix == NEGATIVE_PREFIX) {
119: l = l - Long.MAX_VALUE - 1;
120: } else {
121: throw new NumberFormatException(
122: "string does not begin with the correct prefix");
123: }
124:
125: return l;
126: }
127: }
|