/*******************************************************************************
* Copyright (c) 2000, 2011 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.springsource.ide.eclipse.commons.completions.externaltype.indexing;
import org.eclipse.core.runtime.Assert;
import org.springsource.ide.eclipse.commons.completions.externaltype.ExternalType;
import org.springsource.ide.eclipse.commons.completions.externaltype.ExternalTypeDiscovery;
import org.springsource.ide.eclipse.commons.completions.externaltype.ExternalTypeSource;
import org.springsource.ide.eclipse.commons.completions.util.Requestor;
/**
* An ExternalTypeIndexer instance is responsible for building up a searchable index
* mapping {@link ExternalType}s to a {@link ExternalTypeSource}s.
* <p>
* Building the index is a potentially very long operation and should be done asyncronously.
* Also methods that allow clients to consult the index should be implemented in such a way
* that they can be used safely on an incomplete index, without blocking for extended periods of
* time.
*
* @author Kris De Volder
*/
public abstract class ExternalTypeIndexer {
/**
* This provides the means to iterate all external types currently in the index.
*/
public abstract void getAll(Requestor<ExternalType> requestor);
/**
* Add a bunch of types to the indexer. This can potentially take a very long time.
* Thus this operation is normally implemented asynchronously. I.e. types will be indexed
* eventually but may not be indexed before the method returns.
*/
public abstract void addFrom(ExternalTypeDiscovery ets);
/**
* Subclasses realy *should* override this method. The implementation here serves only
* as a 'specification' of the expected behavior but it is highly ineffecient. A proper
* indexed implementation should use the index to avoid iterating everything.
*/
public void getByPrefix(final String prefix, final Requestor<ExternalType> requestor) {
getAll(new Requestor<ExternalType>() {
public boolean receive(ExternalType element) {
if (element.getName().startsWith(prefix)) {
return requestor.receive(element);
}
return true;
}
});
}
/**
* Find an ExternalTypeSource associated with the given type. If more than one source exists
* an arbitrary source is returned. If no source is found the {@link ExternalTypeSource}.UNKNOWN
* instance is returned.
*/
public abstract ExternalTypeSource getSource(ExternalType type);
/**
* TRivial implementation of an empty index. You can't store anything in it and requesting any
* information from it returns nothing.
* <p>
* Usually it is more appropriate to use this instance instead of 'null'. As it won't cause NPEs
* when trying to retrieve data from it.
*/
public static final ExternalTypeIndexer EMPTY = new ExternalTypeIndexer() {
@Override
public ExternalTypeSource getSource(ExternalType type) {
return null;
}
@Override
public void getAll(Requestor<ExternalType> requestor) {
//Nothing to do.
}
@Override
public void addFrom(ExternalTypeDiscovery ets) {
Assert.isLegal(false, "EMPTY index is immutable");
}
};
}