/*
* 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.util.Collection;
import java.util.zip.CRC32;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.resource.Resource;
import org.teiid.core.designer.TeiidDesignerException;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.resource.EmfResource;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelWorkspace;
import org.teiid.designer.core.workspace.ModelWorkspaceManager;
/**
* IndexUtil
*
* @since 8.0
*/
public class IndexUtil {
private static final class ProgressMonitorImpl implements SimpleIndexUtil.ProgressMonitor {
private final IProgressMonitor monitor;
ProgressMonitorImpl( IProgressMonitor monitor ) {
this.monitor = monitor;
}
@Override
public void beginTask( String name,
int totalWork ) {
monitor.beginTask(name, totalWork);
}
@Override
public void worked( int work ) {
monitor.worked(work);
}
}
public static final boolean CASE_SENSITIVE_INDEX_FILE_NAMES = false;
private static final CRC32 CHECK_SUM_CALCULATOR = new CRC32();
public static String INDEX_PATH;
static {
try {
final Plugin plugin = ModelerCore.getPlugin();
// If we are running in the Eclipse runtime environment use the modeler.core
// plugin's state area as the location for writing the index files
if (plugin != null) {
INDEX_PATH = plugin.getStateLocation().addTrailingSeparator().toString();
} else {
INDEX_PATH = System.getProperty("user.dir") + "\\indexes"; //$NON-NLS-1$ //$NON-NLS-2$
}
} catch (Throwable t) {
INDEX_PATH = System.getProperty("user.dir") + "\\indexes"; //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Adds/removes an IResource to an Index if the resource exists, if the resource does not exist, the resource is removed from
* the index.
*
* @param resource The IResource to be added or removed from the index
* @param reuseExistingFile Boolean indicating if the existing index file needs to be used for indexing this resource.
* @param addResource Boolean indicating if this resource needs to be added or removed from the index file.
*/
public static void indexResource( IResource resource,
boolean reuseExistingFile,
boolean addResource ) throws ModelerCoreException {
ModelWorkspace workspace = ModelerCore.getModelWorkspace();
ModelResource mResource = workspace.findModelResource(resource);
IIndexer indexer = new ModelIndexer();
indexResource(indexer, mResource, INDEX_PATH, reuseExistingFile, addResource);
}
/**
* Create an {@link IIndex} from the {@link org.eclipse.emf.ecore.resource.Resource} if the
* resource exists.
*
* @param resource The EMF resource to use
* @param resourcePath The path to the EMF resource
* @param indexDirectoryPath The path to the directory into which the index file is written
* @param indexFileName The name of the output index file
* @param indexPath The path needs to be used for indexing this resource.
* @return the index
*/
public static IIndex indexResource( final Resource resource,
final String resourcePath,
final String indexDirectoryPath,
final String indexFileName ) throws ModelerCoreException {
if (resource == null) {
CoreArgCheck.isNotNull(resource, ModelerCore.Util.getString("IndexUtil.The_Resource_reference_may_not_be_null_1")); //$NON-NLS-1$
}
try {
IIndexer indexer = new ModelIndexer();
// runtime index
String indexFilePath = getIndexFilePath(indexDirectoryPath, indexFileName);
// IIndex runtimeIndex = new Index(indexFilePath, false);
IIndex runtimeIndex = getNewIndexFile(indexFileName, indexFilePath, resource.getURI().lastSegment());
// emf document
ModelDocumentImpl document = new ModelDocumentImpl(resource);
runtimeIndex.add(document, indexer);
runtimeIndex.save();
return runtimeIndex;
} catch (Exception e) {
IStatus status = new Status(IStatus.ERROR, ModelerCore.PLUGIN_ID, IStatus.OK,
ModelerCore.Util.getString("ModelBuilder.IO_Error_trying_to_index_an_EmfResource_2"), e); //$NON-NLS-1$
throw new ModelerCoreException(status);
}
}
/**
* Adds/removes an EmfResource to an Index if the resource exists, if the resource does not exist, the resource is removed
* from the index.
*
* @param emfresource The EmfResource to be added or removed from the index
* @param reuseExistingFile Boolean indicating if the existing index file needs to be used for indexing this resource.
* @param addResource Boolean indicating if this resource needs to be added or removed from the index file.
*/
public static void indexResource( EmfResource emfresource,
boolean reuseExistingFile,
boolean addResource ) throws ModelerCoreException {
IIndexer indexer = new ModelIndexer();
ModelResource mResource = ModelWorkspaceManager.getModelWorkspaceManager().findModelResource(emfresource);
indexResource(indexer, mResource, INDEX_PATH, reuseExistingFile, addResource);
}
/**
* Adds/removes an ModelResource to an Index if the resource exists, if the resource does not exist, the resource is removed
* from the index.
*
* @param mResource The ModelResource to be added or removed from the index
* @param reuseExistingFile Boolean indicating if the existing index file needs to be used for indexing this resource.
* @param addResource Boolean indicating if this resource needs to be added or removed from the index file.
*/
public static void indexResource( ModelResource mResource,
boolean reuseExistingFile,
boolean addResource ) throws ModelerCoreException {
IIndexer indexer = new ModelIndexer();
indexResource(indexer, mResource, INDEX_PATH, reuseExistingFile, addResource);
}
/**
* Adds/removes an ModelResource to/form an Index if the resource exists, if the resource does not exist, the resource is
* removed from the index.
*
* @param mResource The ModelResource to be added or removed from the index
* @param indexFile Path to the file containing indexes
* @param reuseExistingFile Boolean indicating if the existing index file needs to be used for indexing this resource.
* @param addResource Boolean indicating if this resource needs to be added or removed from the index file.
*/
public static void indexResource( IIndexer indexer,
ModelResource mResource,
String indexPath,
boolean reuseExistingFile,
boolean addResource ) throws ModelerCoreException {
CoreArgCheck.isNotNull(mResource, ModelerCore.Util.getString("IndexUtil.The_Resource_reference_may_not_be_null_1")); //$NON-NLS-1$
try {
String resourceFileName = mResource.getEmfResource().getURI().lastSegment();
// runtime index
String indexFileName = getRuntimeIndexFileName(mResource);
// runtime index
String indexFilePath = getIndexFilePath(indexPath, indexFileName);
// IIndex runtimeIndex = new Index(indexFilePath, reuseExistingFile);
IIndex runtimeIndex = getNewIndexFile(indexFileName, indexFilePath, resourceFileName);
IResource resource = mResource.getResource();
String resourcePath = resource.getFullPath().toString();
resourcePath = resourcePath.replace(IPath.SEPARATOR, File.separatorChar);
if (ModelerCore.DEBUG || ModelerCore.DEBUG_PROJECT_BUILDER) {
final Object[] params = new Object[] {indexFileName, resourcePath};
final String msg = ModelerCore.Util.getString("IndexUtil.DEBUG.Creating_index_file_0_for_resource_1_1", params); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.INFO, msg);
}
// emf document
ModelDocumentImpl document = new ModelDocumentImpl(resource, mResource.getEmfResource());
if (addResource) {
runtimeIndex.add(document, indexer);
} else {
runtimeIndex.remove(document.getName());
}
runtimeIndex.save();
// this is a new resource, mark it as indexed
if (indexer instanceof ModelIndexer) mResource.setIndexType(ModelResource.INDEXED);
if (indexer instanceof ModelSearchIndexer && mResource.getIndexType() == ModelResource.NOT_INDEXED) mResource.setIndexType(ModelResource.SEARCH_INDEXED);
} catch (Exception e) {
IStatus status = new Status(IStatus.ERROR, ModelerCore.PLUGIN_ID, IStatus.OK,
ModelerCore.Util.getString("ModelBuilder.IO_Error_trying_to_index_an_EmfResource_2"), e); //$NON-NLS-1$
throw new ModelerCoreException(status);
}
}
public static String getIndexFilePath( final String indexDirectoryPath,
final String indexFileName ) {
return SimpleIndexUtil.getIndexFilePath(indexDirectoryPath, indexFileName);
}
/**
* Return all index file records that match the specified record pattern. The pattern can be constructed from any combination
* of characters including the multiple character wildcard '*' and single character wildcard '?'. The field delimiter is used
* to tokenize both the pattern and the index record so that individual fields can be matched. The method assumes that the
* first occurrence of the delimiter in the record alligns with the first occurrence in the pattern. Any wildcard characters
* in the pattern cannot represent a delimiter character.
*
* @param indexes the array of MtkIndex instances to query
* @param pattern
* @param fieldDelimiter
* @return results
* @throws ModelerCoreException
*/
public static IEntryResult[] queryIndex( final Index[] indexes,
final char[] pattern,
final char fieldDelimiter ) throws ModelerCoreException {
try {
return SimpleIndexUtil.queryIndex(indexes, pattern, fieldDelimiter);
} catch (TeiidDesignerException e) {
throw new ModelerCoreException(e);
}
}
/**
* Return all index file records that match the specified record prefix or pattern. The pattern can be constructed from any
* combination of characters including the multiple character wildcard '*' and single character wildcard '?'. The prefix may
* be constructed from any combination of characters excluding the wildcard characters. The prefix specifies a fixed number of
* characters that the index record must start with.
*
* @param indexes the array of MtkIndex instances to query
* @param pattern
* @return results
* @throws ModelerCoreException
*/
public static IEntryResult[] queryIndex( final Index[] indexes,
final char[] pattern,
final boolean isPrefix,
final boolean returnFirstMatch ) throws ModelerCoreException {
try {
return SimpleIndexUtil.queryIndex(indexes, pattern, isPrefix, returnFirstMatch);
} catch (TeiidDesignerException e) {
throw new ModelerCoreException(e);
}
}
/**
* Return all index file records that match the specified record prefix or pattern. The pattern can be constructed from any
* combination of characters including the multiple character wildcard '*' and single character wildcard '?'. The prefix may
* be constructed from any combination of characters excluding the wildcard characters. The prefix specifies a fixed number of
* characters that the index record must start with.
*
* @param monitor an optional ProgressMonitor
* @param indexes the array of MtkIndex instances to query
* @param pattern
* @return results
* @throws ModelerCoreException
*/
public static IEntryResult[] queryIndex( final IProgressMonitor monitor,
final Index[] indexes,
final char[] pattern,
final boolean isPrefix,
final boolean returnFirstMatch ) throws ModelerCoreException {
try {
return SimpleIndexUtil.queryIndex(monitor != null ? new ProgressMonitorImpl(monitor) : null,
indexes,
pattern,
isPrefix,
returnFirstMatch);
} catch (TeiidDesignerException e) {
throw new ModelerCoreException(e);
}
}
/**
* Return all index file records that match the specified record prefix or pattern. The pattern can be constructed from any
* combination of characters including the multiple character wildcard '*' and single character wildcard '?'. The prefix may
* be constructed from any combination of characters excluding the wildcard characters. The prefix specifies a fixed number of
* characters that the index record must start with.
*
* @param monitor an optional ProgressMonitor
* @param indexes the array of MtkIndex instances to query
* @param pattern
* @return results
* @throws ModelerCoreException
*/
public static IEntryResult[] queryIndex( IProgressMonitor monitor,
final Index[] indexes,
final Collection patterns,
final boolean isPrefix,
final boolean isCaseSensitive,
final boolean returnFirstMatch ) throws ModelerCoreException {
try {
return SimpleIndexUtil.queryIndex(monitor != null ? new ProgressMonitorImpl(monitor) : null,
indexes,
patterns,
isPrefix,
isCaseSensitive,
returnFirstMatch);
} catch (TeiidDesignerException e) {
throw new ModelerCoreException(e);
}
}
public static String getRuntimeIndexFileName( final ModelResource model ) {
CoreArgCheck.isNotNull(model);
return getRuntimeIndexFileName(model.getResource());
}
public static String getRuntimeIndexFileName( final Resource model ) {
CoreArgCheck.isNotNull(model);
ModelResource mResource = ModelWorkspaceManager.getModelWorkspaceManager().findModelResource(model);
return getRuntimeIndexFileName(mResource);
}
public static String getRuntimeIndexFileName( final IResource resource ) {
CoreArgCheck.isNotNull(resource);
final String resourcePath = resource.getFullPath().toString();
return getRuntimeIndexFileName(resourcePath);
}
public static String getRuntimeIndexFileName( final String fullPath ) {
CoreArgCheck.isNotNull(fullPath);
return getIndexFileName(fullPath, IndexConstants.INDEX_EXT);
}
public static String getSearchIndexFileName( final ModelResource model ) {
CoreArgCheck.isNotNull(model);
return getSearchIndexFileName(model.getResource());
}
public static String getSearchIndexFileName( final Resource model ) {
CoreArgCheck.isNotNull(model);
ModelResource mResource = ModelWorkspaceManager.getModelWorkspaceManager().findModelResource(model);
return getSearchIndexFileName(mResource);
}
public static String getSearchIndexFileName( final IResource resource ) {
CoreArgCheck.isNotNull(resource);
final String resourcePath = resource.getFullPath().toString();
return getSearchIndexFileName(resourcePath);
}
public static String getSearchIndexFileName( final String fullPath ) {
CoreArgCheck.isNotNull(fullPath);
return getIndexFileName(fullPath, IndexConstants.SEARCH_INDEX_EXT);
}
public static String getIndexFileName( final String fullPath,
final String extension ) {
CoreArgCheck.isNotNull(fullPath);
CoreArgCheck.isNotNull(extension);
String pathForName = fullPath;
// If the index file names should be case insensitive ...
if (!CASE_SENSITIVE_INDEX_FILE_NAMES) {
pathForName = pathForName.toUpperCase();
}
CHECK_SUM_CALCULATOR.reset();
CHECK_SUM_CALCULATOR.update(pathForName.getBytes());
// Create an index file name for this path
final String indexFileName = CHECK_SUM_CALCULATOR.getValue() + IndexConstants.EXTENSION_CHAR + extension;
//System.out.println("Index filename = "+indexFileName+", original filename = "+pathForName); //$NON-NLS-1$ //$NON-NLS-2$
return indexFileName;
}
/**
* Return true if the specifed index file exists on the file system otherwise return false.
*/
public static boolean indexFileExists( final String indexFilePath ) {
return SimpleIndexUtil.indexFileExists(indexFilePath);
}
/**
* Return true if the specifed index file exists on the file system otherwise return false.
*/
public static boolean indexFileExists( final File indexFile ) {
return SimpleIndexUtil.indexFileExists(indexFile);
}
/**
* Return true if the specifed index file represents a known index file on the file system otherwise return false.
*/
public static boolean isModelIndex( final String indexFileName ) {
return SimpleIndexUtil.isModelIndex(indexFileName);
}
/**
* Return true if the specifed index file represents a index file on the file system otherwise return false.
*/
public static boolean isIndexFile( final String indexFileName ) {
return SimpleIndexUtil.isIndexFile(indexFileName);
}
/**
* Return true if the specifed index file represents a index file on the file system otherwise return false.
*/
public static boolean isIndexFile( final File indexFile ) {
return SimpleIndexUtil.isIndexFile(indexFile);
}
/**
* Return an array of indexes given a indexName.
*
* @param indexName The shortName of the index file
* @param selector The indexSelector to lookup indexes
* @return An array of indexes, may be duplicates depending on index selector.
* @throws ModelerCoreException If there is an error looking up indexes
* @since 4.2
*/
public static Index[] getIndexes( final String indexName,
final IndexSelector selector ) throws ModelerCoreException {
try {
return SimpleIndexUtil.getIndexes(indexName, selector);
} catch (TeiidDesignerException e) {
throw new ModelerCoreException(e);
}
}
/**
* Return the name of the index file to use for the specified record type, applies only for sever and vdb index files.
*
* @param recordType
* @return
*/
public static String getIndexFileNameForRecordType( final char recordType ) {
return SimpleIndexUtil.getIndexFileNameForRecordType(recordType);
}
/**
* Return the name of the index file to use for the specified record type, applies only for sever and vdb index files.
*
* @param recordType
* @return
*/
public static String getRecordTypeForIndexFileName( final String indexName ) {
return SimpleIndexUtil.getRecordTypeForIndexFileName(indexName);
}
/**
* Return the prefix match string that could be used to exactly match a fully qualified entity name in an index record. All
* index records contain a header portion of the form: recordType|name|
*
* @param name The fully qualified name for which the prefix match string is to be constructed.
* @return The pattern match string of the form: recordType|name|
*/
public static String getPrefixPattern( final char recordType,
final String uuid ) {
return SimpleIndexUtil.getPrefixPattern(recordType, uuid);
}
/**
* Deletes all index files in the specified collection of files.
*
* @param theFiles the collection of files whose index files are being deleted
* @param theContinueOnErrorFlag the flag indicated if this method should proceed even after a problem is encountered deleting
* a file
* @return <code>true</code> if all index files were successfully deleted; <code>false</code> otherwise.
* @since 5.0.1
*/
public static boolean deleteIndexFiles( File[] theFiles,
boolean theContinueOnErrorFlag ) {
boolean result = true;
for (int i = theFiles.length; --i >= 0;) {
File file = theFiles[i];
if (isIndexFile(file)) {
ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().disposeIndex(file.getName());
}
}
return result;
}
public static Index getIndexFile( String indexFileName,
String indexFilePath,
String resourceFileName ) {
return ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().getIndex(indexFileName,
indexFilePath,
resourceFileName);
}
public static Index getIndexFile( String indexFileName,
String indexFilePath ) {
return ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().getIndex(indexFileName, indexFilePath);
}
public static Index getNewIndexFile( String indexFileName,
String indexFilePath,
String resourceFileName ) {
return ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().getNewIndex(indexFileName,
indexFilePath,
resourceFileName);
}
public static Index getNewIndexFile( String indexFileName,
String indexFilePath ) {
return ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().getNewIndex(indexFileName, indexFilePath);
}
public static Index[] getExistingIndexes( File[] indexFiles ) {
return ModelWorkspaceManager.getModelWorkspaceManager().getIndexManager().getExistingIndexes(indexFiles);
}
}