/*
 * Copyright 2001-2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.axis2.databinding.types;


import java.io.ObjectStreamException;
import java.math.BigInteger;
import java.util.Random;

/**
 * Custom class for supporting primitive XSD data type positiveInteger
 *
 * positiveInteger is derived from nonNegativeInteger by setting the value of minInclusive to be 1. 
 * This results in the standard mathematical concept of the positive integer numbers. The value space
 * of positiveInteger is the infinite set {1,2,...}. 
 *
 * @see <a href="http://www.w3.org/TR/xmlschema-2/#positiveInteger">XML Schema 3.3.25</a>
 */
public class PositiveInteger extends NonNegativeInteger {

    private static final long serialVersionUID = -4562301423231920813L;
    
	public PositiveInteger(byte[] val) {
        super(val);
        checkValidity();
    } // ctor

    public PositiveInteger(int signum, byte[] magnitude) {
        super(signum, magnitude);
        checkValidity();
    } // ctor

    public PositiveInteger(int bitLength, int certainty, Random rnd) {
        super(bitLength, certainty, rnd);
        checkValidity();
    } // ctor

    public PositiveInteger(int numBits, Random rnd) {
        super(numBits, rnd);
        checkValidity();
    } // ctor

    public PositiveInteger(String val) {
        super(val);
        checkValidity();
    }

    public PositiveInteger(String val, int radix) {
        super(val, radix);
        checkValidity();
    } // ctor

    /**
     * validate the value against the xsd definition
     */
    private BigInteger iMinInclusive = new BigInteger("1");
    private void checkValidity() {
        if (compareTo(iMinInclusive) < 0) {
            throw new NumberFormatException(
                    //Messages.getMessage("badposInt00")
                    ":  " + this);
        }
    } // checkValidity

    /**
     * Work-around for http://developer.java.sun.com/developer/bugParade/bugs/4378370.html
     * @return BigIntegerRep
     * @throws java.io.ObjectStreamException
     */ 
    public Object writeReplace() throws ObjectStreamException {
        return new BigIntegerRep(toByteArray());
    }
    
    protected static class BigIntegerRep implements java.io.Serializable {
        private static final long serialVersionUID = 1251664160936150499L;
		private byte[] array;
        protected BigIntegerRep(byte[] array) {
            this.array = array;
        }
        protected Object readResolve() throws java.io.ObjectStreamException {
            return new PositiveInteger(array);
        }
    }
} // class NonNegativeInteger
