/* Copyright (C) 2003 EBI, GRL This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.ensembl.mart.shell; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.ensembl.mart.lib.InvalidQueryException; import org.ensembl.mart.lib.config.AttributeCollection; import org.ensembl.mart.lib.config.AttributeGroup; import org.ensembl.mart.lib.config.AttributePage; import org.ensembl.mart.lib.config.ConfigurationException; import org.ensembl.mart.lib.config.FilterDescription; import org.ensembl.mart.lib.config.FilterPage; import org.ensembl.mart.lib.config.RegistryDSConfigAdaptor; //import org.gnu.readline.Readline; //import org.gnu.readline.ReadlineCompleter; import jline.*; /** * <p>ReadlineCompleter implimenting object allowing Mart - specific * behavior. It provides command-completion choices that are based * on the position within an MQL command (see MartShellLib for a description * of the Mart Query Language) where a user requests completion. * It provides public methods to allow its completion mode to * be changed, and allow these modes to be backed with specific lists of * choices for completion. The system provides the following modes:</p> * <ul> * <li><p>Command Mode: keyword: "command". Only available MartShell commands, and other names added by the client for this mode, are made available.</p> * <li><p>Describe Mode: keyword: "describe". This is a special mode, and requires a Map be added, which further categorizes the describe system commands based on successive keys.</p> * <li><p>Help Mode: keyword: "help". Only names added by the client for this mode are made available.</p> * <li><p>Get Mode: keyword: "get". Only attribute_names, and other names added by the client for this mode are made available.</p> * <li><p>Sequence Mode: keyword: "sequence". Only names added by the client for this mode are made available.</p> * <li><p>DatasetConfig Mode: keyword: "datasets". Only dataset names, and other names added by the client for this mode, are made available.</p> * <li><p>Where Mode: keyword: "where". Only filter_names, filter_set_names, and other names added by the client for this mode, are made available.</p> * </ul> * <br> * <p>In some cases it will switch its own mode, but * the client code should manage its mode, as well, otherwise it may get stuck * in a particular mode when its keywords are processed in a line previous to the current * Readline line buffer.</p> * <p> Users wishing to add new Domain Specific attributes (analogous to sequences in the present system) should add keywords and modes to the system to * support them.</p> * @author <a href="mailto:dlondon@ebi.ac.uk">Darin London</a> * @author <a href="mailto:craig@ebi.ac.uk">Craig Melsopp</a> * @see MartShellLib * @see org.ensembl.mart.lib.config.MartConfiguration */ //public class MartCompleter implements ReadlineCompleter { public class MartCompleter implements Completor { /* (non-Javadoc) * @see org.gnu.readline.ReadlineCompleter#completer(java.lang.String, int) */ private Iterator possibleValues; // iterator for subsequent calls. private SortedSet currentSet = new TreeSet(); private MartShellLib msl = null; private SortedSet commandSet = new TreeSet(); // will hold basic shell commands private SortedSet helpSet = new TreeSet(); // will hold help keys available private SortedSet addBaseSet = new TreeSet(); // will hold add completions private SortedSet listSet = new TreeSet(); // will hold list request keys private SortedSet procSet = new TreeSet(); // will hold stored procedure names for remove, describe, and execute private SortedSet environmentSet = new TreeSet(); // will hold environment command completions private SortedSet removeBaseSet = new TreeSet(); // will hold remove base completions private SortedSet updateBaseSet = new TreeSet(); // will hold update remove base completions private SortedSet setBaseSet = new TreeSet(); // will hold set base completions private SortedSet describeBaseSet = new TreeSet(); // will hold describe base completions private SortedSet executeBaseSet = new TreeSet(); // will hold execute base completions private SortedSet martSet = new TreeSet(); // will hold String names for remove, and set private SortedSet adaptorLocationSet = new TreeSet(); // will hold adaptor names for update and remove private SortedSet datasetConfigSet = new TreeSet(); // will hold DatasetConfig names for use, set, remove, and describe private final List NODATASETWARNING = Collections.unmodifiableList(Arrays.asList(new String[] { "No DatasetConfigs loaded", "!" })); private final List NOENVWARNING = Collections.unmodifiableList(Arrays.asList(new String[] { "Please set environmenal Mart and Dataset", "!" })); private final List ERRORMODE = Collections.unmodifiableList(Arrays.asList(new String[] { "ERROR ENCOUNTERED" })); private final String ADDC = "add"; private final String REMOVEC = "remove"; private final String LISTC = "list"; private final String UPDATEC = "update"; private final String SETC = "set"; private final String UNSETC = "unset"; private final String DESCRIBEC = "describe"; private final String HELPC = "help"; private final String USEC = "use"; private final String ENVC = "environment"; private final String EXECC = "execute"; private final String COUNTFOCUSC = "count_focus_from"; private final String COUNTROWSC = "count_rows_from"; private List currentApages = new ArrayList(); private List currentFpages = new ArrayList(); private String lastFilterName = null; private String lastAttributeName = null; private boolean attributeMode = false; private boolean whereMode = false; private boolean whereNamesMode = false; private boolean whereQualifiersMode = false; private boolean whereValuesMode = false; //listlevel characters public int listLevel = 0; private String lastLine = null; //////// New Declarataions public Completor [] completors; public final ArgumentDelimiter delim; public boolean strict = true; /////////////////////////// private Logger logger = Logger.getLogger(MartCompleter.class.getName()); /** * Creates a MartCompleter Object. The MartCompleter processes the MartConfiguration * object, and stores important internal_names into the completion sets that are applicable to the given MartConfiguration object. * @param adaptorManager - a MartConfiguration Object */ public MartCompleter (final List completors) { this ((Completor [])completors.toArray (new Completor [completors.size ()])); } public MartCompleter (final Completor completor) { this (new Completor [] { completor }); } /** * Constuctor: create a new completor with the default * argument separator of " ". * * @param completors the embedded argument completors */ public MartCompleter (final Completor [] completors) { this (completors, new WhitespaceArgumentDelimiter ()); } /** * Constuctor: create a new completor with the specified * argument delimiter. * * @param completor the embedded completor * @param delim the delimiter for parsing arguments */ public MartCompleter (final Completor completor, final ArgumentDelimiter delim) { this (new Completor [] { completor }, delim); } /** * Constuctor: create a new completor with the specified * argument delimiter. * * @param completors the embedded completors * @param delim the delimiter for parsing arguments */ public MartCompleter (final Completor [] completors, final ArgumentDelimiter delim) { this.completors = completors; this.delim = delim; } /** * If true, a completion at argument index N will only succeed * if all the completions from 0-(N-1) also succeed. */ public void setStrict (final boolean strict) { this.strict = strict; } /** * Returns whether a completion at argument index N will succees * if all the completions from arguments 0-(N-1) also succeed. */ public boolean getStrict () { return this.strict; } public static interface ArgumentDelimiter { ArgumentList delimit (String buffer, int argumentPosition); boolean isDelimiter (String buffer, int pos); } public static abstract class AbstractArgumentDelimiter implements ArgumentDelimiter { private char [] quoteChars = new char [] { '\'', '"' }; private char [] escapeChars = new char [] { '\\' }; public void setQuoteChars (final char [] quoteChars) { this.quoteChars = quoteChars; } public char [] getQuoteChars () { return this.quoteChars; } public void setEscapeChars (final char [] escapeChars) { this.escapeChars = escapeChars; } public char [] getEscapeChars () { return this.escapeChars; } public ArgumentList delimit (final String buffer, final int cursor) { List args = new LinkedList (); StringBuffer arg = new StringBuffer (); int argpos = -1; int bindex = -1; for (int i = 0; buffer != null && i <= buffer.length (); i++) { // once we reach the cursor, set the // position of the selected index if (i == cursor) { bindex = args.size (); // the position in the current argument is just the // length of the current argument argpos = arg.length (); } if (i == buffer.length () || isDelimiter (buffer, i)) { if (arg.length () > 0) { args.add (arg.toString ()); arg.setLength (0); // reset the arg } } else { arg.append (buffer.charAt (i)); } } return new ArgumentList ( (String [])args.toArray (new String [args.size ()]), bindex, argpos, cursor); } public boolean isDelimiter (final String buffer, final int pos) { if (isQuoted (buffer, pos)) return false; if (isEscaped (buffer, pos)) return false; return isDelimiterChar (buffer, pos); } public boolean isQuoted (final String buffer, final int pos) { return false; } public boolean isEscaped (final String buffer, final int pos) { if (pos <= 0) return false; for (int i = 0; escapeChars != null && i < escapeChars.length; i++) { if (buffer.charAt (pos) == escapeChars [i]) return !isEscaped (buffer, pos - 1); // escape escape } return false; } public abstract boolean isDelimiterChar (String buffer, int pos); } public static class WhitespaceArgumentDelimiter extends AbstractArgumentDelimiter { public boolean isDelimiterChar (String buffer, int pos) { return Character.isWhitespace (buffer.charAt (pos)); } } public static class ArgumentList { private String [] arguments; private int cursorArgumentIndex; private int argumentPosition; private int bufferPosition; public ArgumentList (String [] arguments, int cursorArgumentIndex, int argumentPosition, int bufferPosition) { this.arguments = arguments; this.cursorArgumentIndex = cursorArgumentIndex; this.argumentPosition = argumentPosition; this.bufferPosition = bufferPosition; } public void setCursorArgumentIndex (int cursorArgumentIndex) { this.cursorArgumentIndex = cursorArgumentIndex; } public int getCursorArgumentIndex () { return this.cursorArgumentIndex; } public String getCursorArgument () { if (cursorArgumentIndex < 0 || cursorArgumentIndex >= arguments.length) return null; return arguments [cursorArgumentIndex]; } public void setArgumentPosition (int argumentPosition) { this.argumentPosition = argumentPosition; } public int getArgumentPosition () { return this.argumentPosition; } public void setArguments (String [] arguments) { this.arguments = arguments; } public String [] getArguments () { return this.arguments; } public void setBufferPosition (int bufferPosition) { this.bufferPosition = bufferPosition; } public int getBufferPosition () { return this.bufferPosition; } } public void setController(MartShellLib msl) throws ConfigurationException { this.msl = msl; RegistryDSConfigAdaptor adaptorManager = msl.adaptorManager; if (adaptorManager.getDatasetNames(false).length > 0) { String[] dsets = adaptorManager.getDatasetNames(false); for (int i = 0, n = dsets.length; i < n; i++) { String dataset = dsets[i]; datasetConfigSet.addAll(Arrays.asList(adaptorManager.getDatasetConfigInternalNamesByDataset(dataset))); } } } /** * Implimentation of the ReadlineCompleter completer method. Switches its state based on the presence and position of keywords in the command. * <ul> * <li><p> If the word "describe" occurs, Describe Mode is chosen.</p> * <li><p> If the word "help" occurs, Help Mode is chosen.</p> * <li><p> If the word "select" is present, and occurs after all other keywords present, then Select Mode is chosen.</p> * <li><p> If the word "sequence" is present, and occurs after all other keywords present, then Sequence Mode is chosen.</p> * <li><p> If the word "from" is present, and occurs after all other keywords present, then From Mode is chosen.</p> * <li><p> If the word "where" is present, and occurs after all other keywords present, then Where Mode is chosen.</p> * </ul> */ /* public String completer(String text, int state) { if (state == 0) { // first call to completer(): initialize our choices-iterator //System.out.println("*STATE = 0*" + text); setModeForLine(Readline.getLineBuffer()); possibleValues = currentSet.tailSet(text).iterator(); } // Iterator temp= possibleValues; // while(temp.hasNext()) // { // System.out.println("**: " + ((String) temp.next())); // } if (possibleValues.hasNext()) { String nextKey = (String) possibleValues.next(); if (nextKey.startsWith(text)) return nextKey; } return null; // we reached the last choice. } */ public int complete (final String buffer, final int cursor, final List candidates) { // TODO: Copy code from above and create a new SimpleCompletor each time as in your own example. ArgumentList list = delim.delimit (buffer, cursor); int argpos = list.getArgumentPosition (); int argIndex = list.getCursorArgumentIndex (); if (argIndex < 0) return -1; Completor comp; setModeForLine(buffer); //////////// For making possible Values as variable possibleOptions String [] for SimpleCompletor Iterator temp = currentSet.iterator(); List mylist = new LinkedList(); while(temp.hasNext()) { mylist.add(temp.next()); } String [] possibleOptions = new String [mylist.size()]; mylist.toArray(possibleOptions); ///////////////////////////////////////////////////////////////////// comp = new SimpleCompletor (possibleOptions); int ret = comp.complete (list.getCursorArgument (), argpos, candidates); if (ret == -1) return -1; int pos = ret + (list.getBufferPosition () - argpos) + 1; if (cursor != buffer.length () && delim.isDelimiter (buffer, cursor)) { for (int i = 0; i < candidates.size (); i++) { String val = candidates.get (i).toString (); while (val.length () > 0 && delim.isDelimiter (val, val.length () - 1)) val = val.substring (0, val.length () - 1); candidates.set (i, val); } } ConsoleReader.debug ("Completing " + buffer + "(pos=" + cursor + ") " + "with: " + candidates + ": offset=" + pos); return pos; } public void setModeForLine(String currentCommand) { if (lastLine == null || !(lastLine.equals(currentCommand))) { if (currentCommand.startsWith(COUNTFOCUSC)) currentCommand = currentCommand.substring(COUNTFOCUSC.length()).trim(); if (currentCommand.startsWith(COUNTROWSC)) currentCommand = currentCommand.substring(COUNTROWSC.length()).trim(); currentCommand = currentCommand.trim(); //strip off trailing whitespace, so most modes will set empty mode when things match exactly if (currentCommand.startsWith(ADDC)) setAddMode(currentCommand); else if (currentCommand.startsWith(REMOVEC)) setRemoveMode(currentCommand); else if (currentCommand.startsWith(LISTC)) setListMode(currentCommand); else if (currentCommand.startsWith(UPDATEC)) setUpdateMode(currentCommand); else if (currentCommand.startsWith(SETC) || currentCommand.startsWith(UNSETC)) setSetUnsetMode(currentCommand); else if (currentCommand.startsWith(DESCRIBEC)) setDescribeMode(currentCommand); else if (currentCommand.startsWith(ENVC)) setEnvironmentMode(); else if (currentCommand.startsWith(EXECC)) setExecuteMode(currentCommand); else if (currentCommand.startsWith(HELPC)) setHelpMode(); else if (currentCommand.startsWith(USEC)) { if (currentCommand.endsWith(">")) setMartReqMode(); else setUseDatasetMode(currentCommand); } else { int usingInd = currentCommand.lastIndexOf(MartShellLib.USINGQSTART); if (usingInd >= 0) { msl.usingLocalDataset = true; String[] toks = currentCommand.split("\\s+"); //unset all modes if user has erased back to using if (toks.length < 3) { attributeMode = false; whereMode = false; } if (toks.length >= 2) { String datasetreq = toks[1]; if (datasetreq.indexOf(">") > 0) datasetreq = datasetreq.substring(0, datasetreq.indexOf(">")); try { msl.setLocalDatasetFor(datasetreq); } catch (InvalidQueryException e) { //ignore this. If they have specified a strange dataset, and then do get, it will complain } } } String[] lineWords = currentCommand.split(" "); // split on single space // determine which mode to be in during a query int getInd = currentCommand.lastIndexOf(MartShellLib.GETQSTART); int seqInd = currentCommand.lastIndexOf(MartShellLib.QSEQUENCE); int whereInd = currentCommand.lastIndexOf(MartShellLib.QWHERE); int limitInd = currentCommand.lastIndexOf(MartShellLib.QLIMIT); if ((usingInd > seqInd) && (usingInd > getInd) && (usingInd > whereInd) && (usingInd > limitInd)) { if (currentCommand.endsWith(">")) setMartReqMode(); else setUseDatasetMode(currentCommand); } if ((seqInd > usingInd) && (seqInd > getInd) && (seqInd > whereInd) && (seqInd > limitInd)) setDomainSpecificMode(); if ((getInd > usingInd) && (getInd > seqInd) && (getInd > whereInd) && (getInd > limitInd)) attributeMode = true; if ((whereInd > usingInd) && (whereInd > seqInd) && (whereInd > getInd) && (whereInd > limitInd)) { attributeMode = false; whereMode = true; } if ((limitInd > usingInd) && (limitInd > getInd) && (limitInd > seqInd) && (limitInd > whereInd)) { attributeMode = false; whereMode = false; setEmptyMode(); } // if none of the key placeholders are present, may still need to further refine the mode if (attributeMode) { if (lineWords.length > 0) { String lastWord = lineWords[lineWords.length - 1]; if (lastWord.equals(MartShellLib.GETQSTART)) { lastAttributeName = null; currentApages = new ArrayList(); } else { if (lastWord.endsWith(",")) { lastAttributeName = lastWord.substring(0, lastWord.length() - 1); pruneAttributePages(); } } setAttributeNames(); } } if (whereMode) { if (!(whereNamesMode || whereQualifiersMode || whereValuesMode)) { //first time in whereNamesMode = true; whereQualifiersMode = false; whereValuesMode = true; currentFpages = new ArrayList(); setWhereNames(); } if (lineWords.length > 0) { String lastWord = lineWords[lineWords.length - 1]; if (lastWord.equals(MartShellLib.QWHERE)) { lastFilterName = null; whereNamesMode = true; whereQualifiersMode = false; whereValuesMode = true; setWhereNames(); } else if (MartShellLib.ALLQUALIFIERS.contains(lastWord)) { if (lineWords.length > 1) { lastFilterName = lineWords[lineWords.length - 2]; pruneFilterPages(); } if (MartShellLib.BOOLEANQUALIFIERS.contains(lastWord)) { whereNamesMode = false; whereQualifiersMode = true; whereValuesMode = false; setEmptyMode(); } else { whereNamesMode = false; whereQualifiersMode = false; whereValuesMode = true; setWhereValues(lastWord); } } if (whereNamesMode) { if (msl.localDataset != null) { if (msl.localDataset.containsFilterDescription(lastWord)) { String thisField = msl.localDataset.getFilterDescriptionByInternalName(lastWord).getField(lastWord); if (thisField != null && thisField.length() > 0) { lastFilterName = lastWord; pruneFilterPages(); whereNamesMode = false; whereQualifiersMode = true; whereValuesMode = false; setWhereQualifiers(); } } } else if (!msl.usingLocalDataset && msl.envDataset != null) { if (msl.envDataset.containsFilterDescription(lastWord)) { FilterDescription thisFilter = msl.envDataset.getFilterDescriptionByInternalName(lastWord); String thisField = thisFilter.getField(lastWord); if (thisField != null && thisField.length() > 0) { lastFilterName = lastWord; pruneFilterPages(); logger.info(lastWord + " appears to be a filter, going to whereQualifiersMode\n"); whereNamesMode = false; whereQualifiersMode = true; whereValuesMode = false; setWhereQualifiers(); } } } else setNoDatasetConfigMode(); } else if (whereQualifiersMode) { if (MartShellLib.ALLQUALIFIERS.contains(lastWord)) { if (lineWords.length > 1) { lastFilterName = lineWords[lineWords.length - 2]; pruneFilterPages(); } if (MartShellLib.BOOLEANQUALIFIERS.contains(lastWord)) { setEmptyMode(); } else { whereQualifiersMode = false; whereValuesMode = true; setWhereValues(lastWord); } } else if (lastWord.equalsIgnoreCase(MartShellLib.FILTERDELIMITER)) { whereNamesMode = true; whereQualifiersMode = false; whereValuesMode = false; pruneFilterPages(); setWhereNames(); } } else if (whereValuesMode) { if (lastWord.equalsIgnoreCase(MartShellLib.FILTERDELIMITER)) { whereNamesMode = true; whereQualifiersMode = false; whereValuesMode = false; pruneFilterPages(); setWhereNames(); } } } } } lastLine = currentCommand; } } /** * Sets the MartCompleter into COMMAND mode * */ public void setCommandMode() { currentSet = new TreeSet(); currentSet.addAll(commandSet); // reset state to pristine setNoLocalDataset(); currentApages = new ArrayList(); currentFpages = new ArrayList(); lastFilterName = null; lastAttributeName = null; attributeMode = false; whereMode = false; whereNamesMode = false; whereQualifiersMode = false; whereValuesMode = false; lastLine = null; } private void setNoLocalDataset() { msl.localDataset = null; msl.usingLocalDataset = false; } private void setHelpMode() { currentSet = new TreeSet(); currentSet.addAll(helpSet); } private void setListMode(String token) { String[] toks = token.split("\\s+"); if (toks.length <= 1) { setListBaseMode(); } else { if (toks[1].equalsIgnoreCase("datasets") || toks[1].equalsIgnoreCase("datasetconfigs")) setAllAdaptorLocationMode(); } } private void setListBaseMode() { currentSet = new TreeSet(); currentSet.addAll(listSet); } private void setAddMode(String token) { String[] toks = token.split("\\s+"); if (toks.length == 1) setAddBaseMode(); else { if (toks[1].equalsIgnoreCase("Datasets")) { if (toks.length == 3 && toks[2].equalsIgnoreCase("from")) setEmptyMode(); else setFromMode(); } else { if (addBaseSet.contains(toks[1])) setEmptyMode(); } } } private void setAddBaseMode() { currentSet = new TreeSet(); currentSet.addAll(addBaseSet); } private void setEnvironmentMode() { currentSet = new TreeSet(); currentSet.addAll(environmentSet); } private void setRemoveMode(String token) { String[] toks = token.split("\\s+"); if (toks.length == 1) setRemoveBaseMode(); else if (toks.length == 2) { String request = toks[1]; if (request.equalsIgnoreCase("Mart")) setMartReqMode(); else if (request.equalsIgnoreCase("Datasets")) setFromMode(); else if (request.equalsIgnoreCase("Dataset")) setDatasetReqMode(); else if (request.equalsIgnoreCase("DatasetConfig")) setDatasetConfigReqMode(); else if (request.equalsIgnoreCase("Procedure")) setProcedureNameMode(); } else { if (toks.length == 3 && toks[2].equalsIgnoreCase("from")) setMartReqMode(); } } private void setRemoveBaseMode() { currentSet = new TreeSet(); currentSet.addAll(removeBaseSet); } private void setUpdateMode(String token) { String[] toks = token.split("\\s+"); if (toks.length == 1) setUpdateBaseMode(); else if (toks.length == 2) { String request = toks[1]; if (request.equalsIgnoreCase("Datasets")) setFromMode(); else { if (request.equalsIgnoreCase("Dataset")) setDatasetReqMode(); } } else { if (toks.length == 3 && toks[2].equalsIgnoreCase("from")) setMartReqMode(); } } private void setUpdateBaseMode() { currentSet = new TreeSet(); currentSet.addAll(updateBaseSet); } private void setSetUnsetMode(String token) { String[] toks = token.split("\\s+"); if (toks.length <= 1) setSetBaseMode(); else { try { if (toks[0].equals(SETC)) { if (toks[1].equalsIgnoreCase("mart")) { if (toks.length == 3 && msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName(toks[2]) ) ) setEmptyMode(); else setMartReqMode(); } else if (toks[1].equalsIgnoreCase("dataset")) { if (toks.length == 3 && msl.adaptorManager.supportsDataset(toks[2])) setEmptyMode(); else setDatasetReqMode(); } else if (toks.length < 3 && setBaseSet.contains(toks[1])) setEmptyMode(); } else { if (toks.length == 2 && setBaseSet.contains(toks[1])) setEmptyMode(); } } catch (ConfigurationException e) { setErrorMode("Caught ConfigurationException updating Completion System\n"); } } } private void setSetBaseMode() { currentSet = new TreeSet(); currentSet.addAll(setBaseSet); } private void setExecuteMode(String token) { String[] toks = token.split("\\s+"); if (toks.length == 1) setExecuteBaseMode(); else if (toks.length == 2) { if (toks[1].equalsIgnoreCase("Procedure")) setProcedureNameMode(); else { if (executeBaseSet.contains(toks[1])) setEmptyMode(); } } } private void setExecuteBaseMode() { currentSet = new TreeSet(); currentSet.addAll(executeBaseSet); } private void setDescribeMode(String token) { String[] toks = token.split("\\s+"); if (toks.length == 1) setBaseDescribeMode(); else if (toks.length >= 2) { String request = toks[1]; try { if (request.equalsIgnoreCase("dataset")) { if (toks.length == 3 && msl.adaptorManager.supportsDataset(toks[2])) setEmptyMode(); else setDatasetReqMode(); } else if (request.equalsIgnoreCase("Mart")) { if (toks.length == 3 && msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( toks[2] ) ) ) setEmptyMode(); else setMartReqMode(); } else if (request.equalsIgnoreCase("filter")) setDescribeFilterMode(); else if (request.equalsIgnoreCase("attribute")) setDescribeAttributeMode(); else { if (request.equalsIgnoreCase("procedure")) { setDescribeProcedureMode(); } } } catch (ConfigurationException e) { setErrorMode("Caught ConfigurationException updating Completion System\n"); } } } private void setBaseDescribeMode() { currentSet = new TreeSet(); currentSet.addAll(describeBaseSet); } private void setDatasetReqMode() { if (msl.envMart == null) setNoEnvMode(); else setDatasetReqMode(msl.envMart.getName()); } private void setDatasetReqMode(String martName) { currentSet = new TreeSet(); try { if (msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) ) ) currentSet.addAll(Arrays.asList(msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).getDatasetNames(false))); } catch (ConfigurationException e) { currentSet = new TreeSet(); setErrorMode("Couldng set describe dataset mode, caught Configuration Exception: " + e.getMessage() + "\n"); } } private void setUsingDatasetReqMode(String martName) { currentSet = new TreeSet(); try { if (msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) )) { String[] dsets = msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).getDatasetNames(false); for (int i = 0, n = dsets.length; i < n; i++) { String dset = dsets[i]; currentSet.add(martName+"."+dset); //martName.dataset } } } catch (ConfigurationException e) { currentSet = new TreeSet(); setErrorMode("Couldnot set describe dataset mode, caught Configuration Exception: " + e.getMessage() + "\n"); } } private void setDatasetConfigReqMode() { currentSet = new TreeSet(); if (msl.envMart == null) setNoEnvMode(); else { if (msl.envDataset == null) setNoEnvMode(); else setDatasetConfigReqMode(msl.envMart.getName(), msl.envDataset.getDataset()); } } private void setDatasetConfigReqMode(String martName, String datasetName) { currentSet = new TreeSet(); try { if (msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) ) && msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).supportsDataset(datasetName)) currentSet.addAll( Arrays.asList( msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).getDatasetConfigInternalNamesByDataset(datasetName))); } catch (ConfigurationException e) { currentSet = new TreeSet(); if (logger.isLoggable(Level.INFO)) logger.info("Couldng set dataset config req mode, caught Configuration Exception: " + e.getMessage() + "\n"); } } private void setUsingDatasetConfigReqMode(String martName, String datasetName) { currentSet = new TreeSet(); try { if (msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) ) && msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).supportsDataset(datasetName)) { String[] dnames = msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName )).getDatasetConfigInternalNamesByDataset(datasetName); for (int i = 0, n = dnames.length; i < n; i++) { String dname = dnames[i]; currentSet.add(martName+"."+datasetName+"."+dname); } } } catch (ConfigurationException e) { currentSet = new TreeSet(); if (logger.isLoggable(Level.INFO)) logger.info("Couldng set dataset config req mode, caught Configuration Exception: " + e.getMessage() + "\n"); } } private void setDescribeFilterMode() { if (msl.envDataset == null) setNoEnvMode(); else { currentSet = new TreeSet(); currentSet.addAll(msl.envDataset.getFilterCompleterNames()); } } private void setDescribeAttributeMode() { if (msl.envDataset == null) setNoEnvMode(); else { currentSet = new TreeSet(); currentSet.addAll(msl.envDataset.getAttributeCompleterNames()); } } private void setDescribeProcedureMode() { currentSet = new TreeSet(); currentSet.addAll(procSet); } private void setAttributeNames() { if (msl.localDataset != null) { currentSet = new TreeSet(); if (currentApages.size() == 0) currentApages = Arrays.asList(msl.localDataset.getAttributePages()); for (int i = 0, n = currentApages.size(); i < n; i++) { AttributePage apage = (AttributePage) currentApages.get(i); List completers = apage.getCompleterNames(); for (int j = 0, m = completers.size(); j < m; j++) { String completer = (String) completers.get(j); if (!currentSet.contains(completer)) currentSet.add(completer); } } } else if (!(msl.usingLocalDataset) && msl.envDataset != null) { currentSet = new TreeSet(); if (currentApages.size() == 0) currentApages = Arrays.asList(msl.envDataset.getAttributePages()); for (int i = 0, n = currentApages.size(); i < n; i++) { AttributePage apage = (AttributePage) currentApages.get(i); List completers = apage.getCompleterNames(); for (int j = 0, m = completers.size(); j < m; j++) { String completer = (String) completers.get(j); if (!currentSet.contains(completer)) currentSet.add(completer); } } } else setNoDatasetConfigMode(); } private void setFromMode() { currentSet = new TreeSet(); currentSet.add("from"); } private void setEmptyMode() { currentSet = new TreeSet(); } private void setNoDatasetConfigMode() { currentSet = new TreeSet(); currentSet.addAll(NODATASETWARNING); } private void setNoEnvMode() { currentSet = new TreeSet(); currentSet.addAll(NOENVWARNING); } private void setErrorMode(String error) { currentSet = new TreeSet(); currentSet.addAll(ERRORMODE); currentSet.add(error); } private void pruneAttributePages() { List newPages = new ArrayList(); if (msl.localDataset != null) newPages = msl.localDataset.getPagesForAttribute(lastAttributeName); else if (!msl.usingLocalDataset && msl.envDataset != null) newPages = msl.envDataset.getPagesForAttribute(lastAttributeName); else newPages = new ArrayList(); if (newPages.size() < currentApages.size()) currentApages = new ArrayList(newPages); } private void setDomainSpecificMode() { attributeMode = false; currentSet = new TreeSet(); //find all sequence attributes AttributePage seqPage = null; if (msl.usingLocalDataset) seqPage = msl.localDataset.getAttributePageByInternalName("sequences"); else seqPage = msl.envDataset.getAttributePageByInternalName("sequences"); if (seqPage == null) { setErrorMode("No sequences loaded in dataset " + msl.envDataset.getDisplayName() + "\n"); return; } AttributeGroup seqGroup = (AttributeGroup) seqPage.getAttributeGroupByName("sequence"); if (seqGroup == null) { setErrorMode("No sequences loaded in dataset " + msl.envDataset.getDisplayName() + "\n"); return; } AttributeCollection[] cols = seqGroup.getAttributeCollections(); AttributeCollection seqCol = null; for (int i = 0; i < cols.length; i++) { if (cols[i].getInternalName().matches("\\w*seq_scope\\w*")) { seqCol = cols[i]; break; } } if (seqCol == null) { setErrorMode("No sequences loaded in dataset " + msl.envDataset.getDisplayName() + "\n"); return; } currentSet.addAll(seqCol.getHiddenCompleterNames()); } private void setAllAdaptorLocationMode() { currentSet = new TreeSet(); currentSet.add("all"); try { String[] names = msl.adaptorManager.getAdaptorNames(); for (int i = 0, n = names.length; i < n; i++) { currentSet.add( msl.canonicalizeMartName( names[i] ) ); } } catch (ConfigurationException e) { if (logger.isLoggable(Level.INFO)) logger.info("Caught ConfigurationException getting adaptor names: " + e.getMessage() + "\n"); } } private void setMartReqMode() { currentSet = new TreeSet(); currentSet.addAll(martSet); } private void setUseDatasetMode(String token) { try { Pattern usePat = Pattern.compile(USEC + "\\s*(\\w*)(\\.?)(\\w*)(\\.?)(\\w*)"); Matcher useMatcher = usePat.matcher(token); Pattern usingPat = Pattern.compile(MartShellLib.USINGQSTART + "\\s*(\\w*)(\\.?)(\\w*)(\\.?)(\\w*)"); Matcher usingMatcher = usingPat.matcher(token); if (useMatcher.matches()) setUseDatasetModeWithMatcher(useMatcher); else if (usingMatcher.matches()) setUseDatasetModeWithMatcher(usingMatcher); } catch (ConfigurationException e) { setErrorMode("Caught ConfigurationException updating the Completion System\n"); } } private void setUseDatasetModeWithMatcher(Matcher matcher) throws ConfigurationException { String mat1 = matcher.group(1); String mat2 = matcher.group(2); String mat3 = matcher.group(3); String mat4 = matcher.group(4); String mat5 = matcher.group(5); if (validString(mat5)) { //using x.y.z if (validMartAndDataset(mat1, mat3)) { if (msl.adaptorManager.getDatasetConfigByDatasetInternalName(mat3, mat5) != null) setEmptyMode(); //nothing more to complete else setUsingDatasetConfigReqMode(mat1, mat3); //still in configreq } } else if (validString(mat4)) { //using x.y. if (validMartAndDataset(mat1, mat3)) setUsingDatasetConfigReqMode(mat1, mat3); } else if (validString(mat3)) { //using x.y if (validMartAndDataset(mat1, mat3)) setEmptyMode(); //nothing more to complete else if (validMart(mat1)) setUsingDatasetReqMode(mat1); else if (msl.envMart != null) if (validDatasetForMart(msl.envMart.getName(), mat3)) setEmptyMode(); //nothing more to complete else setDatasetReqMode(msl.envMart.getName()); else setNoEnvMode(); } else if (validString(mat2)) { //using x. if (validMart(mat1)) setUsingDatasetReqMode(mat1); else if (msl.envMart != null) { if (validDatasetForMart(msl.envMart.getName(), mat1)) setEmptyMode(); else setDatasetReqMode(msl.envMart.getName()); } else setNoEnvMode(); } else if (validString(mat1)) { //using x if (validMart(mat1)) setEmptyMode(); //nothing more to complete else if (msl.envMart != null) { //assume dataset relative to envMart setDatasetReqMode(msl.envMart.getName()); } else { //assume mart. request setMartReqMode(); } } else { //using if (msl.envMart != null) setDatasetReqMode(msl.envMart.getName()); else setMartReqMode(); } } private void setProcedureNameMode() { currentSet = new TreeSet(); currentSet.addAll(procSet); } private void setWhereNames() { if (msl.localDataset != null) { currentSet = new TreeSet(); if (currentFpages.size() == 0) currentFpages = Arrays.asList(msl.localDataset.getFilterPages()); for (int i = 0, n = currentFpages.size(); i < n; i++) { FilterPage fpage = (FilterPage) currentFpages.get(i); List completers = fpage.getCompleterNames(); for (int j = 0, m = completers.size(); j < m; j++) { String completer = (String) completers.get(j); if (!currentSet.contains(completer)) currentSet.add(completer); } } } else if (!(msl.usingLocalDataset) && msl.envDataset != null) { currentSet = new TreeSet(); if (currentFpages.size() == 0) currentFpages = Arrays.asList(msl.envDataset.getFilterPages()); for (int i = 0, n = currentFpages.size(); i < n; i++) { FilterPage fpage = (FilterPage) currentFpages.get(i); List completers = fpage.getCompleterNames(); for (int j = 0, m = completers.size(); j < m; j++) { String completer = (String) completers.get(j); if (!currentSet.contains(completer)) currentSet.add(completer); } } } else setNoDatasetConfigMode(); } private void setWhereQualifiers() { currentSet = new TreeSet(); if (msl.localDataset != null) { if (msl.localDataset.containsFilterDescription(lastFilterName)) currentSet.addAll(msl.localDataset.getFilterCompleterQualifiersByInternalName(lastFilterName)); } else if (!msl.usingLocalDataset && msl.envDataset != null) { if (logger.isLoggable(Level.INFO)) logger.info("getting qualifiers for filter " + lastFilterName + "\n"); if (msl.envDataset.containsFilterDescription(lastFilterName)) { if (logger.isLoggable(Level.INFO)) logger.info("Its a filter, getting from dataset\n"); currentSet.addAll(msl.envDataset.getFilterCompleterQualifiersByInternalName(lastFilterName)); } } else setNoDatasetConfigMode(); } private void setWhereValues(String lastWord) { currentSet = new TreeSet(); if (msl.localDataset != null) { if (msl.localDataset.containsFilterDescription(lastFilterName)) { currentSet.addAll(msl.localDataset.getFilterCompleterValuesByInternalName(lastFilterName)); if (lastWord.equalsIgnoreCase("in")) currentSet.addAll(procSet); } } else if (!msl.usingLocalDataset && msl.envDataset != null) { if (msl.envDataset.containsFilterDescription(lastFilterName)) { currentSet.addAll(msl.envDataset.getFilterCompleterValuesByInternalName(lastFilterName)); if (lastWord.equalsIgnoreCase("in")) currentSet.addAll(procSet); } } else setNoDatasetConfigMode(); } private void pruneFilterPages() { List newPages = new ArrayList(); if (msl.localDataset != null) newPages = msl.localDataset.getPagesForFilter(lastFilterName); else if (!msl.usingLocalDataset && msl.envDataset != null) newPages = msl.envDataset.getPagesForFilter(lastFilterName); else newPages = new ArrayList(); if (newPages.size() < currentFpages.size()) currentFpages = new ArrayList(newPages); } /** * Set the String names (path, url, Mart name) used to refer * to locations from whence DSConfigAdaptor objects were loaded. * @param names -- names of path, url, or Mart names from whence DSConfigAdaptor Objects were loaded */ public void setAdaptorLocations(Collection names) { adaptorLocationSet = new TreeSet(); adaptorLocationSet.addAll(names); } public void setDatasetConfigInternalNames(Collection names) { datasetConfigSet = new TreeSet(); datasetConfigSet.addAll(names); } /** * Set the Names used to refer to Mart Objects in the Shell. * @param names -- names used to refer to Mart Objects in the Shell. */ public void setMartNames(Collection names) { martSet = new TreeSet(); martSet.addAll(names); } /** * Set the names of stored procedures * @param names -- names of stored procedures */ public void setProcedureNames(Collection names) { procSet = new TreeSet(); procSet.addAll(names); } /** * Set the Base Shell Commands available * @param names -- base commands available to the Shell. */ public void setBaseCommands(Collection names) { commandSet = new TreeSet(); commandSet.addAll(names); } /** * set Help commands * @param names -- help commands */ public void setHelpCommands(Collection names) { helpSet = new TreeSet(); helpSet.addAll(names); } /** * Set the add command sub tokens * @param addRequests -- add command sub tokens */ public void setAddCommands(Collection requests) { addBaseSet = new TreeSet(); addBaseSet.addAll(requests); } /** * Set the Base Remove sub tokens * @param removeRequests -- base remove sub tokens */ public void setRemoveBaseCommands(Collection requests) { removeBaseSet = new TreeSet(); removeBaseSet.addAll(requests); } /** * Set the List command sub tokens * @param listRequests -- list command sub tokens */ public void setListCommands(Collection requests) { listSet = new TreeSet(); listSet.addAll(requests); } /** * Set the Update command base sub tokens * @param updateRequests -- update command base sub tokens */ public void setUpdateBaseCommands(Collection requests) { updateBaseSet = new TreeSet(); updateBaseSet.addAll(requests); } /** * Set the Set command base sub tokens * @param requests -- Set command base sub tokens */ public void setSetBaseCommands(Collection requests) { setBaseSet = new TreeSet(); setBaseSet.addAll(requests); } /** * Set the Describe command base sub tokens * @param describeRequests -- describe command base sub tokens */ public void setDescribeBaseCommands(Collection requests) { describeBaseSet = new TreeSet(); describeBaseSet.addAll(requests); } /** * Set the Environment command base sub tokens * @param envRequests -- environment command base sub tokens */ public void setEnvironmentBaseCommands(Collection requests) { environmentSet = new TreeSet(); environmentSet.addAll(requests); } /** * Sets the Execute command base sub tokens * @param executeRequests -- execute command base sub tokens */ public void setExecuteBaseCommands(Collection requests) { executeBaseSet = new TreeSet(); executeBaseSet.addAll(requests); } private void logInfo(String message) { if (logger.isLoggable(Level.INFO)) logger.info(message); } private void logWarning(String message) { if (logger.isLoggable(Level.WARNING)) logger.warning(message); } private boolean validString(String input) { return input != null && input.length() > 0; } private boolean validMartAndDataset(String martName, String dataset) throws ConfigurationException { return msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) ) && msl.adaptorManager.supportsDataset(dataset); } private boolean validDatasetForMart(String martName, String dataset) throws ConfigurationException { return msl.adaptorManager.getAdaptorByName( msl.deCanonicalizeMartName( martName ) ).supportsDataset(dataset); } private boolean validMart(String martName) throws ConfigurationException { return msl.adaptorManager.supportsAdaptor( msl.deCanonicalizeMartName( martName ) ); } }