/*
 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.protocol.bgp.openconfig.routing.policy.statement.actions;

import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.opendaylight.protocol.util.Values;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.AsPathBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.as.path.Segments;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.attributes.as.path.SegmentsBuilder;

abstract class AbstractPrependAsPath {

    static final Attributes prependAS(final Attributes attributes, final AsNumber as) {
        return new AttributesBuilder(attributes)
                .setAsPath(new AsPathBuilder()
                    .setSegments(prependAS(attributes.getAsPath().getSegments(), as))
                    .build())
                .build();
    }

    private static List<Segments> prependAS(final List<Segments> oldSegments, final AsNumber as) {
        if (oldSegments == null || oldSegments.isEmpty()) {
            return ImmutableList.of(singleSequence(as));
        }

        /*
         * We need to check the first segment.
         * If it has as-set then new as-sequence with local AS is prepended.
         * If it has as-sequence, we may add local AS when it has less than 255 elements.
         * Otherwise we need to create new as-sequence for local AS.
         */
        final Iterator<Segments> it = oldSegments.iterator();
        final Segments firstSegment = it.next();
        final List<AsNumber> firstAsSequence = firstSegment.getAsSequence();

        final List<Segments> newSegments;
        if (firstAsSequence != null && firstAsSequence.size() < Values.UNSIGNED_BYTE_MAX_VALUE) {
            final ArrayList<AsNumber> newAsSequence = new ArrayList<>(firstAsSequence.size() + 1);
            newAsSequence.add(as);
            newAsSequence.addAll(firstAsSequence);

            newSegments = new ArrayList<>(oldSegments.size());
            newSegments.add(new SegmentsBuilder().setAsSequence(newAsSequence).build());
        } else {
            newSegments = new ArrayList<>(oldSegments.size() + 1);
            newSegments.add(singleSequence(as));
            newSegments.add(firstSegment);
        }

        it.forEachRemaining(newSegments::add);
        return newSegments;
    }

    private static Segments singleSequence(final AsNumber as) {
        return new SegmentsBuilder().setAsSequence(ImmutableList.of(as)).build();
    }
}

@@ -432,36 +432,8 @@
 st;%0A
-import java.util.ArrayList;%0A
 impo
@@ -1482,28 +1482,24 @@
             
-    
 .setAsPath(n
@@ -1516,37 +1516,16 @@
 uilder()
-%0A                    
 .setSegm
@@ -1585,29 +1585,8 @@
 as))
-%0A                    
 .bui
@@ -1591,20 +1591,16 @@
 uild())%0A
-    
         
@@ -2352,28 +2352,45 @@
       final 
-List
+ImmutableList.Builder
 %3CSegments%3E n
@@ -2515,65 +2515,215 @@
     
-final ArrayList%3CAsNumber%3E newAsSequence = new ArrayList%3C%3E
+newSegments = ImmutableList.%3CSegments%3EbuilderWithExpectedSize(oldSegments.size())%0A                .add(new SegmentsBuilder()%0A                    .setAsSequence(ImmutableList.%3CAsNumber%3EbuilderWithExpectedSize
 (fir
@@ -2738,34 +2738,35 @@
 ence.size() + 1)
-;
 %0A
+  
             newA
@@ -2765,29 +2765,26 @@
     
-newAsSequence
+          
 .add(as)
 ;%0A  
@@ -2779,18 +2779,21 @@
 .add(as)
-;
 %0A
+    
         
@@ -2796,29 +2796,24 @@
         
-newAsSequence
+        
 .addAll(
@@ -2828,19 +2828,24 @@
 equence)
-;%0A%0A
+%0A       
         
@@ -2852,58 +2852,22 @@
     
-newSegments = new ArrayList%3C%3E(oldSegments.size
+     .build
 ())
-;
 %0A   
@@ -2879,74 +2879,16 @@
     
-newSegments.add(new SegmentsBuilder().setAsSequence(newAsSequence)
+        
 .bui
@@ -2941,23 +2941,55 @@
 s = 
-new ArrayList%3C%3E
+ImmutableList.%3CSegments%3EbuilderWithExpectedSize
 (old
@@ -3008,18 +3008,20 @@
 e() + 1)
-;
 %0A
+   
         
@@ -3020,35 +3020,25 @@
             
-newSegments
+ 
 .add(singleS
@@ -3041,33 +3041,32 @@
 gleSequence(as))
-;
 %0A            new
@@ -3062,27 +3062,20 @@
         
-newSegments
+    
 .add(fir
@@ -3166,24 +3166,32 @@
  newSegments
+.build()
 ;%0A    %7D%0A%0A   

Use ImmutableLists in AbstractPrependAsPath