Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/new_class_id/src/lib/shell/shell_command.cc @ 9727

Last change on this file since 9727 was 9727, checked in by bensch, 18 years ago

orxonox/new_class_id: new Executor construct, that is much more typesafe, faster, and easier to extend…

Also changed the LoadParam process, and adapted ScriptEngine calls

Then at the end, some missing headers appeared, and appended them to all the cc-files again.

File size: 13.7 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: ...
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
17
18#include "shell_command.h"
19#include "shell_command_class.h"
20
21#include "compiler.h"
22#include "debug.h"
23
24#include "key_names.h"
25
26namespace OrxShell
27{
28  ObjectListDefinition(ShellCommand);
29  SHELL_COMMAND(debug, ShellCommandClass, help);
30
31
32  /**
33   * @brief constructs and registers a new Command
34   * @param commandName the name of the Command
35   * @param className the name of the class to apply this command to
36   * @param paramCount the count of parameters this command takes
37   */
38  ShellCommand::ShellCommand(const std::string& commandName, const std::string& className, Executor<const SubString>* executor)
39  {
40    this->registerObject(this, ShellCommand::_objectList);
41    PRINTF(4)("create shellcommand '%s' for class '%s'\n", commandName.c_str(), className.c_str());
42    this->setName(commandName);
43
44    // copy the executor:
45    this->executor = executor;
46    this->executor->setName(commandName);
47
48    for (unsigned int i = 0; i < this->executor->getParamCount(); i++)
49      this->completors.push_back(new CompletorDefault(&this->executor->getDefaultValue(i)));
50    this->alias = NULL;
51
52    //  this->classID = classID;
53    this->shellClass = ShellCommandClass::acquireCommandClass(className);
54    assert (this->shellClass != NULL);
55    this->shellClass->registerCommand(this);
56  }
57
58  /**
59   * @brief deconstructs a ShellCommand
60   */
61  ShellCommand::~ShellCommand()
62  {
63    this->shellClass->unregisterCommand(this);
64    if (this->alias != NULL)
65      delete this->alias;
66    while (!this->completors.empty())
67    {
68      delete this->completors.back();
69      this->completors.pop_back();
70    }
71    delete this->executor;
72  }
73
74  /**
75   * @brief registers a new ShellCommand
76   */
77  ShellCommand* ShellCommand::registerCommand(const std::string& commandName, const std::string& className, Executor<const SubString>* executor)
78  {
79    if (ShellCommand::exists(commandName, className))
80    {
81      delete executor;
82      return NULL;
83    }
84    else
85      return new ShellCommand(commandName, className, executor);
86
87  }
88
89  /**
90   * @brief unregister an existing commandName
91   * @param className the name of the Class the command belongs to.
92   * @param commandName the name of the command itself
93   */
94  void ShellCommand::unregisterCommand(const std::string& commandName, const std::string& className)
95  {
96    ShellCommandClass* cmdClass = ShellCommandClass::acquireCommandClass(className);
97    if (cmdClass != NULL)
98    {
99      CmdList::iterator cmd;
100      for (cmd = cmdClass->_commandList.begin(); cmd != cmdClass->_commandList.end(); cmd++)
101        if (commandName == (*cmd)->getName())
102        {
103          delete (*cmd);
104          break;
105        }
106    }
107  }
108
109  /**
110   * @brief gets a command if it has already been registered.
111   * @param commandName the name of the Command
112   * @param cmdClass the CommandClass of the Class the command is in.
113   * @returns The Registered Command, or NULL if it does not exist.
114   */
115  const ShellCommand* const ShellCommand::getCommand(const std::string& commandName, const ShellCommandClass* cmdClass)
116  {
117    assert(cmdClass != NULL);
118
119    CmdList::const_iterator elem;
120    for (unsigned int i = 0; i < cmdClass->_commandList.size(); i++)
121    {
122      if (commandName == cmdClass->_commandList[i]->getName())
123        return (cmdClass->_commandList[i]);
124    }
125    return NULL;
126  }
127
128
129  /**
130   * @brief gets a command if it has already been registered.
131   * @param commandName the name of the Command
132   * @param className the name of the Class the command is in.
133   * @returns The Registered Command, or NULL if it does not exist.
134   */
135  const ShellCommand* const ShellCommand::getCommand(const std::string& commandName, const std::string& className)
136  {
137    const ShellCommandClass* checkClass = ShellCommandClass::getCommandClass(className);
138    if (likely(checkClass != NULL))
139      return ShellCommand::getCommand(commandName, checkClass);
140    else
141      return NULL;
142  }
143
144  /**
145   * @brief takes out an InputLine, searching for a Command.
146   * @see const ShellCommand* const ShellCommand::getCommandFromInput(const SubString& strings)
147   * @param inputLine: the Input to analyse.
148   * @param paramBegin: The begin of the Splitted SubStrings entry of the Parameters section.
149   * @returns: The ShellCommand if found.
150   */
151  const ShellCommand* const ShellCommand::getCommandFromInput(const std::string& inputLine, unsigned int& paramBegin, std::vector<BaseObject*>* boList)
152  {
153    return ShellCommand::getCommandFromInput(SubString(inputLine, SubString::WhiteSpaces), paramBegin, boList);
154  }
155
156  /**
157   * @brief takes out an InputLine, searching for a Command.
158   * @param strings: the Input to analyse.
159   * @param paramBegin: The begin of the Splitted SubStrings entry of the Parameters section.
160   * @returns: The ShellCommand if found.
161   */
162  const ShellCommand* const ShellCommand::getCommandFromInput(const SubString& strings, unsigned int& paramBegin, std::vector<BaseObject*>* boList)
163  {
164    // no input, no Command.
165    if (strings.size() == 0)
166    {
167      paramBegin = 0;
168      return NULL;
169    }
170
171    // CHECK FOR ALIAS
172    std::vector<ShellCommandAlias*>::const_iterator alias;
173    for (alias = ShellCommandAlias::getAliases().begin(); alias != ShellCommandAlias::getAliases().end(); alias++ )
174    {
175      if (strings[0] == (*alias)->getName())
176      {
177        assert ((*alias)->getCommand() != NULL && (*alias)->getCommand()->shellClass != NULL);
178        // Search for Objects.
179        if (strings.size() == 1)
180        {
181          if (fillObjectList("", (*alias)->getCommand(), boList))
182            ;
183        }
184        else
185        {
186          if (!fillObjectList(strings[1], (*alias)->getCommand(), boList))
187            fillObjectList("", (*alias)->getCommand(), boList);
188        }
189        paramBegin = 1;
190        return (*alias)->getCommand();
191      }
192    }
193
194    // CHECK FOR COMMAND_CLASS
195    const ShellCommandClass* cmdClass = ShellCommandClass::getCommandClass(strings[0]);
196    if (cmdClass != NULL)
197    {
198      const ShellCommand* retCmd = NULL;
199      // Function/Command right after Class
200      if (strings.size() >= 1)
201      {
202        // Search for Objects.
203        retCmd = ShellCommand::getCommand((strings.size() > 1) ? strings[1] : "", cmdClass);
204        if (retCmd != NULL)
205        {
206          paramBegin = 2;
207          fillObjectList("", retCmd, boList);
208          return retCmd;
209        }
210      }
211      // Function/Command after Class and 'Object'
212      if (retCmd == NULL && strings.size() >= 2)
213      {
214        retCmd = ShellCommand::getCommand((strings.size() > 2) ? strings[2] : "", cmdClass);
215        if (retCmd != NULL)
216        {
217          paramBegin = 3;
218          fillObjectList(strings[1], retCmd, boList);
219          return retCmd;
220        }
221      }
222      if (retCmd != NULL) // check for the paramBegin.
223        return retCmd;
224    }
225    // Nothing usefull found at all.
226    paramBegin = 0;
227    return NULL;
228  }
229
230  /**
231   * @brief fills the ObjectList boList with Objects that can be reffered to by cmd.
232   * @param objectDescriptor: the ObjectName (beginning, full name or empty) to fill the List with
233   * @param cmd: The Command to complete Objects for.
234   * @param boList: The List of BaseObject's that will be filled with found entries.
235   * @returns: true if more than one Entry was fond, else (false , or if boList is NULL).
236   */
237  bool ShellCommand::fillObjectList(const std::string& objectDescriptor, const ShellCommand* cmd, std::vector<BaseObject*>* boList)
238  {
239    assert (cmd != NULL && cmd->shellClass != NULL);
240    if(boList == NULL)
241      return false;
242
243    const ObjectListBase* const objectList = ObjectListBase::getObjectList(cmd->shellClass->getName());
244    if (objectList != NULL)
245    {
246      ObjectListBase::base_list list;
247      objectList->getBaseObjectList(&list);
248      ObjectListBase::base_iterator it;
249
250      // No Description given (only for speedup)
251      if (objectDescriptor.empty())
252      {
253        for (it = list.begin(); it != list.end(); it++)
254          boList->push_back(*it);
255      }
256      // some description
257      else
258      {
259        for (it = list.begin(); it != list.end(); it++)
260          if (!nocaseCmp(objectDescriptor, (*it)->getName(), objectDescriptor.size()))
261            boList->push_back(*it);
262      }
263    }
264    return !boList->empty();
265  }
266
267  /**
268   * @brief checks if a command has already been registered.
269   * @param commandName the name of the Command
270   * @param className the name of the Class the command should apply to.
271   * @returns true, if the command is registered/false otherwise
272   *
273   * This is used internally, to see, if we have multiple command subscriptions.
274   * This is checked in the registerCommand-function.
275   */
276  bool ShellCommand::exists(const std::string& commandName, const std::string& className)
277  {
278    return (ShellCommand::getCommand(commandName, className) != NULL);
279  }
280
281
282  /**
283   * @brief executes commands
284   * @param executionString the string containing the following input
285   * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
286   * @return true on success, false otherwise.
287   */
288  bool ShellCommand::execute(const std::string& executionString)
289  {
290    SubString inputSplits(executionString, SubString::WhiteSpacesWithComma);
291
292    // if we do not have any input return
293    if (inputSplits.empty())
294      return false;
295
296    unsigned int paramBegin;
297    const ShellCommand* sc = NULL;
298    std::vector<BaseObject*> boList;
299    sc = getCommandFromInput(inputSplits, paramBegin, &boList);
300    if (sc != NULL)
301    {
302      for(std::vector<BaseObject*>::const_iterator bo = boList.begin(); bo != boList.end(); ++bo)
303      {
304        PRINT(0)("Command '%s' on '%s::%s'\n", sc->getCName(), (*bo)->getClassCName(), (*bo)->getCName());
305        (*sc->executor)((*bo), inputSplits.subSet(paramBegin));
306      }
307      return true;
308    }
309    return false;
310  }
311
312
313  /**
314   * @brief lets a command be described
315   * @param description the description of the Given command
316   */
317  ShellCommand* ShellCommand::describe(const std::string& description)
318  {
319    if (this == NULL)
320      return NULL;
321    this->description = description;
322    return this;
323  }
324
325  /**
326   * @brief adds an Alias to this Command
327   * @param alias the name of the Alias to set
328   * @returns itself
329   */
330  ShellCommand* ShellCommand::setAlias(const std::string& alias)
331  {
332    if (this == NULL)
333      return NULL;
334
335    if (this->alias != NULL)
336    {
337      PRINTF(2)("not more than one Alias allowed for functions (%s::%s)\n", this->getCName(), this->shellClass->getCName());
338    }
339    else
340    {
341      ShellCommandAlias* aliasCMD = new ShellCommandAlias(alias, this);
342      this->alias = aliasCMD;
343    }
344    return this;
345  }
346
347  /**
348   * @brief set the default values of the executor
349   * @param value0 the first default value
350   * @param value1 the second default value
351   * @param value2 the third default value
352   * @param value3 the fourth default value
353   * @param value4 the fifth default value
354   */
355  ShellCommand* ShellCommand::defaultValues(const MultiType& value0, const MultiType& value1,
356      const MultiType& value2, const MultiType& value3,
357      const MultiType& value4)
358  {
359    if (this == NULL || this->executor == NULL)
360      return NULL;
361
362    this->executor->defaultValues(value0, value1, value2, value3, value4);
363
364    return this;
365  }
366
367  ShellCommand* ShellCommand::completionPlugin(unsigned int parameter, const CompletorPlugin& completorPlugin)
368  {
369    if (this == NULL || this->executor == NULL)
370      return NULL;
371
372    if (parameter >= this->executor->getParamCount())
373    {
374      PRINTF(1)("Parameter %d not inside of valid ParameterCount %d of Command %s::%s\n",
375                parameter, this->executor->getParamCount(), this->getCName(), this->shellClass->getCName());
376    }
377    else
378    {
379//       if(this->completors[parameter] == NULL)
380//       delete this->completors[parameter];
381//       this->completors[parameter] = completorPlugin.clone();
382    }
383    return this;
384  }
385
386  /**
387   * @brief prints a Help string from this Command
388   */
389  void ShellCommand::help() const
390  {
391    PRINT(0)("%s ", this->getCName());
392  }
393
394  /**
395   * @brief converts a Parameter to a String
396   * @param parameter the Parameter we have.
397   * @returns the Name of the Parameter at Hand
398   */
399  const std::string& ShellCommand::paramToString(long parameter)
400  {
401    return MultiType::MultiTypeToString((MT_Type)parameter);
402  }
403
404
405
406  ///////////
407  // ALIAS //
408  ///////////
409
410  /**
411   * @param aliasName the name of the Alias
412   * @param command the Command, to associate this alias with
413   */
414  ShellCommandAlias::ShellCommandAlias(const std::string& aliasName, ShellCommand* command)
415  {
416    this->aliasName = aliasName;
417    this->command = command;
418    ShellCommandAlias::aliasList.push_back(this);
419  };
420
421  ShellCommandAlias::~ShellCommandAlias()
422  {
423    std::vector<ShellCommandAlias*>::iterator delA = std::find(aliasList.begin(), aliasList.end(), this);
424    if (delA != aliasList.end())
425      ShellCommandAlias::aliasList.push_back(this);
426
427  }
428
429  std::vector<ShellCommandAlias*> ShellCommandAlias::aliasList;
430  /**
431  * @brief collects the Aliases registered to the ShellCommands
432  * @param stringList a List to paste the Aliases into.
433  * @returns true on success, false otherwise
434   */
435
436  bool ShellCommandAlias::getCommandListOfAlias(std::list<std::string>& stringList)
437  {
438    std::vector<ShellCommandAlias*>::iterator alias;
439    for (alias = ShellCommandAlias::aliasList.begin(); alias != ShellCommandAlias::aliasList.end(); alias++)
440      stringList.push_back((*alias)->getName());
441    return true;
442  }
443
444
445}
Note: See TracBrowser for help on using the repository browser.