/*
* 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.search;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
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.core.designer.ModelerCoreException;
import org.teiid.core.designer.id.ObjectID;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.index.IEntryResult;
import org.teiid.designer.core.index.IQueryResult;
import org.teiid.designer.core.index.Index;
import org.teiid.designer.core.index.IndexConstants;
import org.teiid.designer.core.index.IndexSelector;
import org.teiid.designer.core.index.IndexUtil;
import org.teiid.designer.core.index.ModelWorkspaceSearchIndexSelector;
import org.teiid.designer.core.search.runtime.ReferencesRecord;
import org.teiid.designer.core.search.runtime.ResourceImportRecord;
import org.teiid.designer.core.search.runtime.ResourceObjectRecord;
import org.teiid.designer.core.search.runtime.ResourceRecord;
import org.teiid.designer.core.search.runtime.SearchRuntimeAdapter;
/**
* ModelWorkspaceSearch
*
* @since 8.0
*/
public class ModelWorkspaceSearch {
private static final IQueryResult[] EMTPY_QUERY_RESULT_ARRAY = new IQueryResult[0];
private static final IEntryResult[] EMTPY_ENTRY_RESULT_ARRAY = new IEntryResult[0];
private IndexSelector selector;
private IProgressMonitor monitor;
private int iIncrement = -1;
private static final int NOMINAL_WORK = 100;
private static final int START_UNITS = 10;
// ==================================================================================
// C O N S T R U C T O R S
// ==================================================================================
/**
* Construct an instance of ModelWorkspaceSearch.
*/
public ModelWorkspaceSearch() {}
// jhNOTE: essential fix to pass monitor
public ModelWorkspaceSearch( IProgressMonitor monitor ) {
this.monitor = monitor;
}
// ==================================================================================
// P U B L I C M E T H O D S
// ==================================================================================
/**
* Return an array of IPath instances corresponding to the workspace relative
* paths to all model resources containing an EObject with the specified identifier.
*/
public IPath[] getResourcesContainingObjectId(final ObjectID id) {
return this.getResourcesContainingObjectId(id.toString());
}
/**
* Return an array of IPath instances corresponding to the workspace relative
* paths to all model resources containing an EObject with the specified identifier.
*/
public IPath[] getResourcesContainingObjectId(final String id) {
String prefix = IndexUtil.getPrefixPattern(IndexConstants.SEARCH_RECORD_TYPE.OBJECT, id);
IQueryResult[] results = this.queryPrefix(prefix);
final ArrayList tmp = new ArrayList(results.length);
for (int i = 0; i < results.length; i++) {
IQueryResult result = results[i];
String resultPath = result.getPath();
int beginIndex = resultPath.indexOf(IPath.SEPARATOR);
if (beginIndex > 0) {
resultPath = resultPath.substring(beginIndex);
}
IPath path = new Path(resultPath);
tmp.add(path);
}
IPath[] paths = new IPath[tmp.size()];
tmp.toArray(paths);
return paths;
}
/**
* Return an array of IPath instances corresponding to the workspace relative
* paths to all resources containing an EObject with the specified identifier.
*/
public IPath[] getResourcesWithId(final ObjectID id) {
return this.getResourcesWithId(id.toString());
}
/**
* Return an array of IPath instances corresponding to the workspace relative
* paths to all model resources containing an EObject with the specified identifier.
*/
public IPath[] getResourcesWithId(final String id) {
String prefix = IndexUtil.getPrefixPattern(IndexConstants.SEARCH_RECORD_TYPE.RESOURCE, id);
IEntryResult[] results = this.queryWithPrefix(prefix);
final ArrayList tmp = new ArrayList(results.length);
for (int i = 0; i < results.length; i++) {
IEntryResult result = results[i];
ResourceRecord record = (ResourceRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
tmp.add(new Path(record.getPath()));
}
IPath[] paths = new IPath[tmp.size()];
tmp.toArray(paths);
return paths;
}
/**
* Return a collection of {@link org.teiid.designer.core.search.runtime.ResourceObjectRecord}
* objects.
* @return Collection of records containing info about eobjects in the workspace
*/
public Collection getAllModelObjectRecords() {
// comment this out so we only use the monitoring in IndexUtil...
initMonitor(); // Better, set it to UNKNOWN and see what happens.
String prefix = IndexUtil.getPrefixPattern(IndexConstants.SEARCH_RECORD_TYPE.OBJECT, null);
IEntryResult[] results = null;
if ( monitor != null ) {
results = this.queryWithPrefix(prefix, monitor);
} else {
results = this.queryWithPrefix(prefix);
}
Collection objRecords = new HashSet(results.length);
int iRecordCount = results.length;
for (int i = 0; i < iRecordCount; i++) {
IEntryResult result = results[i];
ResourceObjectRecord record = (ResourceObjectRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
objRecords.add(record);
// update the monitor
try {
updateMonitor( i, iRecordCount );
} catch ( InterruptedException ie ) {
// this is a cancel, so quit and return null
return null;
}
}
return objRecords;
}
private void initMonitor() {
if ( monitor == null ) {
return;
}
monitor.beginTask( null, NOMINAL_WORK );
}
private void updateMonitor( int iCurrentIndex, int iTotalRecords )
throws InterruptedException {
if ( monitor == null || iTotalRecords == 0) {
return;
}
// just need to calc the increment once
if ( iIncrement == -1 ) {
int iRemainingUnits = NOMINAL_WORK - START_UNITS;
iIncrement = ( iTotalRecords / iRemainingUnits );
if( iIncrement == 0 )
iIncrement = 1;
}
if ( iCurrentIndex % iIncrement == 0 ) {
if (monitor.isCanceled())
throw new InterruptedException();
monitor.worked( iIncrement );
}
}
/**
* Return a collection of {@link org.teiid.designer.core.search.runtime.ResourceImportRecord}
* objects.
* @param path The workspace relative path of the model that is being imported.
* @return Collection of records containing import info for the model
*/
public Collection getModelsImportingResources(String folderOrFilePath) {
// construct the pattern string
final String prefix = "" //$NON-NLS-1$
+ IndexConstants.SEARCH_RECORD_TYPE.MODEL_IMPORT
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ folderOrFilePath.trim();
IEntryResult[] results = this.queryWithPrefix(prefix);
Collection refRecords = new HashSet(results.length);
for (int i = 0; i < results.length; i++) {
IEntryResult result = results[i];
ResourceImportRecord record = (ResourceImportRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
refRecords.add(record);
}
return refRecords;
}
/**
* Return a collection of {@link org.teiid.designer.core.search.runtime.ResourceImportRecord}
* objects.
* @param path The workspace relative path of the model that is importing resources.
* @return Collection of records containing import info for the model
*/
public Collection getResourcesImportedByModel(String folderOrFilePath) {
// construct the pattern string
final String pattern = "" //$NON-NLS-1$
+ IndexConstants.SEARCH_RECORD_TYPE.MODEL_IMPORT
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ IndexConstants.RECORD_STRING.MATCH_CHAR_STRING
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ IndexConstants.RECORD_STRING.MATCH_CHAR_STRING
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ folderOrFilePath.trim()
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER;
IEntryResult[] results = this.queryWithPattern(pattern);
Collection refRecords = new HashSet(results.length);
for (int i = 0; i < results.length; i++) {
IEntryResult result = results[i];
ResourceImportRecord record = (ResourceImportRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
refRecords.add(record);
}
return refRecords;
}
/**
* Return a collection of {@link org.teiid.designer.core.search.runtime.ReferencesRecord}
* objects.
* @param id UUID of the object that has uni-directional references to other objects
* @return Collection of records containing reference info
*/
public Collection getUniDirectionalReferencesTo(String id) {
// construct the pattern string
String prefix = "" //$NON-NLS-1$
+ IndexConstants.SEARCH_RECORD_TYPE.OBJECT_REF
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ id.trim()
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER;
IEntryResult[] results = this.queryWithPrefix(prefix);
Collection refRecords = new HashSet(results.length);
for (int i = 0; i < results.length; i++) {
IEntryResult result = results[i];
ReferencesRecord record = (ReferencesRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
refRecords.add(record);
}
return refRecords;
}
public Collection getUniDirectionalReferencesFrom(String id) {
// construct the pattern string
String pattern = "" //$NON-NLS-1$
+ IndexConstants.SEARCH_RECORD_TYPE.OBJECT_REF
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ IndexConstants.RECORD_STRING.MATCH_CHAR_STRING
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER
+ id.trim()
+ IndexConstants.RECORD_STRING.RECORD_DELIMITER;
IEntryResult[] results = this.queryWithPattern(pattern);
Collection refRecords = new HashSet(results.length);
for (int i = 0; i < results.length; i++) {
IEntryResult result = results[i];
ReferencesRecord record = (ReferencesRecord) SearchRuntimeAdapter.getSearchRecord(result.getWord());
refRecords.add(record);
}
return refRecords;
}
/**
* Set the IndexSelector reference
*/
public void setIndexSelector(final IndexSelector indexSelector) {
this.selector = indexSelector;
}
// ==================================================================================
// P R O T E C T E D M E T H O D S
// ==================================================================================
protected IndexSelector getIndexSelector() {
return getIndexSelector( null );
}
protected IndexSelector getIndexSelector( IProgressMonitor monitor ) {
if (this.selector == null) {
this.selector = createIndexSelector(monitor);
}
if(this.selector instanceof ModelWorkspaceSearchIndexSelector) {
((ModelWorkspaceSearchIndexSelector)this.selector).setMonitor(monitor);
}
return this.selector;
}
protected IndexSelector createIndexSelector(IProgressMonitor monitor) {
return new ModelWorkspaceSearchIndexSelector(monitor);
}
// ==================================================================================
// P R I V A T E M E T H O D S
// ==================================================================================
private IEntryResult[] queryWithPrefix(final String prefix) {
return queryWithPrefix(prefix, null);
}
private IEntryResult[] queryWithPrefix(final String prefix, IProgressMonitor monitor) {
try {
Index[] indexes = null;
if (monitor != null) {
indexes = this.getIndexSelector( monitor ).getIndexes();
} else {
indexes = this.getIndexSelector().getIndexes();
}
return IndexUtil.queryIndex(monitor, indexes, prefix.toCharArray(), true, false);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR,e,e.getMessage());
} catch (IOException e) {
ModelerCore.Util.log(IStatus.ERROR,e,ModelerCore.Util.getString("ModelWorkspaceSearch.Error_trying_to_index_files_from_selector_1")); //$NON-NLS-1$
}
return EMTPY_ENTRY_RESULT_ARRAY;
}
private IEntryResult[] queryWithPattern(final String pattern) {
try {
Index[] indexes = this.getIndexSelector().getIndexes();
return IndexUtil.queryIndex(indexes, pattern.toCharArray(), false, false);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR,e,e.getMessage());
} catch (IOException e) {
ModelerCore.Util.log(IStatus.ERROR,e,ModelerCore.Util.getString("ModelWorkspaceSearch.Error_trying_to_index_files_from_selector_1")); //$NON-NLS-1$
}
return EMTPY_ENTRY_RESULT_ARRAY;
}
private IQueryResult[] queryPrefix(final String prefix) {
try {
Index[] indexes = this.getIndexSelector().getIndexes();
return this.queryPrefix(indexes,prefix.toCharArray());
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR,e,e.getMessage());
} catch (IOException e) {
ModelerCore.Util.log(IStatus.ERROR,e,ModelerCore.Util.getString("ModelWorkspaceSearch.Error_trying_to_index_files_from_selector_1")); //$NON-NLS-1$
}
return EMTPY_QUERY_RESULT_ARRAY;
}
private IQueryResult[] queryPrefix(final Index[] indexes, final char[] prefix) throws ModelerCoreException {
final ArrayList queryResult = new ArrayList();
try {
for (int i = 0; i < indexes.length; i++) {
IQueryResult[] partialResult = indexes[i].queryPrefix(prefix);
if (partialResult != null && partialResult.length > 0) {
queryResult.addAll(Arrays.asList(partialResult));
}
}
} catch(IOException e) {
Object[] params = new Object[]{new String(prefix)};
throw new ModelerCoreException(e, ModelerCore.Util.getString("ModelWorkspaceSearch.Error_trying_to_query_index_files_for_prefix_2",params)); //$NON-NLS-1$
}
IQueryResult[] result = new IQueryResult[queryResult.size()];
queryResult.toArray(result);
return result;
}
}