/****************************************************************************** * Copyright (c) 2016 Oracle * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Konstantin Komissarchik - initial implementation and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire; import static java.lang.Math.max; import java.util.Collections; import java.util.List; import org.eclipse.sapphire.util.ListFactory; /** * Represents a version as a sequence of long integers. In string format, it is represented as a dot-separated * list of numeric segments, such as "1.2.3" or "5.7.3.2012070310003". * * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public final class Version implements Comparable<Version> { private final List<Long> segments; private final int length; public Version( final long version ) { if( version == 0 ) { this.segments = Collections.emptyList(); this.length = 0; } else if( version > 0 ) { this.segments = Collections.singletonList( version ); this.length = 1; } else { throw new IllegalArgumentException( String.valueOf( version ) ); } } public Version( final String versionString ) throws IllegalArgumentException { if( versionString == null ) { throw new IllegalArgumentException(); } final String str = versionString.trim(); if( str.startsWith( "." ) || str.endsWith( "." ) || str.contains( ".." ) ) { throw new IllegalArgumentException( str ); } final ListFactory<Long> segments = ListFactory.start(); for( String segment : str.split( "\\." ) ) { final long segmentAsLong; try { segmentAsLong = Long.parseLong( segment ); } catch( NumberFormatException e ) { throw new IllegalArgumentException( str ); } if( segmentAsLong < 0 ) { throw new IllegalArgumentException( str ); } segments.add( segmentAsLong ); } for( int i = segments.size() - 1; i >= 0; i-- ) { if( segments.get( i ) == 0 ) { segments.remove( i ); } else { break; } } this.segments = segments.result(); this.length = this.segments.size(); } public List<Long> segments() { return this.segments; } public long segment( final int position ) { if( position < 0 ) { throw new IllegalArgumentException( String.valueOf( position ) ); } else if( position < this.length ) { return this.segments.get( position ); } else { return 0; } } public int length() { return this.length; } public boolean matches( final String constraint ) { return matches( new VersionConstraint( constraint ) ); } public boolean matches( final VersionConstraint constraint ) { return constraint.check( this ); } public int compareTo( final Version version ) { for( int i = 0, n = max( length(), version.length ); i < n; i++ ) { final long res = segment( i ) - version.segment( i ); if( res > 0 ) { return 1; } else if( res < 0 ) { return -1; } } return 0; } @Override public boolean equals( final Object obj ) { if( obj instanceof Version ) { final Version version = (Version) obj; if( length() == version.length() ) { for( int i = 0, n = length(); i < n; i++ ) { if( segment( i ) != version.segment( i ) ) { return false; } } return true; } } return false; } @Override public int hashCode() { int hashCode = 1; for( int i = 0, n = length(); i < n; i++ ) { hashCode *= segment( i ); } return hashCode; } @Override public String toString() { final StringBuilder buf = new StringBuilder(); for( long segment : this.segments ) { if( buf.length() > 0 ) { buf.append( '.' ); } buf.append( segment ); } return buf.toString(); } }