    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.jxpath;
    019
    020import java.util.ArrayList;
    021import java.util.Collections;
    022import java.util.List;
    023import java.util.stream.Collectors;
    024
    025/**
    026 * A simple implementation of {@link NodeSet} that behaves as a collection of pointers.
    027 */
    028public class BasicNodeSet implements NodeSet {
    029
    030    private final List<Pointer> pointers = new ArrayList<>();
    031    private List<Pointer> readOnlyPointers;
    032    private List nodes;
    033    private List values;
    034
    035    /**
    036     * Constructs a new instance.
    037     */
    038    public BasicNodeSet() {
    039        // empty
    040    }
    041
    042    /**
    043     * Add the specified NodeSet to this NodeSet.
    044     *
    045     * @param nodeSet to add
    046     */
    047    public void add(final NodeSet nodeSet) {
    048        if (pointers.addAll(nodeSet.getPointers())) {
    049            clear();
    050        }
    051    }
    052
    053    /**
    054     * Add a pointer to this NodeSet.
    055     *
    056     * @param pointer to add
    057     */
    058    public void add(final Pointer pointer) {
    059        if (pointers.add(pointer)) {
    060            clear();
    061        }
    062    }
    063
    064    /**
    065     * Clear cache list members.
    066     */
    067    private synchronized void clear() {
    068        readOnlyPointers = null;
    069        nodes = null;
    070        values = null;
    071    }
    072
    073    @Override
    074    public synchronized List getNodes() {
    075        if (nodes == null) {
    076            nodes = Collections.unmodifiableList(pointers.stream().map(Pointer::getNode).collect(Collectors.toList()));
    077        }
    078        return nodes;
    079    }
    080
    081    @Override
    082    public synchronized List<Pointer> getPointers() {
    083        if (readOnlyPointers == null) {
    084            readOnlyPointers = Collections.unmodifiableList(pointers);
    085        }
    086        return readOnlyPointers;
    087    }
    088
    089    @Override
    090    public synchronized List getValues() {
    091        if (values == null) {
    092            values = Collections.unmodifiableList(pointers.stream().map(Pointer::getValue).collect(Collectors.toList()));
    093        }
    094        return values;
    095    }
    096
    097    /**
    098     * Remove a pointer from this NodeSet.
    099     *
    100     * @param pointer to remove
    101     */
    102    public void remove(final Pointer pointer) {
    103        if (pointers.remove(pointer)) {
    104            clear();
    105        }
    106    }
    107
    108    @Override
    109    public String toString() {
    110        return pointers.toString();
    111    }
    112}