/**
 * Copyright (c) 2013, impossibl.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of impossibl.com nor the names of its contributors may
 *    be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package com.impossibl.postgres.system;

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Version {
	
	//private static final Pattern VERSION_PATTERN = compile("(\\d+)(?:\\.(\\d+)(?:\\.(\\d+))?)?");
	private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?");
	private static final HashMap<Version,Version> all = new HashMap<Version,Version>();
	
	int major;
	Integer minor;
	Integer revision;
	
	public static Version parse(String versionString) {
		
		Matcher matcher = VERSION_PATTERN.matcher(versionString);
		if(!matcher.find())
			return null;
		
		int major = Integer.parseInt(matcher.group(1));
		Integer minor = matcher.group(2) != null ? Integer.parseInt(matcher.group(2)) : null;
		Integer revision = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : null;
		
		return get(major, minor, revision);
	}

	public static synchronized Version get(int major, Integer minor, Integer revision) {
		
		Version test = new Version(major, minor, revision);
		
		Version found = all.get(test);
		if(found == null) {
			
			all.put(test, test);
			found = test;
		}
		
		return found;
	}	
	
	private Version(int major, Integer minor, Integer revision) {

		if(minor == null && revision != null)
			throw new IllegalArgumentException();
		

		this.major = major;
		this.minor = minor;
		this.revision = revision;
	}

	public int getMajor() {
		return major;
	}

	public Integer getMinor() {
		return minor;
	}

	public Integer getRevision() {
		return revision;
	}

	public boolean compatible(Version current) {
		return compatible(current.major, current.minor, current.revision);
	}
	
	public boolean compatible(int major, Integer minor, Integer revision) {
		return this.major >= major 
				&& (minor == null || this.minor == null || minor >= this.minor) 
				&& (revision == null || this.revision == null || revision >= this.revision);
	}

	public boolean equals(Version current) {
		return equals(current.major, current.minor, current.revision);
	}
	
	public boolean equals(int major, Integer minor, Integer revision) {
		return this.major == major && (minor == null || minor.equals(this.minor)) && (revision == null || revision.equals(this.revision));
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(major);
		if(minor != null)
			sb.append('.').append(minor);
		if(revision != null)
			sb.append('.').append(revision);
		return sb.toString();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + major;
		result = prime * result + ((minor == null) ? 0 : minor.hashCode());
		result = prime * result + ((revision == null) ? 0 : revision.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Version other = (Version) obj;
		if (major != other.major)
			return false;
		if (minor == null) {
			if (other.minor != null)
				return false;
		}
		else if (!minor.equals(other.minor))
			return false;
		if (revision == null) {
			if (other.revision != null)
				return false;
		}
		else if (!revision.equals(other.revision))
			return false;
		return true;
	}

}

@@ -1635,297 +1635,33 @@
 ap;%0A
-import java.util.regex.Matcher;%0Aimport java.util.regex.Pattern;%0A%0Apublic class Version %7B%0A%09%0A%09//private static final Pattern VERSION_PATTERN = compile(%22(%5C%5Cd+)(?:%5C%5C.(%5C%5Cd+)(?:%5C%5C.(%5C%5Cd+))?)?%22);%0A%09private static final Pattern VERSION_PATTERN = Pattern.compile(%22(%5C%5Cd+)(?:%5C%5C.(%5C%5Cd+))?(?:%5C%5C.(%5C%5Cd+))?%22);
+%0Apublic class Version %7B%0A%09
 %0A%09pr
@@ -1745,16 +1745,24 @@
 %3E();%0A%09%0A%09
+private 
 int majo
@@ -1761,24 +1761,32 @@
 int major;%0A%09
+private 
 Integer mino
@@ -1789,16 +1789,24 @@
 minor;%0A%09
+private 
 Integer 
@@ -1874,107 +1874,69 @@
 ) %7B%0A
-%09%09%0A%09%09Matcher matcher = VERSION_PATTERN.matcher(versionString);%0A%09%09if(!matcher.find())%0A%09%09%09return null
+                String%5B%5D version = versionString.split(%22%5C%5C.%22)
 ;%0A%09%09
@@ -1971,24 +1971,18 @@
 Int(
-matcher.group(1)
+version%5B0%5D
 );%0A%09
@@ -2002,174 +2002,160 @@
 r = 
-matcher.group(2) != null ? Integer.parseInt(matcher.group(2)) : null;%0A%09%09Integer revision = matcher.group(3) != null ? Integer.parseInt(matcher.group(3)) : null;%0A%09%09%0A%09%09
+version.length %3E 1 ? Integer.valueOf(version%5B1%5D) : null;%0A%09%09Integer revision = version.length %3E 2 ? Integer.valueOf(version%5B2%5D) : null;%0A%0A                
 retu

Simplify version parsing