/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.core.index;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.TransactionRunnable;
import org.teiid.designer.core.builder.ModelBuildUtil;
import org.teiid.designer.core.transaction.UnitOfWork;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.core.workspace.ModelWorkspaceManager;
/**
* ModelResourceIndexSelector finds all index files associated with any projects and resources within the model workspace
*
* @since 8.0
*/
public class ModelWorkspaceSearchIndexSelector extends TargetLocationIndexSelector {
private static final Index[] EMPTY_INDEX_ARRAY = new Index[0];
private Collection resources = null;
IProgressMonitor monitor;
// if this is set to true, we were constructed with a set of resources, which
// implies that we have been handed a 'selection' scope for a real search.
// We need to know this so that we can handle the alternate case:
// if no resources are provided, default to 'workspace' scope.
// This is the treatment required by classes like FindRelatedObjectsCommandImpl.
private final boolean bCreatedWithResources;
private boolean indexesForCreatedResourcesAreSet = false;
private Index[] cachedIndexes = null;
/**
* Construct an instance of ModelResourceIndexSelector
*/
public ModelWorkspaceSearchIndexSelector() {
super(IndexUtil.INDEX_PATH);
bCreatedWithResources = false;
}
/**
* Construct an instance of ModelResourceIndexSelector
*/
public ModelWorkspaceSearchIndexSelector( IProgressMonitor monitor ) {
super(IndexUtil.INDEX_PATH);
this.monitor = monitor;
bCreatedWithResources = false;
}
/**
* Construct an instance of ModelResourceIndexSelector
*
* @param resources The collection of ModelResources to be indexed
*/
public ModelWorkspaceSearchIndexSelector( Collection resources ) {
super(IndexUtil.INDEX_PATH);
this.resources = resources;
bCreatedWithResources = true;
}
/**
* Construct an instance of ModelResourceIndexSelector Defect 22774 - This constructor allows ModelEditorImpl the ability to
* set the search parameters (i.e. resources) so the search to find objects related to deleted/refactored objects can be
* narrowed based on the object types (i.e. resource types) slated to be deleted.
*
* @param resources The collection of ModelResources to be indexed
* @param monitor The progress monitor
*/
public ModelWorkspaceSearchIndexSelector( Collection resources,
IProgressMonitor monitor ) {
super(IndexUtil.INDEX_PATH);
this.resources = resources;
this.monitor = monitor;
bCreatedWithResources = true;
}
private boolean updateIndexes() {
Collection nonIndexedResources = null;
try {
if (this.resources == null) {
nonIndexedResources = ModelWorkspaceManager.getModelWorkspaceManager().getNonIndexedResources(ModelResource.SEARCH_INDEXED);
} else {
nonIndexedResources = new LinkedList();
for (Iterator rscIter = this.resources.iterator(); rscIter.hasNext();) {
if (monitor != null) {
monitor.worked(1);
}
ModelResource mResource = (ModelResource)rscIter.next();
if (mResource.getIndexType() != ModelResource.INDEXED
&& mResource.getIndexType() != ModelResource.SEARCH_INDEXED) {
nonIndexedResources.add(mResource.getResource());
}
}
}
if (nonIndexedResources != null && !nonIndexedResources.isEmpty()) {
final Collection resourcesToIndex = new ArrayList(nonIndexedResources);
// If there are models with unsaved changes create index files
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) {
ModelBuildUtil.createSearchIndexes(monitor, resourcesToIndex);
return null;
}
};
// Execute the indexing within a transaction as this operation may open resources
// and create new EObjects
ModelerCore.getModelEditor().executeAsTransaction(runnable, "Updating ModelIndexes", false, false, this); //$NON-NLS-1$
return true;
}
} catch (CoreException e) {
ModelerCore.Util.log(IStatus.ERROR,
e,
ModelerCore.Util.getString("ModelWorkspaceSearchIndexSelector.Error_trying_to_index_update_search_indexes___1") + e.getMessage()); //$NON-NLS-1$
}
return false;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.index.IndexSelector#getIndexes()
*/
@Override
public Index[] getIndexes() throws IOException {
// update indexes if needed
boolean indexesUpdated = updateIndexes();
// jh Defect 18513 fix: I removed code that returned here if the indexes did not have to be updated
// if no resource selection is provided and if indexes are not updated
// return the cached indexes (or buld index objects for whole workspce and return those)
if (!bCreatedWithResources && !indexesUpdated) {
return super.getIndexes();
}
// clear the cached indexes
setIndexes(null);
// if resource selection is available, build index objects for the selected resources
// index cache may not need to change but rebuild the index objects for the selection any way,
// the supers getIndex() assumes whole workspce when the cache is empty regardless of the selection
// so need to make sure cache is properly set
// --------------------------------
// Defect 22774 - refactored this a bit so we cache up the index (i.e. only create them once here.
// --------------------------------
if (this.resources != null) {
if (!indexesForCreatedResourcesAreSet || indexesUpdated) {
ArrayList tmp = new ArrayList();
for (Iterator rscIter = this.resources.iterator(); rscIter.hasNext();) {
String resourceFileName = null;
ModelResource mResource = (ModelResource)rscIter.next();
try {
resourceFileName = mResource.getEmfResource().getURI().lastSegment();
} catch (ModelWorkspaceException theException) {
ModelerCore.Util.log(theException);
}
String fileName = IndexUtil.getSearchIndexFileName(mResource);
String path = IndexUtil.INDEX_PATH + fileName;
if (IndexUtil.indexFileExists(path)) {
Index theIndex = IndexUtil.getIndexFile(fileName, path, resourceFileName);
if (theIndex != null) {
tmp.add(theIndex);
}
}
}
cachedIndexes = new Index[tmp.size()];
tmp.toArray(cachedIndexes);
indexesForCreatedResourcesAreSet = true;
}
// cache the indexes
super.setIndexes(cachedIndexes);
return cachedIndexes;
}
// index cache is set by this point in which case just resurn the cached objects,
// else build objects for all indexes in the workspace and return those.
return super.getIndexes();
}
public void setMonitor( IProgressMonitor monitor ) {
this.monitor = monitor;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer(100);
sb.append("ModelWorkspaceSearchIndexSelector ["); //$NON-NLS-1$
Index[] indexes = EMPTY_INDEX_ARRAY;
try {
indexes = getIndexes();
} catch (IOException e) {
// do nothing
}
for (int i = 0; i < indexes.length; i++) {
if (i > 0) {
sb.append(", "); //$NON-NLS-1$
}
sb.append(indexes[i].getIndexFile());
}
sb.append("]"); //$NON-NLS-1$
return sb.toString();
}
@Override
protected FilenameFilter getIndexFileFilter() {
return IndexFilter.FILTER_INSTANCE;
}
public static class IndexFilter implements FilenameFilter {
public static IndexFilter FILTER_INSTANCE = new IndexFilter();
@Override
public boolean accept( File dir,
String name ) {
IPath path = new Path(name);
String extension = path.getFileExtension();
if (extension != null && extension.equals(IndexConstants.SEARCH_INDEX_EXT)) {
return true;
}
return false;
}
}
}