&{ProtocolVersion.java}
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.
*
*/

/*
* This file is auto-generated by ${GENERATOR} - do not modify.
* Supported AMQP versions:
%{VLIST} *   ${major}-${minor}
*/

package org.apache.qpid.framing;

import java.util.SortedSet;
import java.util.Collections;
import java.util.TreeSet;


public class ProtocolVersion  implements Comparable
{
    private final byte _majorVersion;
    private final byte _minorVersion;


    public ProtocolVersion(byte majorVersion, byte minorVersion)
    {
        _majorVersion = majorVersion;
        _minorVersion = minorVersion;
    }

    public byte getMajorVersion()
    {
        return _majorVersion;
    }

    public byte getMinorVersion()
    {
        return _minorVersion;
    }


    public int compareTo(Object o)
    {
        ProtocolVersion pv = (ProtocolVersion) o;
        if(getMajorVersion() > pv.getMajorVersion())
        {
            return 1;
        }
        else if(getMajorVersion() < pv.getMajorVersion())
        {
            return -1;
        }
        else if(getMajorVersion() > pv.getMajorVersion())
        {
            return 1;
        }
        else if(getMinorVersion() < pv.getMinorVersion())
        {
            return -1;
        }
        else
        {
            return 0;
        }

    }

    public boolean equals(Object o)
    {
        return o != null && (o == this || (compareTo(o) == 0));
    }

    public int hashCode()
    {
        return (0xFF & (int)_minorVersion) | ((0xFF & (int)_majorVersion) << 8);
    }
    
    
    public boolean isSupported()
    {
        return _supportedVersions.contains(this);
    }
    
    public static ProtocolVersion getLatestSupportedVersion()
    {
        return _supportedVersions.last();
    }
    
    private static final SortedSet<ProtocolVersion> _supportedVersions;

    static
    {
        SortedSet<ProtocolVersion> versions = new TreeSet<ProtocolVersion>();

%{VLIST}        versions.add(new ProtocolVersion((byte)${major},(byte)${minor}));

        _supportedVersions = Collections.unmodifiableSortedSet(versions);
    }

    
    public static SortedSet<ProtocolVersion> getSupportedProtocolVersions()
    {
        return _supportedVersions;
    }
    
    
    
    

}
