/*
 * Copyright 2017, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * 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 org.spine3.server.aggregate;

import org.spine3.server.BoundedContext;
import org.spine3.server.entity.AbstractEntity;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Common abstract base for repositories that manage {@code AggregatePart}s.
 *
 * @author Alexander Yevsyukov
 */
public abstract class AggregatePartRepository<I, A extends AggregatePart<I, ?, ?>> extends AggregateRepository<I, A> {

    /**
     * {@inheritDoc}
     */
    protected AggregatePartRepository(BoundedContext boundedContext) {
        super(boundedContext);
    }

    @Override // to expose this method in the same package.
    protected Class<I> getIdClass() {
        return super.getIdClass();
    }

    @SuppressWarnings("MethodDoesntCallSuperMethod") // The call of the super metho is not needed.
    @Override
    public A create(I id) {
        try {
            final Constructor<A> entityConstructor =
                    AbstractEntity.getAggregatePartConstructor(getEntityClass(), getIdClass());
            @SuppressWarnings("unchecked")
            // It is OK because it is checked above,
            // in the AbstractEntity.getAggregatePartConstructor method
            final Class<AggregateRoot<I>> rootClass =
                    (Class<AggregateRoot<I>>) entityConstructor.getParameterTypes()[1];
            final Constructor<AggregateRoot<I>> rootConstructor =
                    rootClass.getDeclaredConstructor(getBoundedContext().getClass(), id.getClass());
            rootConstructor.setAccessible(true);
            final AggregateRoot<I> root = rootConstructor.newInstance(getBoundedContext(), id);
            final A result = AbstractEntity.createEntity(entityConstructor, id, root);
            return result;
        } catch (NoSuchMethodException | InvocationTargetException |
                InstantiationException | IllegalAccessException e) {
            throw new IllegalStateException(e);
        }
    }
}

@@ -1180,58 +1180,171 @@
 or;%0A
+%0A
 import 
-java.lang.reflect.InvocationTargetException
+static org.spine3.server.entity.AbstractEntity.createAggregateRootEntity;%0Aimport static org.spine3.server.entity.AbstractEntity.getAggregatePartConstructor
 ;%0A%0A/
@@ -1723,24 +1723,61 @@
 xt);%0A    %7D%0A%0A
+    /**%0A     * %7B@inheritDoc%7D%0A     */%0A
     @Overrid
@@ -2049,26 +2049,8 @@
 ) %7B%0A
-        try %7B%0A    
     
@@ -2114,27 +2114,8 @@
     
-    AbstractEntity.
 getA
@@ -2163,36 +2163,32 @@
  getIdClass());%0A
-    
         @Suppres
@@ -2218,20 +2218,16 @@
         
-    
 // It is
@@ -2259,20 +2259,16 @@
  above,%0A
-    
         
@@ -2331,28 +2331,24 @@
 hod%0A        
-    
 final Class%3C
@@ -2377,20 +2377,16 @@
 Class =%0A
-    
         
@@ -2469,38 +2469,22 @@
         
-    
 final 
-Constructor%3C
 Aggregat
@@ -2495,248 +2495,46 @@
 t%3CI%3E
-%3E
  root
-Constructor =%0A                    rootClass.getDeclaredConstructor(getBoundedContext().getClass(), id.getClass());%0A            rootConstructor.setAccessible(true);%0A            final AggregateRoot%3CI%3E root = rootConstructor.newInstance(
+ = createAggregateRootEntity(id, 
 getB
@@ -2554,17 +2554,20 @@
 (), 
-id);%0A    
+rootClass);%0A
     
@@ -2608,16 +2608,29 @@
 y.create
+AggregatePart
 Entity(e
@@ -2662,28 +2662,24 @@
 t);%0A        
-    
 return resul
@@ -2685,203 +2685,8 @@
 lt;%0A
-        %7D catch (NoSuchMethodException %7C InvocationTargetException %7C%0A                InstantiationException %7C IllegalAccessException e) %7B%0A            throw new IllegalStateException(e);%0A        %7D
 %0A   

Move extracted method to the `AbstractEntity` class.