All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sk.uniq.protobuf.schema.impl.ProtoSyntaxElementImpl Maven / Gradle / Ivy

/* 
 * Copyright 2016 Jakub Herkel.
 *
 * 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 sk.uniq.protobuf.schema.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import sk.uniq.protobuf.schema.ProtoPosition;
import sk.uniq.protobuf.schema.ProtoComments;
import sk.uniq.protobuf.schema.ProtoSyntaxElement;

/**
 *
 * @author jherkel
 */
public abstract class ProtoSyntaxElementImpl implements ProtoSyntaxElement {

    private final ProtoPosition position;
    private final ProtoComments comments;
    private final List elements;

    /**
     *
     * @param builder
     */
    public ProtoSyntaxElementImpl(Builder builder) {
        if (builder.position == null) {
            throw new IllegalArgumentException("position == null");
        }
        if (builder.comments == null) {
            throw new IllegalArgumentException("comments == null");
        }
        Set allowedTypes = getAllowedElements();
        if (builder.elements != null) {
            for (ProtoSyntaxElement element : (List) builder.elements) {
                if (allowedTypes.contains(element.getType()) == false) {
                    throw new IllegalArgumentException(String.format("Nested element %s is not allowed for this element %s", element.getType(), getType()));
                }
            }
        }
        this.position = builder.position;
        this.comments = builder.comments;
        this.elements = builder.elements == null ? Collections.EMPTY_LIST : Collections.unmodifiableList(builder.elements);
    }

    /**
     *
     * @return
     */
    @Override
    public ProtoPosition getPosition() {
        return position;
    }

    /**
     *
     * @return
     */
    @Override
    public ProtoComments getComments() {
        return comments;
    }

    @Override
    public List getNestedElements() {
        return elements;
    }

    @Override
    public  List getFilteredNestedElements(ElementType type) {
        return elements.stream().filter(line -> line.getType() == type)
                .map(c -> (T) c).collect(Collectors.toList());
    }

    @Override
    public List getFilteredNestedElements(Set types) {
        return elements.stream().filter(line -> types.contains(line.getType()))
                .collect(Collectors.toList());
    }     
    
    /**
     *
     * @param 
     */
    public static abstract class Builder> {

        private ProtoPosition position = ProtoPosition.EMPTY_POSITION;
        private ProtoComments comments = ProtoComments.EMPTY;
        private List elements;

        /**
         *
         * @param position
         * @return
         */
        public B position(ProtoPosition position) {
            this.position = position;
            return (B) this;
        }

        /**
         *
         * @param comments
         * @return
         */
        public B comments(ProtoComments comments) {
            this.comments = comments;
            return (B) this;
        }

        /**
         *
         * @param element
         * @return
         */
        public B addNestedElement(ProtoSyntaxElement element) {
            if (element == null) {
                throw new IllegalArgumentException("Element must be not null");
            }
            if (this.elements == null) {
                this.elements = new ArrayList<>();
            }
            this.elements.add(element);
            return (B) this;
        }

        /**
         *
         * @param elements
         * @return
         */
        public B addAllNestedElements(Collection elements) {
            for (ProtoSyntaxElement element : elements) {
                if (element == null) {
                    throw new IllegalArgumentException("Element must be not null");
                }
            }
            if (this.elements == null) {
                this.elements = new ArrayList<>(elements.size());
            }
            this.elements.addAll(elements);
            return (B) this;
        }

        /**
         *
         * @return
         */
        public abstract Object build();

    }

}