/*
 * Copyright (c) 2013 Cisco Systems, Inc. and others.  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.yangtools.yang.model.api;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;

/**
 * Contains method which returns various data constraints for a list-like YANG element
 * (e.g. min or max number of elements).
 */
@Beta
public abstract class ElementCountConstraint {
    private static final class Min extends ElementCountConstraint {
        private final int minElements;

        Min(final int minElements) {
            checkArgument(minElements >= 0);
            this.minElements = minElements;
        }

        @Override
        public Integer getMinElements() {
            return minElements;
        }

        @Override
        public Integer getMaxElements() {
            return null;
        }
    }

    private static final class Max extends ElementCountConstraint {
        private final int maxElements;

        Max(final int maxElements) {
            checkArgument(maxElements >= 0);
            this.maxElements = maxElements;
        }

        @Override
        public Integer getMinElements() {
            return null;
        }

        @Override
        public Integer getMaxElements() {
            return maxElements;
        }
    }

    private static final class MinMax extends ElementCountConstraint {
        private final int minElements;
        private final int maxElements;

        MinMax(final int minElements, final int maxElements) {
            checkArgument(minElements >= 0);
            checkArgument(maxElements >= 0);
            checkArgument(minElements <= maxElements);
            this.minElements = minElements;
            this.maxElements = maxElements;
        }

        @Override
        public Integer getMinElements() {
            return minElements;
        }

        @Override
        public Integer getMaxElements() {
            return maxElements;
        }
    }

    ElementCountConstraint() {
        // Hidden on purpose
    }

    public static ElementCountConstraint atLeast(final int minElements) {
        return new Min(minElements);
    }

    public static ElementCountConstraint atMost(final int maxElements) {
        return new Max(maxElements);
    }

    public static ElementCountConstraint inRange(final int minElements, final int maxElements) {
        return new MinMax(minElements, maxElements);
    }

    public static Optional<ElementCountConstraint> forNullable(@Nullable final Integer minElements,
            @Nullable final Integer maxElements) {
        if (minElements == null) {
            return maxElements != null ? Optional.of(new Max(maxElements)) : Optional.empty();
        }

        return Optional.of(maxElements != null ? new MinMax(minElements, maxElements) : new Min(minElements));
    }

    /**
     * Returns the minimum required number of data elements for node where this
     * constraint is specified.
     *
     * <p>
     * The returning value equals to value of the argument of the
     * <b>min-elements</b> YANG substatement.
     * It is used with YANG statements leaf-list, list, deviate.
     *
     * @return integer with minimal number of elements, or null if no minimum is defined
     */
    @Nullable public abstract Integer getMinElements();

    /**
     * Returns the maximum admissible number of data elements for node where
     * this constraint is specified.
     *
     * <p>
     * The returning value equals to value of the argument of the
     * <b>max-elements</b> YANG substatement.
     * It is used with YANG statements leaf-list, list, deviate.
     *
     * @return integer with maximum number of elements, or null if no maximum is defined
     */
    @Nullable public abstract Integer getMaxElements();

    @Override
    public final int hashCode() {
        return Objects.hash(getMinElements(), getMaxElements());
    }

    @Override
    public final boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof ElementCountConstraint)) {
            return false;
        }
        final ElementCountConstraint other = (ElementCountConstraint) obj;
        return Objects.equals(getMinElements(), other.getMinElements())
                && Objects.equals(getMaxElements(), other.getMaxElements());
    }

    @Override
    public final String toString() {
        return MoreObjects.toStringHelper(ElementCountConstraint.class).omitNullValues()
                .add("minElements", getMinElements())
                .add("maxElements", getMaxElements()).toString();
    }
}

@@ -570,13 +570,66 @@
 ort 
-javax
+org.eclipse.jdt.annotation.NonNull;%0Aimport org.eclipse.jdt
 .ann
@@ -2482,32 +2482,41 @@
   public static 
+@NonNull 
 ElementCountCons
@@ -2609,32 +2609,41 @@
   public static 
+@NonNull 
 ElementCountCons
@@ -2743,16 +2743,25 @@
  static 
+@NonNull 
 ElementC
@@ -2909,16 +2909,25 @@
  static 
+@NonNull 
 Optional
@@ -2963,16 +2963,22 @@
 ullable(
+final 
 @Nullabl
@@ -2971,38 +2971,32 @@
 final @Nullable 
-final 
 Integer minEleme
@@ -3008,24 +3008,30 @@
             
+final 
 @Nullable fi
@@ -3028,22 +3028,16 @@
 ullable 
-final 
 Integer 
@@ -3729,34 +3729,24 @@
      */%0A    
-@Nullable 
 public abstr
@@ -3741,32 +3741,42 @@
 public abstract 
+@Nullable 
 Integer getMinEl
@@ -4211,26 +4211,16 @@
  */%0A    
-@Nullable 
 public a
@@ -4227,16 +4227,26 @@
 bstract 
+@Nullable 
 Integer 

Migrate ElementCountConstraint to JDT annotations