package org.hcjf.layers.crud;

import org.hcjf.layers.Layer;
import org.hcjf.layers.query.Query;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;
import java.util.Map;

/**
 * This layer implements the {@link CrudLayerInterface}
 * @author javaito
 * @email javaito@gmail.com
 */
public abstract class CrudLayer<O extends Object> extends Layer implements CrudLayerInterface<O> {

    public CrudLayer(String implName) {
        super(implName);
    }

    public CrudLayer() {
    }

    /**
     * This method return the resource class of the layer.
     * @return Resource class.
     */
    public final Class<O> getResourceType() {
        Class<O> resourceClass = (Class<O>)
                ((ParameterizedType)getClass().getGenericSuperclass()).
                        getActualTypeArguments()[0];
        return resourceClass;
    }

    /**
     * This method implements the creation of the resource.
     *
     * @param object     Object to represents an instance of the resource.
     * @param parameters Some parameters that could be necessaries
     *                   in order to create an instance of the resource.
     * @return The instance of the resource.
     */
    @Override
    public O create(O object, Map<String, Object> parameters) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the creation of the resource.
     * @param object Object to represents an instance of the resource.
     * @return The instance of the resource.
     */
    @Override
    public O create(O object) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the read operation to find an instance of
     * the resource using only it's id.
     *
     * @param id Id to found the instance.
     * @return Return the instance founded or null if the instance is not found.
     */
    @Override
    public O read(Object id) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the update of the resource.
     *
     * @param object     Instance of the resource that gonna be updated.
     *                   This instance must have an id to identify the updatable data.
     * @param parameters Some parameters that could be necessaries
     *                   in order to update an instance of the resource.
     * @return The instance updated.
     */
    @Override
    public O update(O object, Map<String, Object> parameters) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the update of the resource.
     * @param object Instance of the resource that gonna be updated.
     *               This instance must have an id to identify the updatable data.
     * @return The instance updated.
     */
    @Override
    public O update(O object) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the delete operation over the resource.
     *
     * @param id Id of the instance that gonna be deleted.
     * @return Instance of the resource that was deleted.
     */
    @Override
    public O delete(Object id) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the read operation using the filters
     * specified in the query.
     * @param query Query.
     * @return Return the list with the instances founded.
     */
    @Override
    public Collection<O> read(Query query) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the read operation without filters.
     *
     * @return List with all the instances of the resource.
     */
    @Override
    public Collection<O> read() {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the read operation using the filters
     * specified in the query.
     *
     * @param queryId Id of the query.
     * @return Return the list with the instances founded.
     */
    @Override
    public Collection<O> read(Query.QueryId queryId) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the update operation over a add of the instances,
     * this instances are selected using the query like a filter.
     *
     * @param queryId    Id of the query.
     * @param parameters Values that contains the information to update the
     *                   instances.
     * @return Return the instances updated.
     */
    @Override
    public Collection<O> update(Query.QueryId queryId, Map<String, Object> parameters) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the delete operation over a add of the instances.
     * This instances are selected using the query like a filter.
     *
     * @param queryId Id of the query.
     * @return Return the instances deleted.
     */
    @Override
    public Collection<O> delete(Query.QueryId queryId) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the read operation over the add of query created.
     *
     * @param queryId Id of the query.
     * @return Return the instance of the resource's query.
     */
    @Override
    public Query readQuery(Query.QueryId queryId) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the create operation of the resource's query.
     *
     * @param query
     * @param parameters Some parameters that could be necessaries
     *                   in order to create an instance of the resource's query.
     * @return Instance of the resource's query.
     */
    @Override
    public Query createQuery(Query query, Map<String, Object> parameters) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the update operation of the resource's query.
     *
     * @param query      Instance of the resource's query that gonna be updated.
     *                   This instance must have an id to identify the updatable data.
     * @param parameters Some parameters that could be necessaries
     *                   in order to update an instance of the resource's query.
     * @return Updated instance of the resource's query.
     */
    @Override
    public Query updateQuery(Query query, Map<String, Object> parameters) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method implements the delete operation of the resource's query.
     *
     * @param queryId Id of the query.
     * @return Deleted instance of the resource's query.
     */
    @Override
    public Query deleteQuery(Query.QueryId queryId) {
        throw new UnsupportedOperationException();
    }
}

@@ -135,16 +135,47 @@
 edType;%0A
+import java.lang.reflect.Type;%0A
 import j
@@ -216,16 +216,42 @@
 til.Map;
+%0Aimport java.util.Objects;
 %0A%0A/**%0A *
@@ -745,21 +745,50 @@
 lass
- = (
+;%0A        Class currentClass = get
 Class
-%3CO%3E)
+();
 %0A   
@@ -796,124 +796,616 @@
     
-        ((ParameterizedType)getClass().getGenericSuperclass()).%0A                        getActualTypeArguments()%5B0%5D;
+Type genericSuperClass = currentClass.getGenericSuperclass();%0A        while(currentClass != Object.class &&%0A                !(genericSuperClass instanceof ParameterizedType)) %7B%0A            currentClass = currentClass.getSuperclass();%0A            genericSuperClass = currentClass.getGenericSuperclass();%0A        %7D%0A%0A        if(genericSuperClass instanceof ParameterizedType) %7B%0A            resourceClass = (Class%3CO%3E)%0A                    ((ParameterizedType)genericSuperClass).%0A                            getActualTypeArguments()%5B0%5D;%0A        %7D else %7B%0A            throw new IllegalArgumentException();%0A        %7D%0A
 %0A   

Check all the inheritance branch to known parameterized type of the crud