/**
 * Copyright (C) 2014 UpSwell LLC (developers@theupswell.com)
 *
 * 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 com.theupswell.appengine.counter.data.base;

import java.util.UUID;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.annotation.Id;

/**
 * An abstract base class for appengine-counter entities (data stored to the datastore).
 * 
 * @author David Fuelling
 */
@Getter
@Setter
@ToString
@EqualsAndHashCode(of = "id")
public abstract class AbstractDateTimeEntity
{
	@Id
	private String id;

	private DateTime creationDateTime;
	private DateTime updatedDateTime;

	/**
	 * Default Constructor
	 */
	public AbstractDateTimeEntity()
	{
		this(UUID.randomUUID().toString());
	}

	/**
	 * Required Params constructor
	 *
	 * @param id A globally unique identifier (i.e., a {@link UUID} as a String).
	 */
	public AbstractDateTimeEntity(String id)
	{
		this.id = id;
		this.creationDateTime = DateTime.now(DateTimeZone.UTC);
		this.updatedDateTime = DateTime.now(DateTimeZone.UTC);
	}

	/**
	 * By default, Entities have a null parent Key. This is overridden by implementations if a Parent key exists.
	 */
	public Key<?> getParentKey()
	{
		return null;
	}

	/**
	 * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key
	 * heirarchy.
	 * 
	 * @return
	 */
	public <T> Key<T> getTypedKey()
	{
		if (this.getId() == null)
		{
			return null;
		}
		else
		{
			com.google.appengine.api.datastore.Key rawKey = ObjectifyService.factory().getMetadataForEntity(this)
				.getKeyMetadata().getRawKey(this);
			return Key.create(rawKey);
		}
	}

	/**
	 * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key
	 * heirarchy.
	 */
	public com.google.appengine.api.datastore.Key getKey()
	{
		Key<?> typedKey = this.getTypedKey();
		return typedKey == null ? null : typedKey.getRaw();
	}
}

@@ -689,41 +689,8 @@
 D;%0A%0A
-import lombok.EqualsAndHashCode;%0A
 impo
@@ -825,143 +825,8 @@
 e;%0A%0A
-import com.googlecode.objectify.Key;%0Aimport com.googlecode.objectify.ObjectifyService;%0Aimport com.googlecode.objectify.annotation.Id;%0A%0A
 /**%0A
@@ -977,38 +977,94 @@
 ring
-%0A@EqualsAndHashCode(of = %22id%22)
+(callSuper = true)%0A// No @EqualsAndHashCode since we identify by Id in the super-class
 %0Apub
@@ -1108,36 +1108,33 @@
 tity
-%0A%7B%0A%09@Id%0A%09private String id;%0A
+ extends AbstractEntity%0A%7B
 %0A%09pr
@@ -1276,46 +1276,8 @@
 %0A%09%7B%0A
-%09%09this(UUID.randomUUID().toString());%0A
 %09%7D%0A%0A
@@ -1452,20 +1452,17 @@
 %7B%0A%09%09
-this.id = id
+super(id)
 ;%0A%09%09
@@ -1582,915 +1582,6 @@
 %09%7D%0A%0A
-%09/**%0A%09 * By default, Entities have a null parent Key. This is overridden by implementations if a Parent key exists.%0A%09 */%0A%09public Key%3C?%3E getParentKey()%0A%09%7B%0A%09%09return null;%0A%09%7D%0A%0A%09/**%0A%09 * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key%0A%09 * heirarchy.%0A%09 * %0A%09 * @return%0A%09 */%0A%09public %3CT%3E Key%3CT%3E getTypedKey()%0A%09%7B%0A%09%09if (this.getId() == null)%0A%09%09%7B%0A%09%09%09return null;%0A%09%09%7D%0A%09%09else%0A%09%09%7B%0A%09%09%09com.google.appengine.api.datastore.Key rawKey = ObjectifyService.factory().getMetadataForEntity(this)%0A%09%09%09%09.getKeyMetadata().getRawKey(this);%0A%09%09%09return Key.create(rawKey);%0A%09%09%7D%0A%09%7D%0A%0A%09/**%0A%09 * Assembles the Key for this entity. If an Entity has a Parent Key, that key will be included in the returned Key%0A%09 * heirarchy.%0A%09 */%0A%09public com.google.appengine.api.datastore.Key getKey()%0A%09%7B%0A%09%09Key%3C?%3E typedKey = this.getTypedKey();%0A%09%09return typedKey == null ? null : typedKey.getRaw();%0A%09%7D%0A
 %7D%0A

Separate AbstractEntity into two classes