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, 18 years ago

orxonox/trunk: SubString more functionality

File size: 11.9 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#include "class_list.h"
24
25#include "key_names.h"
26
27namespace OrxShell
28{
29  SHELL_COMMAND_STATIC(debug, ShellCommand, ShellCommand::debug);
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, 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);
43
44    // copy the executor:
45    this->executor = executor.clone();
46    this->executor->setName(commandName);
47
48    this->alias = NULL;
49
50    //  this->classID = classID;
51    this->shellClass = ShellCommandClass::getCommandClass(className);
52    assert (this->shellClass != NULL);
53    this->shellClass->commandList.push_back(this);
54  }
55
56  /**
57   * @brief deconstructs a ShellCommand
58   */
59  ShellCommand::~ShellCommand()
60  {
61    if (this->alias != NULL)
62      delete this->alias;
63    delete this->executor;
64  }
65
66  /**
67   * @brief registers a new ShellCommand
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);
75
76  }
77
78  /**
79   * @brief unregister an existing commandName
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();
88
89     const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
90
91     if (checkClass != NULL)
92      {
93        std::list<ShellCommand*>::iterator elem;
94        for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
95        {
96          if (!strcmp(commandName, (*elem)->getName()))
97          {
98            delete (*elem);
99            checkClass->commandList.remove(*elem);
100            break;
101          }
102        }
103
104        if (checkClass->commandList->size() == 0)
105        {
106          ShellCommandClass::commandClassList->remove(checkClass);
107          delete checkClass;
108        }
109      }*/
110  }
111
112  /**
113   * @brief checks if a command has already been registered.
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)
122  {
123    const ShellCommandClass* checkClass = ShellCommandClass::isRegistered(className);
124    if (checkClass != NULL)
125    {
126      std::vector<ShellCommand*>::const_iterator elem;
127      for (elem = checkClass->commandList.begin(); elem != checkClass->commandList.end(); elem++)
128      {
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        }
134      }
135      return false;
136    }
137    else
138      return false;
139  }
140
141
142  /**
143   * @brief executes commands
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);
157
158
159    // if we do not have any input return
160    if (inputSplits.empty())
161      return false;
162
163    // if we only have one input (!MUST BE AN ALIAS)
164    if (inputSplits.size() >= 1)
165    {
166      // CHECK FOR ALIAS
167      std::vector<ShellCommandAlias*>::const_iterator alias;
168      for (alias = ShellCommandAlias::getAliases().begin(); alias != ShellCommandAlias::getAliases().end(); alias++ )
169      {
170        if (inputSplits.getString(0) == (*alias)->getName() && (*alias)->getCommand() != NULL &&
171            (*alias)->getCommand()->shellClass != NULL )
172        {
173          objectList = ClassList::getList((*alias)->getCommand()->shellClass->getName());
174          if (objectList != NULL)
175          {
176            (*(*alias)->getCommand()->executor)(objectList->front(), inputSplits.getSubSet(1).join());
177            return true;
178          }
179          /// TODO CHECK FOR STATIC functions.
180        }
181      }
182
183      // looking for a Matching Class
184      std::vector<ShellCommandClass*>::iterator commandClassIT;
185      for (commandClassIT = ShellCommandClass::commandClassList.begin(); commandClassIT != ShellCommandClass::commandClassList.end(); commandClassIT++)
186      {
187        if ((*commandClassIT)->getName() && inputSplits[0] == (*commandClassIT)->getName())
188        {
189          //elemCL->getName();
190          classID = ClassList::StringToID((*commandClassIT)->getName());
191          commandClass = (*commandClassIT);
192          objectList = ClassList::getList((ClassID)classID);
193          break;
194        }
195      }
196
197      // Second Agument. (either Object, or Function)
198      if (commandClass != NULL && inputSplits.size() >= 2)
199      {
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)
203        {
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++)
207          {
208            if ((*object)->getName() != NULL && inputSplits[1] == (*object)->getName())
209            {
210              objectPointer = (*object);
211              fktPos = 2;
212              break;
213            }
214          }
215
216          // if we did not find an Object with matching name, take the first.
217          if (objectPointer == NULL)
218            objectPointer = objectList->front();
219        }
220
221        // match a function.
222        if (commandClass != NULL && (fktPos == 1 || (fktPos == 2 && inputSplits.size() >= 3)))
223        {
224          std::vector<ShellCommand*>::iterator cmdIT;
225          for (cmdIT = commandClass->commandList.begin(); cmdIT != commandClass->commandList.end(); cmdIT++)
226          {
227            if (inputSplits[fktPos] == (*cmdIT)->getName())
228            {
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              }
236            }
237          }
238        }
239      }
240    }
241    return false;
242  }
243
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)
249  {
250    if (this == NULL)
251      return NULL;
252    else
253    {
254      this->description = description;
255      return this;
256    }
257  }
258
259  /**
260   * @brief adds an Alias to this Command
261   * @param alias the name of the Alias to set
262   * @returns itself
263   */
264  ShellCommand* ShellCommand::setAlias(const std::string& alias)
265  {
266    if (this == NULL)
267      return NULL;
268
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;
279  }
280
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;
295
296    this->executor->defaultValues(value0, value1, value2, value3, value4);
297
298    return this;
299  }
300
301  /**
302   * prints out nice information about the Shells Commands
303   */
304  void ShellCommand::debug()
305  {
306    std::vector<ShellCommandClass*>::iterator classIT;
307    for (classIT = ShellCommandClass::commandClassList.begin(); classIT != ShellCommandClass::commandClassList.end(); classIT++)
308    {
309      PRINT(0)("Class:'%s' registered %d commands: \n", (*classIT)->className.c_str(), (*classIT)->commandList.size());
310
311      std::vector<ShellCommand*>::iterator cmdIT;
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      }
323    }
324  }
325
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
336
337  /**
338   * @param aliasName the name of the Alias
339   * @param command the Command, to associate this alias with
340   */
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
371}
Note: See TracBrowser for help on using the repository browser.