package ch.cyberduck.core; /* * Copyright (c) 2005 David Kocher. All rights reserved. * http://cyberduck.ch/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 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 General Public License for more details. * * Bug fixes, suggestions and comments should be sent to: * dkocher@cyberduck.ch */ import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; /** * @version $Id: AttributedList.java 5543 2009-11-08 00:10:56Z dkocher $ */ public class AttributedList<E extends AbstractPath> extends CopyOnWriteArrayList<E> { //primary attributes protected static final String FILTER = "FILTER"; protected static final String COMPARATOR = "COMPARATOR"; protected static final String HIDDEN = "HIDDEN"; /** * file listing has changed; the cached version should be superseded */ private static final String INVALID = "INVALID"; /** * file listing is not readable; permission issue */ private static final String READABLE = "READABLE"; private Attributes<E> attributes; /** * Initialize an attributed list with default attributes */ public AttributedList() { this.attributes = new Attributes<E>(); } public AttributedList(java.util.Collection<E> collection) { this.attributes = new Attributes<E>(); this.addAll(collection); } private static final AttributedList<AbstractPath> EMPTY_LIST = new EmptyList(); public static <T extends AbstractPath> AttributedList<T> emptyList() { return (AttributedList<T>) EMPTY_LIST; } private static class EmptyList extends AttributedList<AbstractPath> { @Override public int size() { return 0; } @Override public boolean contains(Object obj) { return false; } @Override public AbstractPath get(int index) { throw new IndexOutOfBoundsException("Index: " + index); } // Preserves singleton property private Object readResolve() { return EMPTY_LIST; } } /** * Container for file listing attributes, such as a sorting comparator and filter * * @see PathFilter * @see BrowserComparator */ public class Attributes<E> extends HashMap<String, Object> { /** * Initialize with default values */ public Attributes() { this.put(FILTER, new NullPathFilter()); this.put(COMPARATOR, new NullComparator<E>()); this.put(HIDDEN, new HashSet()); this.put(INVALID, Boolean.FALSE); this.put(READABLE, Boolean.TRUE); } public Attributes(Comparator<E> comparator, PathFilter filter) { this.put(COMPARATOR, comparator); this.put(FILTER, filter); this.put(HIDDEN, new HashSet()); this.put(INVALID, Boolean.FALSE); this.put(READABLE, Boolean.TRUE); } public void addHidden(E child) { ((Set<E>) this.get(HIDDEN)).add(child); } public Set<E> getHidden() { return (Set<E>) this.get(HIDDEN); } public void setReadable(boolean readable) { this.put(READABLE, readable); } public boolean isReadable() { return this.get(READABLE).equals(Boolean.TRUE); } /** * Mark cached listing as superseded * * @param dirty */ public void setDirty(boolean dirty) { this.put(INVALID, dirty); if(dirty) { this.put(READABLE, Boolean.TRUE); } } /** * @return true if the listing should be superseded */ public boolean isDirty() { return this.get(INVALID).equals(Boolean.TRUE); } } public Attributes<E> attributes() { return attributes; } private Map<PathReference, E> references = new HashMap<PathReference, E>(); @Override public boolean add(E path) { references.put(path.getReference(), path); return super.add(path); } @Override public boolean addAll(java.util.Collection<? extends E> c) { for(E item : c) { references.put(item.getReference(), item); } return super.addAll(c); } public E get(PathReference reference) { return references.get(reference); } @Override public void clear() { attributes.clear(); references.clear(); super.clear(); } }