Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/shell/shell_command.cc @ 7398

Last change on this file since 7398 was 7398, checked in by bensch, 20 years ago

orxonox/trunk: SubString more functionality

File size: 11.9 KB
RevLine 
[4744]1/*
[1853]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.
[1855]10
11   ### File Specific:
[5068]12   main-programmer: Benjamin Grauer
[1855]13   co-programmer: ...
[1853]14*/
15
[7374]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_SHELL
[1853]17
[5129]18#include "shell_command.h"
[5639]19#include "shell_command_class.h"
[1853]20
[6222]21#include "compiler.h"
[5129]22#include "debug.h"
[5113]23#include "class_list.h"
24
25#include "key_names.h"
[5075]26
[7374]27namespace OrxShell
[3365]28{
[7394]29  SHELL_COMMAND_STATIC(debug, ShellCommand, ShellCommand::debug);
[5141]30
[7394]31
[7374]32  /**
[7394]33   * @brief constructs and registers a new Command
[7374]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, const Executor& executor)
39  {
40    this->setClassID(CL_SHELL_COMMAND, "ShellCommand");
41    PRINTF(5)("create shellcommand %s %s\n", commandName, className);
42    this->setName(commandName);
[7398]43
44    // copy the executor:
[7374]45    this->executor = executor.clone();
46    this->executor->setName(commandName);
[7398]47
[7388]48    this->alias = NULL;
[4320]49
[7374]50    //  this->classID = classID;
[7388]51    this->shellClass = ShellCommandClass::getCommandClass(className);
[7398]52    assert (this->shellClass != NULL);
53    this->shellClass->commandList.push_back(this);
[7374]54  }
55
56  /**
[7394]57   * @brief deconstructs a ShellCommand
[7374]58   */
59  ShellCommand::~ShellCommand()
[5196]60  {
[7389]61    if (this->alias != NULL)
[7374]62      delete this->alias;
63    delete this->executor;
[5196]64  }
[1853]65
[7374]66  /**
[7398]67   * @brief registers a new ShellCommand
[7374]68   */
69  ShellCommand* ShellCommand::registerCommand(const std::string& commandName, const std::string& className, const Executor& executor)
70  {
71    if (ShellCommand::isRegistered(commandName, className))
72      return NULL;
73    else
74      return new ShellCommand(commandName, className, executor);
[5636]75
[7374]76  }
[5636]77
[7374]78  /**
[7398]79   * @brief unregister an existing commandName
[7374]80   * @param className the name of the Class the command belongs to.
81   * @param commandName the name of the command itself
82   */
83  void ShellCommand::unregisterCommand(const std::string& commandName, const std::string& className)
84  {
85    /// FIXME
86    /*  if (ShellCommandClass::commandClassList == NULL)
87        ShellCommandClass::initCommandClassList();
[5171]88
[7374]89     const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
[5171]90
[7374]91     if (checkClass != NULL)
[5171]92      {
[7374]93        std::list<ShellCommand*>::iterator elem;
94        for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
[7340]95        {
[7374]96          if (!strcmp(commandName, (*elem)->getName()))
97          {
98            delete (*elem);
99            checkClass->commandList.remove(*elem);
100            break;
101          }
[7340]102        }
[5171]103
[7374]104        if (checkClass->commandList->size() == 0)
105        {
106          ShellCommandClass::commandClassList->remove(checkClass);
107          delete checkClass;
108        }
109      }*/
[5113]110  }
[5105]111
[7374]112  /**
[7394]113   * @brief checks if a command has already been registered.
[7374]114   * @param commandName the name of the Command
115   * @param className the name of the Class the command should apply to.
116   * @returns true, if the command is registered/false otherwise
117   *
118   * This is used internally, to see, if we have multiple command subscriptions.
119   * This is checked in the registerCommand-function.
120   */
121  bool ShellCommand::isRegistered(const std::string& commandName, const std::string& className)
[5113]122  {
[7374]123    const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
124    if (checkClass != NULL)
125    {
[7388]126      std::vector<ShellCommand*>::const_iterator elem;
[7374]127      for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
[5779]128      {
[7374]129        if (commandName == (*elem)->getName())
130        {
131          PRINTF(2)("Command '%s::%s' already registered\n", className.c_str(), commandName.c_str());
132          return true;
133        }
[5170]134      }
[7374]135      return false;
[5779]136    }
[7374]137    else
138      return false;
[5113]139  }
140
[5140]141
[7374]142  /**
[7394]143   * @brief executes commands
[7374]144   * @param executionString the string containing the following input
145   * ClassName [ObjectName] functionName [parameter1[,parameter2[,...]]]
146   * @return true on success, false otherwise.
147   */
148  bool ShellCommand::execute(const std::string& executionString)
149  {
150    long classID = CL_NULL;                      //< the classID retrieved from the Class.
151    ShellCommandClass* commandClass = NULL;      //< the command class this command applies to.
152    const std::list<BaseObject*>* objectList = NULL;   //< the list of Objects stored in classID
153    BaseObject* objectPointer = NULL;            //< a pointer to th Object to Execute the command on
154    bool emptyComplete = false;                  //< if the completion input is empty string. e.g ""
155    //  long completeType = SHELLC_NONE;           //< the Type we'd like to complete.
156    SubString inputSplits(executionString, SubString::WhiteSpacesWithComma);
[5198]157
[7340]158
[7374]159    // if we do not have any input return
160    if (inputSplits.empty())
161      return false;
[7340]162
[7374]163    // if we only have one input (!MUST BE AN ALIAS)
164    if (inputSplits.size() >= 1)
[5198]165    {
[7374]166      // CHECK FOR ALIAS
[7397]167      std::vector<ShellCommandAlias*>::const_iterator alias;
168      for (alias = ShellCommandAlias::getAliases().begin(); alias != ShellCommandAlias::getAliases().end(); alias++ )
[5198]169      {
[7389]170        if (inputSplits.getString(0) == (*alias)->getName() && (*alias)->getCommand() != NULL &&
171            (*alias)->getCommand()->shellClass != NULL )
[5198]172        {
[7389]173          objectList = ClassList::getList((*alias)->getCommand()->shellClass->getName());
174          if (objectList != NULL)
[5199]175          {
[7389]176            (*(*alias)->getCommand()->executor)(objectList->front(), inputSplits.getSubSet(1).join());
177            return true;
[5199]178          }
[7389]179          /// TODO CHECK FOR STATIC functions.
[5198]180        }
181      }
[7340]182
[7374]183      // looking for a Matching Class
[7394]184      std::vector<ShellCommandClass*>::iterator commandClassIT;
185      for (commandClassIT = ShellCommandClass::commandClassList.begin(); commandClassIT != ShellCommandClass::commandClassList.end(); commandClassIT++)
[5203]186      {
[7394]187        if ((*commandClassIT)->getName() && inputSplits[0] == (*commandClassIT)->getName())
[5203]188        {
[7394]189          //elemCL->getName();
190          classID = ClassList::StringToID((*commandClassIT)->getName());
191          commandClass = (*commandClassIT);
192          objectList = ClassList::getList((ClassID)classID);
193          break;
[5203]194        }
195      }
[5200]196
[7374]197      // Second Agument. (either Object, or Function)
198      if (commandClass != NULL && inputSplits.size() >= 2)
[5203]199      {
[7374]200        int fktPos = 1; // The position of the Function (either at pos 1, or 2)
201        // If we have an ObjectList.
202        if (objectList != NULL)
[5203]203        {
[7374]204          // Checking for a Match in the Objects of classID (else take the first)
205          std::list<BaseObject*>::const_iterator object;
206          for (object = objectList->begin(); object != objectList->end(); object++)
[5329]207          {
[7374]208            if ((*object)->getName() != NULL && inputSplits[1] == (*object)->getName())
209            {
210              objectPointer = (*object);
211              fktPos = 2;
212              break;
213            }
[5329]214          }
[7374]215
216          // if we did not find an Object with matching name, take the first.
217          if (objectPointer == NULL)
218            objectPointer = objectList->front();
[7340]219        }
[5203]220
[7374]221        // match a function.
222        if (commandClass != NULL && (fktPos == 1 || (fktPos == 2 && inputSplits.size() >= 3)))
[5203]223        {
[7388]224          std::vector<ShellCommand*>::iterator cmdIT;
[7374]225          for (cmdIT = commandClass->commandList.begin(); cmdIT != commandClass->commandList.end(); cmdIT++)
[5203]226          {
[7374]227            if (inputSplits[fktPos] == (*cmdIT)->getName())
[7340]228            {
[7374]229              if (objectPointer == NULL && (*cmdIT)->executor->getType() & Executor_Objective)
230                return false;
231              else
232              {
233                (*(*cmdIT)->executor)(objectPointer, inputSplits.getSubSet(fktPos+1).join()); /// TODO CHECK IF OK
234                return true;
235              }
[7340]236            }
[5203]237          }
238        }
239      }
240    }
[7374]241    return false;
[5198]242  }
[5148]243
[7374]244  /**
245   * lets a command be described
246   * @param description the description of the Given command
247   */
248  ShellCommand* ShellCommand::describe(const std::string& description)
[7340]249  {
[7374]250    if (this == NULL)
251      return NULL;
252    else
253    {
254      this->description = description;
255      return this;
256    }
[7340]257  }
[5164]258
[7374]259  /**
[7389]260   * @brief adds an Alias to this Command
[7374]261   * @param alias the name of the Alias to set
262   * @returns itself
263   */
264  ShellCommand* ShellCommand::setAlias(const std::string& alias)
[5196]265  {
[7374]266    if (this == NULL)
267      return NULL;
[5196]268
[7374]269    if (this->alias != NULL)
270    {
271      PRINTF(2)("not more than one Alias allowed for functions (%s::%s)\n", this->getName(), this->shellClass->getName());
272    }
273    else
274    {
275      ShellCommandAlias* aliasCMD = new ShellCommandAlias(alias, this);
276      this->alias = aliasCMD;
277    }
278    return this;
[5196]279  }
[5195]280
[7374]281  /**
282   * @brief set the default values of the executor
283   * @param value0 the first default value
284   * @param value1 the second default value
285   * @param value2 the third default value
286   * @param value3 the fourth default value
287   * @param value4 the fifth default value
288   */
289  ShellCommand* ShellCommand::defaultValues(const MultiType& value0, const MultiType& value1,
290      const MultiType& value2, const MultiType& value3,
291      const MultiType& value4)
292  {
293    if (this == NULL || this->executor == NULL)
294      return NULL;
[5207]295
[7374]296    this->executor->defaultValues(value0, value1, value2, value3, value4);
[5207]297
[7374]298    return this;
[5148]299  }
300
[7374]301  /**
302   * prints out nice information about the Shells Commands
303   */
304  void ShellCommand::debug()
[5148]305  {
[7394]306    std::vector<ShellCommandClass*>::iterator classIT;
307    for (classIT = ShellCommandClass::commandClassList.begin(); classIT != ShellCommandClass::commandClassList.end(); classIT++)
[7374]308    {
309      PRINT(0)("Class:'%s' registered %d commands: \n", (*classIT)->className.c_str(), (*classIT)->commandList.size());
[5148]310
[7388]311      std::vector<ShellCommand*>::iterator cmdIT;
[7374]312      for (cmdIT = (*classIT)->commandList.begin(); cmdIT != (*classIT)->commandList.end(); cmdIT++)
313      {
314        PRINT(0)("  command:'%s' : params:%d: ", (*cmdIT)->getName(), (*cmdIT)->executor->getParamCount());
315        /// FIXME
316        /*      for (unsigned int i = 0; i< elem->paramCount; i++)
317         printf("%s ", ShellCommand::paramToString(elem->parameters[i]));*/
318        if (!(*cmdIT)->description.empty())
319          printf("- %s", (*cmdIT)->description.c_str());
320        printf("\n");
321
322      }
[5170]323    }
[5148]324  }
325
[7374]326  /**
327   * converts a Parameter to a String
328   * @param parameter the Parameter we have.
329   * @returns the Name of the Parameter at Hand
330   */
331  const char* ShellCommand::paramToString(long parameter)
332  {
333    return MultiType::MultiTypeToString((MT_Type)parameter);
334  }
335
[7389]336
[7397]337  /**
338   * @param aliasName the name of the Alias
339   * @param command the Command, to associate this alias with
340   */
[7389]341  ShellCommandAlias::ShellCommandAlias(const std::string& aliasName, ShellCommand* command)
342  {
343    this->aliasName = aliasName;
344    this->command = command;
345    ShellCommandAlias::aliasList.push_back(this);
346  };
347
348  ShellCommandAlias::~ShellCommandAlias()
349  {
350    std::vector<ShellCommandAlias*>::iterator delA = std::find(aliasList.begin(), aliasList.end(), this);
351    if (delA != aliasList.end())
352      ShellCommandAlias::aliasList.push_back(this);
353
354  }
355
356  std::vector<ShellCommandAlias*> ShellCommandAlias::aliasList;
357  /**
358  * @brief collects the Aliases registered to the ShellCommands
359  * @param stringList a List to paste the Aliases into.
360  * @returns true on success, false otherwise
361   */
362  bool ShellCommandAlias::getCommandListOfAlias(std::list<std::string>& stringList)
363  {
364    std::vector<ShellCommandAlias*>::iterator alias;
365    for (alias = ShellCommandAlias::aliasList.begin(); alias != ShellCommandAlias::aliasList.end(); alias++)
366      stringList.push_back((*alias)->getName());
367    return true;
368  }
369
370
[5148]371}
Note: See TracBrowser for help on using the repository browser.