org.sonar.javascript.model.internal.SeparatedList.java Source code

Java tutorial

Introduction

Here is the source code for org.sonar.javascript.model.internal.SeparatedList.java

Source

/*
 * SonarQube JavaScript Plugin
 * Copyright (C) 2011 SonarSource and Eriks Nukis
 * sonarqube@googlegroups.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
 */
package org.sonar.javascript.model.internal;

import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.UnmodifiableIterator;
import com.sonar.sslr.api.AstNode;
import org.apache.commons.collections.ListUtils;
import org.sonar.javascript.model.internal.lexical.InternalSyntaxToken;
import org.sonar.plugins.javascript.api.tree.Tree;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class SeparatedList<T> implements List<T> {

    private final List<T> list;
    private final List<InternalSyntaxToken> separators;
    /**
     * +   * FIXME to remove when remove use of AstNode
     * +   * /!\ HACK: Use only to be able to pass the AstNode children to the parent in order.
     * +   * this list is used temporary during construction of the AST. It might be empty
     * +   * and/or not up to date.
     * +
     */
    private List<AstNode> children = ListUtils.EMPTY_LIST;

    public SeparatedList(List<T> list, List<InternalSyntaxToken> separators) {
        Preconditions.checkArgument(list.size() == separators.size() + 1 || list.size() == separators.size(),
                "Instanciating a SeparatedList with inconsistent number of elements (%s) and separators (%s)",
                list.size(), separators.size());
        this.list = list;
        this.separators = separators;
    }

    public SeparatedList(List<T> list, List<InternalSyntaxToken> separators, List<AstNode> children) {
        this(list, separators);
        this.children = children;
    }

    public InternalSyntaxToken getSeparator(int i) {
        return separators.get(i);
    }

    public List<InternalSyntaxToken> getSeparators() {
        return separators;
    }

    public void addChild(AstNode child) {
        children.add(child);
    }

    public List<AstNode> getChildren() {
        return children;
    }

    public void clearChildren() {
        children = ListUtils.EMPTY_LIST;
    }

    @Override
    public int size() {
        return list.size();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        return list.contains(o);
    }

    @Override
    public Iterator<T> iterator() {
        return list.iterator();
    }

    @Override
    public Object[] toArray() {
        return list.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }

    @Override
    public boolean add(T e) {
        return list.add(e);
    }

    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        return list.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        return list.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }

    @Override
    public void clear() {
        list.clear();
    }

    @Override
    public T get(int index) {
        return list.get(index);
    }

    @Override
    public T set(int index, T element) {
        return list.set(index, element);
    }

    @Override
    public void add(int index, T element) {
        list.add(index, element);
    }

    @Override
    public T remove(int index) {
        return list.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }

    @Override
    public ListIterator<T> listIterator() {
        return list.listIterator();
    }

    @Override
    public ListIterator<T> listIterator(int index) {
        return list.listIterator(index);
    }

    @Override
    public List<T> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }

    public Iterator<Tree> elementsAndSeparators(final Function<T, ? extends Tree> elementTransformer) {
        return new ElementAndSeparatorIterator(elementTransformer);
    }

    private final class ElementAndSeparatorIterator extends UnmodifiableIterator<Tree> {

        private final Function<T, ? extends Tree> elementTransformer;
        private final Iterator<T> elementIterator = list.iterator();
        private final Iterator<InternalSyntaxToken> separatorIterator = separators.iterator();
        private boolean nextIsElement = true;

        private ElementAndSeparatorIterator(Function<T, ? extends Tree> elementTransformer) {
            this.elementTransformer = elementTransformer;
        }

        @Override
        public boolean hasNext() {
            return elementIterator.hasNext() || separatorIterator.hasNext();
        }

        @Override
        public Tree next() {
            Tree next = nextIsElement ? elementTransformer.apply(elementIterator.next()) : separatorIterator.next();
            nextIsElement = !nextIsElement;
            return next;
        }
    }

}