Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/new_class_id: some thoughts on a BaseIterator class, that can travers through ObejectLists without knowing the Polymorph type.
This is all virtual, and since templated virutal functions are not allowed, quite hard to implements…
hpe it will work

File size: 13.6 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  SHELL_COMMAND(debug, ShellCommandClass, help);
29  NewObjectListDefinition(ShellCommand);
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* 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* 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 std::list<BaseObject*>* objectList = ClassList::getList(cmd->shellClass->getName());
244    if (objectList != NULL)
245    {
246      std::list<BaseObject*>::const_iterator bo;
247
248      // No Description given (only for speedup)
249      if (objectDescriptor.empty())
250      {
251        for (bo = objectList->begin(); bo != objectList->end(); bo++)
252          boList->push_back(*bo);
253      }
254      // some description
255      else
256      {
257        for (bo = objectList->begin(); bo != objectList->end(); bo++)
258          if (!nocaseCmp(objectDescriptor, (*bo)->getName(), objectDescriptor.size()))
259            boList->push_back(*bo);
260      }
261    }
262    return !boList->empty();
263  }
264
265  /**
266   * @brief checks if a command has already been registered.
267   * @param commandName the name of the Command
268   * @param className the name of the Class the command should apply to.
269   * @returns true, if the command is registered/false otherwise
270   *
271   * This is used internally, to see, if we have multiple command subscriptions.
272   * This is checked in the registerCommand-function.
273   */
274  bool ShellCommand::exists(const std::string& commandName, const std::string& className)
275  {
276    return (ShellCommand::getCommand(commandName, className) != NULL);
277  }
278
279
280  /**
281   * @brief executes commands
282   * @param executionString the string containing the following input
283   * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
284   * @return true on success, false otherwise.
285   */
286  bool ShellCommand::execute(const std::string& executionString)
287  {
288    SubString inputSplits(executionString, SubString::WhiteSpacesWithComma);
289
290    // if we do not have any input return
291    if (inputSplits.empty())
292      return false;
293
294    unsigned int paramBegin;
295    const ShellCommand* sc = NULL;
296    std::vector<BaseObject*> boList;
297    sc = getCommandFromInput(inputSplits, paramBegin, &boList);
298    if (sc != NULL)
299    {
300      for(std::vector<BaseObject*>::const_iterator bo = boList.begin(); bo != boList.end(); ++bo)
301      {
302        PRINT(0)("Command '%s' on '%s::%s'\n", sc->getCName(), (*bo)->getClassCName(), (*bo)->getCName());
303        (*sc->executor)((*bo), inputSplits.subSet(paramBegin));
304      }
305      return true;
306    }
307    return false;
308  }
309
310
311  /**
312   * @brief lets a command be described
313   * @param description the description of the Given command
314   */
315  ShellCommand* ShellCommand::describe(const std::string& description)
316  {
317    if (this == NULL)
318      return NULL;
319    this->description = description;
320    return this;
321  }
322
323  /**
324   * @brief adds an Alias to this Command
325   * @param alias the name of the Alias to set
326   * @returns itself
327   */
328  ShellCommand* ShellCommand::setAlias(const std::string& alias)
329  {
330    if (this == NULL)
331      return NULL;
332
333    if (this->alias != NULL)
334    {
335      PRINTF(2)("not more than one Alias allowed for functions (%s::%s)\n", this->getCName(), this->shellClass->getCName());
336    }
337    else
338    {
339      ShellCommandAlias* aliasCMD = new ShellCommandAlias(alias, this);
340      this->alias = aliasCMD;
341    }
342    return this;
343  }
344
345  /**
346   * @brief set the default values of the executor
347   * @param value0 the first default value
348   * @param value1 the second default value
349   * @param value2 the third default value
350   * @param value3 the fourth default value
351   * @param value4 the fifth default value
352   */
353  ShellCommand* ShellCommand::defaultValues(const MultiType& value0, const MultiType& value1,
354      const MultiType& value2, const MultiType& value3,
355      const MultiType& value4)
356  {
357    if (this == NULL || this->executor == NULL)
358      return NULL;
359
360    this->executor->defaultValues(value0, value1, value2, value3, value4);
361
362    return this;
363  }
364
365  ShellCommand* ShellCommand::completionPlugin(unsigned int parameter, const CompletorPlugin& completorPlugin)
366  {
367    if (this == NULL || this->executor == NULL)
368      return NULL;
369
370    if (parameter >= this->executor->getParamCount())
371    {
372      PRINTF(1)("Parameter %d not inside of valid ParameterCount %d of Command %s::%s\n",
373                parameter, this->executor->getParamCount(), this->getCName(), this->shellClass->getCName());
374    }
375    else
376    {
377//       if(this->completors[parameter] == NULL)
378//       delete this->completors[parameter];
379//       this->completors[parameter] = completorPlugin.clone();
380    }
381    return this;
382  }
383
384  /**
385   * @brief prints a Help string from this Command
386   */
387  void ShellCommand::help() const
388  {
389    PRINT(0)("%s ", this->getCName());
390  }
391
392  /**
393   * @brief converts a Parameter to a String
394   * @param parameter the Parameter we have.
395   * @returns the Name of the Parameter at Hand
396   */
397  const std::string& ShellCommand::paramToString(long parameter)
398  {
399    return MultiType::MultiTypeToString((MT_Type)parameter);
400  }
401
402
403
404  ///////////
405  // ALIAS //
406  ///////////
407
408  /**
409   * @param aliasName the name of the Alias
410   * @param command the Command, to associate this alias with
411   */
412  ShellCommandAlias::ShellCommandAlias(const std::string& aliasName, ShellCommand* command)
413  {
414    this->aliasName = aliasName;
415    this->command = command;
416    ShellCommandAlias::aliasList.push_back(this);
417  };
418
419  ShellCommandAlias::~ShellCommandAlias()
420  {
421    std::vector<ShellCommandAlias*>::iterator delA = std::find(aliasList.begin(), aliasList.end(), this);
422    if (delA != aliasList.end())
423      ShellCommandAlias::aliasList.push_back(this);
424
425  }
426
427  std::vector<ShellCommandAlias*> ShellCommandAlias::aliasList;
428  /**
429  * @brief collects the Aliases registered to the ShellCommands
430  * @param stringList a List to paste the Aliases into.
431  * @returns true on success, false otherwise
432   */
433
434  bool ShellCommandAlias::getCommandListOfAlias(std::list<std::string>& stringList)
435  {
436    std::vector<ShellCommandAlias*>::iterator alias;
437    for (alias = ShellCommandAlias::aliasList.begin(); alias != ShellCommandAlias::aliasList.end(); alias++)
438      stringList.push_back((*alias)->getName());
439    return true;
440  }
441
442
443}
Note: See TracBrowser for help on using the repository browser.