blob: e01d34127f57aa1377fc7d463299ff456cf0189c [file] [log] [blame]
/*
* Copyright (c) 2011, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.jpql.tools.model.query;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.eclipse.persistence.jpa.jpql.tools.model.IListChangeListener;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;
/**
* The abstraction definition of a {@link StateObject} that holds onto a list of children, the
* methods defined in {@link ListHolderStateObject} are automatically handled here.
*
* @version 2.4
* @since 2.4
* @author Pascal Filion
*/
public abstract class AbstractListHolderStateObject<T extends StateObject> extends AbstractStateObject
implements ListHolderStateObject<T> {
/**
* The list of children owned by this one.
*/
private List<T> items;
/**
* Creates a new <code>AbstractListHolderStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
protected AbstractListHolderStateObject(StateObject parent) {
super(parent);
}
/**
* Creates a new <code>AbstractListHolderStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param items The list of {@link StateObject StateObjects} to add as children to this one
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
protected AbstractListHolderStateObject(StateObject parent, List<? extends T> items) {
super(parent);
this.items = new ArrayList<T>(items);
parent(items);
}
/**
* Creates a new <code>AbstractListHolderStateObject</code>.
*
* @param parent The parent of this state object, which cannot be <code>null</code>
* @param items The list of {@link StateObject StateObjects} to add as children to this one
* @exception NullPointerException The given parent cannot be <code>null</code>
*/
protected AbstractListHolderStateObject(StateObject parent, T... items) {
super(parent);
this.items = new ArrayList<>();
Collections.addAll(this.items, parent(items));
}
@Override
protected void addChildren(List<StateObject> children) {
super.addChildren(children);
children.addAll(items);
}
@Override
public <S extends T> S addItem(S item) {
getChangeSupport().addItem(this, this.items, listName(), parent(item));
return item;
}
@Override
public void addItems(List<? extends T> items) {
getChangeSupport().addItems(this, this.items, listName(), parent(items));
}
@Override
public void addListChangeListener(String listName, IListChangeListener<T> listener) {
getChangeSupport().addListChangeListener(listName, listener);
}
/**
* Determines whether the children of this {@link StateObject} are equivalent to the children
* of the given one, i.e. the information of the {@link StateObject StateObjects} is the same.
*
* @param stateObject The {@link StateObject} to compare its children to this one's children
* @return <code>true</code> if both have equivalent children; <code>false</code> otherwise
*/
protected boolean areChildrenEquivalent(AbstractListHolderStateObject<? extends StateObject> stateObject) {
int size = itemsSize();
if (size != stateObject.itemsSize()) {
return false;
}
for (int index = size; --index >= 0; ) {
StateObject child1 = getItem(index);
StateObject child2 = stateObject.getItem(index);
if (!child1.isEquivalent(child2)) {
return false;
}
}
return true;
}
@Override
public boolean canMoveDown(T stateObject) {
return getChangeSupport().canMoveDown(items, stateObject);
}
@Override
public boolean canMoveUp(T stateObject) {
return getChangeSupport().canMoveUp(items, stateObject);
}
@Override
public T getItem(int index) {
return items.get(index);
}
@Override
public boolean hasItems() {
return !items.isEmpty();
}
@Override
protected void initialize() {
super.initialize();
items = new ArrayList<T>();
}
@Override
public ListIterable<? extends T> items() {
return new SnapshotCloneListIterable<T>(items);
}
@Override
public int itemsSize() {
return items.size();
}
/**
* Returns the name that is uniquely identifying the list.
*
* @return The unique name identifying the list
*/
protected abstract String listName();
@Override
public T moveDown(T item) {
getChangeSupport().moveDown(this, items, listName(), item);
return item;
}
@Override
public T moveUp(T item) {
getChangeSupport().moveUp(this, items, listName(), item);
return item;
}
@Override
public void removeItem(T stateObject) {
getChangeSupport().removeItem(this, items, listName(), stateObject);
}
@Override
public void removeItems(Collection<T> items) {
getChangeSupport().removeItems(this, this.items, listName(), items);
}
@Override
public void removeListChangeListener(String listName, IListChangeListener<T> listener) {
getChangeSupport().removeListChangeListener(listName, listener);
}
/**
* Adds to the given writer a crude string representation of the children of this one.
*
* @param writer The writer used to print out the string representation
* @param useComma Determines whether a comma should be added after each item, except after the
* last one
* @throws IOException This should never happens, only required because {@link Appendable} is
* used instead of {@link StringBuilder} for instance
*/
protected void toStringItems(Appendable writer, boolean useComma) throws IOException {
toStringItems(writer, items, useComma);
}
}