package de.sambalmueslie.herold.model;

import java.util.Optional;

import de.sambalmueslie.herold.DataModelChangeListener;
import de.sambalmueslie.herold.DataModelElement;
import de.sambalmueslie.herold.annotations.ChangeListener;
import de.sambalmueslie.herold.annotations.ImplementationType;
import de.sambalmueslie.herold.util.AnnotationSpy;

public class Metadata<T extends DataModelElement> {

	Metadata(Class<T> elementType) {
		this.elementType = elementType;
	}

	public Class<? extends T> getElementImplType() {
		if (implType == null) {
			implType = getImplementationType();
		}
		return implType;
	}

	public Class<T> getElementType() {
		return elementType;
	}

	public Class<? extends DataModelChangeListener<? extends T>> getSpecificListenerType() {
		if (specificListenerType == null) {
			specificListenerType = getListenerType();
		}
		return specificListenerType;
	}

	@SuppressWarnings("unchecked")
	private Class<? extends T> getImplementationType() {
		final Optional<ImplementationType> result = AnnotationSpy.findAnnotation(elementType, ImplementationType.class);
		return result.isPresent() ? (Class<T>) result.get().value() : elementType;
	}

	@SuppressWarnings("unchecked")
	private <S extends DataModelChangeListener<? extends T>> Class<S> getListenerType() {
		final Optional<ChangeListener> result = AnnotationSpy.findAnnotation(elementType, ChangeListener.class);
		return result.isPresent() ? (Class<S>) result.get().value() : (Class<S>) DataModelChangeListener.class;
	}

	private final Class<T> elementType;
	private Class<? extends T> implType;
	private Class<? extends DataModelChangeListener<? extends T>> specificListenerType;
}

@@ -393,16 +393,48 @@
 ent%3E %7B%0A%0A
+%09@SuppressWarnings(%22unchecked%22)%0A
 %09Metadat
@@ -484,32 +484,133 @@
 e = elementType;
+%0A%0A%09%09genericListenerType = (Class%3CDataModelChangeListener%3CT%3E%3E) (Object) DataModelChangeListener.class;
 %0A%09%7D%0A%0A%09public Cla
@@ -1307,32 +1307,34 @@
 uppressWarnings(
+%7B 
 %22unchecked%22)%0A%09pr
@@ -1320,32 +1320,34 @@
 gs(%7B %22unchecked%22
+ %7D
 )%0A%09private %3CS ex
@@ -1341,18 +1341,23 @@
 private 
-%3CS
+Class%3C?
  extends
@@ -1398,17 +1398,8 @@
  T%3E%3E
- Class%3CS%3E
  get
@@ -1514,32 +1514,33 @@
 istener.class);%0A
+%0A
 %09%09return result.
@@ -1564,69 +1564,75 @@
 ass%3C
-S%3E) result.get().value() : (Class%3CS%3E) DataModelChange
+DataModelChangeListener%3CT%3E%3E) result.get().value() : generic
 Listener
 .cla
@@ -1619,38 +1619,36 @@
  genericListener
-.class
+Type
 ;%0A%09%7D%0A%0A%09private f
@@ -1670,24 +1670,94 @@
 lementType;%0A
+%09private final Class%3CDataModelChangeListener%3CT%3E%3E genericListenerType;%0A
 %09private Cla

fix java generics shit