/*
 * Copyright 2014-2017 Real Logic Ltd.
 *
 * 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 org.agrona.concurrent;

import java.util.Arrays;
import java.util.List;

/**
 * Group several {@link Agent}s into one composite so they can be scheduled as a unit.
 */
public class CompositeAgent implements Agent
{
    private final Agent[] agents;
    private final String roleName;

    /**
     * @param agents the parts of this composite, at least one agent and no null agents allowed
     * @throws IllegalArgumentException if an empty array of agents is provided
     * @throws NullPointerException     if the array or any element is null
     */
    public CompositeAgent(final List<? extends Agent> agents)
    {
        this(agents.toArray(new Agent[agents.size()]));
    }

    /**
     * @param agents the parts of this composite, at least one agent and no null agents allowed
     * @throws IllegalArgumentException if an empty array of agents is provided
     * @throws NullPointerException     if the array or any element is null
     */
    public CompositeAgent(final Agent... agents)
    {
        if (agents == null)
        {
            throw new NullPointerException("Expecting at least one Agent");
        }

        if (agents.length == 0)
        {
            throw new IllegalArgumentException("Expecting at least one Agent");
        }

        final StringBuilder sb = new StringBuilder(agents.length * 16);
        sb.append('[');
        for (final Agent agent : agents)
        {
            if (agent == null)
            {
                throw new NullPointerException("Agents list contains a null");
            }

            sb.append(agent.roleName()).append(',');
        }

        sb.setCharAt(sb.length() - 1, ']');
        roleName = sb.toString();

        this.agents = Arrays.copyOf(agents, agents.length);
    }

    public int doWork() throws Exception
    {
        int workCount = 0;

        for (final Agent agent : agents)
        {
            workCount += agent.doWork();
        }

        return workCount;
    }

    /**
     * {@inheritDoc}
     * <p>
     * Note that one agent throwing an exception on close may result in other agents not being closed.
     */
    public void onClose()
    {
        for (final Agent agent : agents)
        {
            agent.onClose();
        }
    }

    /**
     * {@inheritDoc}
     * <p>
     * Note that one agent throwing an exception on start may result in other agents not being started.
     */
    public void onStart()
    {
        for (final Agent agent : agents)
        {
            agent.onStart();
        }
    }

    public String roleName()
    {
        return roleName;
    }
}

@@ -642,22 +642,20 @@
 va.util.
-Arrays
+List
 ;%0Aimport
@@ -665,20 +665,23 @@
 va.util.
-List
+Objects
 ;%0A%0A/**%0A 
@@ -1621,20 +1621,21 @@
     
-if (
+this.
 agents =
 = nu
@@ -1634,244 +1634,34 @@
 ts =
-= null)%0A        %7B%0A            throw new NullPointerException(%22Expecting at least one Agent%22);%0A        %7D%0A%0A        if (agents.length == 0)%0A        %7B%0A            throw new IllegalArgumentException(%22Expecting at least one Agent%22);%0A        %7D
+ new Agent%5Bagents.length%5D;
 %0A%0A  
@@ -1750,24 +1750,43 @@
 ppend('%5B');%0A
+        int i = 0;%0A
         for 
@@ -1840,134 +1840,62 @@
     
-if (agent == null)%0A            %7B%0A                throw new NullPointerException(%22Agents list contains a null%22);%0A            %7D%0A
+Objects.requireNonNull(agent, %22Agent cannot be null%22);
 %0A   
@@ -1940,24 +1940,62 @@
 ppend(',');%0A
+            this.agents%5Bi++%5D = agent;%0A
         %7D%0A%0A 
@@ -2074,280 +2074,8 @@
 g();
-%0A%0A        this.agents = Arrays.copyOf(agents, agents.length);%0A    %7D%0A%0A    public int doWork() throws Exception%0A    %7B%0A        int workCount = 0;%0A%0A        for (final Agent agent : agents)%0A        %7B%0A            workCount += agent.doWork();%0A        %7D%0A%0A        return workCount;
 %0A   
@@ -2337,24 +2337,24 @@
 .onClose();%0A
-
         %7D%0A  
@@ -2350,32 +2350,243 @@
        %7D%0A    %7D%0A%0A
+    public int doWork() throws Exception%0A    %7B%0A        int workCount = 0;%0A%0A        for (final Agent agent : agents)%0A        %7B%0A            workCount += agent.doWork();%0A        %7D%0A%0A        return workCount;%0A    %7D%0A%0A
     /**%0A     * %7B

Tidy up CompositeAgent class to be consistent with DynamicCompositeAgent.