package com.alvazan.orm.api.base.spi;

import java.net.InetAddress;
import java.net.UnknownHostException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * Some programmers I have met think random == unique.  It does NOT.  Generate 11 random
 * numbers between 1 and 10 and the 11th "randomly generated number will match one of the
 * previous 10 meaning it is NOT unique.  That said, we could have used
 * http://johannburkard.de/blog/programming/java/Java-UUID-generators-compared.html
 * to generate UUID's here but instead we wanted smaller keys so we use the following method
 * for generation which WILL be unique within a cluster of machines with unique ips.  The
 * algorithm is VERY simple host-specialtimestamp where special timestamp is time in 
 * millis BUT in the case where two people called this method on the same machine, the last
 * timestamp given was stored so we increment by one such that there will never be 
 * a non-unique key.  
 */
public class UniqueKeyGenerator implements KeyGenerator {

	private static final Logger log = LoggerFactory.getLogger(UniqueKeyGenerator.class);
	private static String ipAddress;
	private static long lastTimeStamp = System.currentTimeMillis();
	
	static {
		try {
			createHostName();
		} catch(Throwable e) {
			log.warn("Could not create a ip needed for unique key gen.\n" +
					"PLEASE if you are on linux configure it properly and\n" +
					" run this simple code to test(this code fails right" +
					" now returning localhost instead of the hostname!!!)\n" +
					"InetAddress local = InetAddress.getLocalHost();\n" +
					"String hostname = local.getHostName();", e);
			
			throw new RuntimeException(e);
		}
	}
	
	@Override
	public String generateNewKey(Object entity) {
		return generateKey();
	}
	
	private static synchronized String generateKey() {
		long time = lastTimeStamp++;
		return time+":"+ipAddress;
	}

	private static void createHostName() throws UnknownHostException {
		InetAddress local = InetAddress.getLocalHost();
		ipAddress = local.getHostName();
		if(ipAddress.contains(".")) {
			//let's strip it down to just the raw host name since all hosts will have the same domain
			int index = ipAddress.indexOf(".");
			ipAddress = ipAddress.substring(0, index);
		}
		
		if(ipAddress.contains("localhost"))
			throw new RuntimeException("Call to InetAddress.getLocalHost().getHostname() == localhost.  This must be fixed(you are most likely on linux!!) or unique keys will not be generated");
	}

}

@@ -101,24 +101,61 @@
 ception;%0D%0A%0D%0A
+import org.joda.time.LocalDateTime;%0D%0A
 import org.s
@@ -1192,16 +1192,22 @@
  static 
+final 
 String i
@@ -1217,16 +1217,18 @@
 dress;%0D%0A
+%0D%0A
 %09private
@@ -1240,16 +1240,153 @@
 ic long 
+lastTimeStamp;%0D%0A%09%0D%0A%09static %7B%0D%0A%09%09LocalDateTime time = new LocalDateTime(2012, 6, 1, 0, 0);%0D%0A%09%09long baseTime = time.toDate().getTime();%0D%0A%09%09
 lastTime
@@ -1419,31 +1419,32 @@
 Millis()
-;%0D%0A%09%0D%0A%09static %7B
+ - baseTime;%0D%0A%09%09
 %0D%0A%09%09try 
@@ -1449,16 +1449,28 @@
 y %7B%0D%0A%09%09%09
+ipAddress = 
 createHo
@@ -2163,12 +2163,14 @@
 tic 
-void
+String
  cre
@@ -2214,16 +2214,35 @@
 tion %7B%0D%0A
+%09%09String address;%0D%0A
 %09%09InetAd
@@ -2286,19 +2286,17 @@
 t();%0D%0A%09%09
-ipA
+a
 ddress =
@@ -2319,27 +2319,25 @@
 me();%0D%0A%09%09if(
-ipA
+a
 ddress.conta
@@ -2458,19 +2458,17 @@
 index = 
-ipA
+a
 ddress.i
@@ -2480,27 +2480,25 @@
 f(%22.%22);%0D%0A%09%09%09
-ipA
+a
 ddress = ipA
@@ -2494,19 +2494,17 @@
 dress = 
-ipA
+a
 ddress.s
@@ -2538,19 +2538,17 @@
 %09%0D%0A%09%09if(
-ipA
+a
 ddress.c
@@ -2753,21 +2753,40 @@
 nerated%22);%0D%0A
+%09%09return address;%0D%0A
 %09%7D%0D%0A%0D%0A%7D%0D%0A

shrink the time down and are numbers are smaller