blob: 1da4239ce3025a0088338070ab32dc52fa8ea596 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.openide.util.lookup;
import org.openide.util.Lookup;
import java.io.*;
import java.util.*;
import org.openide.util.lookup.AbstractLookup.Pair;
/** Storages that can switch between another storages.
* @author Jaroslav Tulach
*/
final class DelegatingStorage<Transaction> extends Object
implements Serializable, AbstractLookup.Storage<Transaction> {
/** object to delegate to */
private AbstractLookup.Storage<Transaction> delegate;
/** thread just accessing the storage */
private Thread owner;
public DelegatingStorage(AbstractLookup.Storage<Transaction> d) {
this.delegate = d;
this.owner = Thread.currentThread();
}
/** Never serialize yourself, always put there the delegate */
public Object writeReplace() {
return this.delegate;
}
/** Method to check whether there is not multiple access from the same thread.
*/
public void checkForTreeModification() {
if (Thread.currentThread() == owner) {
throw new AbstractLookup.ISE("You are trying to modify lookup from lookup query!"); // NOI18N
}
}
/** Checks whether we have simple behaviour or complex.
*/
public static boolean isSimple(AbstractLookup.Storage s) {
if (s instanceof DelegatingStorage) {
return ((DelegatingStorage) s).delegate instanceof ArrayStorage;
} else {
return s instanceof ArrayStorage;
}
}
/** Exits from the owners ship of the storage.
*/
public AbstractLookup.Storage<Transaction> exitDelegate() {
if (Thread.currentThread() != owner) {
throw new IllegalStateException("Onwer: " + owner + " caller: " + Thread.currentThread()); // NOI18N
}
AbstractLookup.Storage<Transaction> d = delegate;
delegate = null;
return d;
}
public boolean add(AbstractLookup.Pair<?> item, Transaction transaction) {
return delegate.add(item, transaction);
}
public void remove(org.openide.util.lookup.AbstractLookup.Pair item, Transaction transaction) {
delegate.remove(item, transaction);
}
public void retainAll(Map retain, Transaction transaction) {
delegate.retainAll(retain, transaction);
}
/** A special method to change the backing storage.
* In fact it is not much typesafe as it changes the
* type of Transaction but we know that nobody is currently
* holding a transaction object, so there cannot be inconsitencies.
*/
@SuppressWarnings("unchecked")
private void changeDelegate(InheritanceTree st) {
delegate = (AbstractLookup.Storage<Transaction>)st;
}
public Transaction beginTransaction(int ensure) {
try {
return delegate.beginTransaction(ensure);
} catch (UnsupportedOperationException ex) {
// let's convert to InheritanceTree
ArrayStorage arr = (ArrayStorage) delegate;
InheritanceTree inh = new InheritanceTree();
changeDelegate(inh);
//
// Copy content
//
Enumeration<Pair<Object>> en = arr.lookup(Object.class);
while (en.hasMoreElements()) {
if (!inh.add(en.nextElement(), new ArrayList<Class>())) {
throw new IllegalStateException("All objects have to be accepted"); // NOI18N
}
}
//
// Copy listeners
//
AbstractLookup.ReferenceToResult<?> ref = arr.cleanUpResult(null);
if (ref != null) {
ref.cloneList(inh);
}
// we have added the current content and now we can start transaction
return delegate.beginTransaction(ensure);
}
}
public org.openide.util.lookup.AbstractLookup.ReferenceToResult cleanUpResult(
org.openide.util.Lookup.Template templ
) {
return delegate.cleanUpResult(templ);
}
public void endTransaction(Transaction transaction, Set<AbstractLookup.R> modified) {
delegate.endTransaction(transaction, modified);
}
public <T> Enumeration<Pair<T>> lookup(Class<T> clazz) {
return delegate.lookup(clazz);
}
public org.openide.util.lookup.AbstractLookup.ReferenceToResult registerReferenceToResult(
org.openide.util.lookup.AbstractLookup.ReferenceToResult newRef
) {
return delegate.registerReferenceToResult(newRef);
}
@Override
public <T> Lookup.Result<T> findResult(Lookup.Template<T> template) {
return delegate.findResult(template);
}
}