1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License:  See top level LICENSE.txt file.
5 //
6 // Author: Garrett Potts
7 //
8 // Description:
9 //
10 // Contains class declaration for ossimConnectableObject the base class for
11 // all connectable objects.
12 //
13 //*************************************************************************
14 // $Id$
15 
16 #ifndef ossimConnectableObject_HEADER
17 #define ossimConnectableObject_HEADER 1
18 
19 #include <ossim/base/ossimConstants.h>
20 #include <ossim/base/ossimObject.h>
21 #include <ossim/base/ossimId.h>
22 #include <ossim/base/ossimListenerManager.h>
23 #include <ossim/base/ossimPropertyInterface.h>
24 #include <ossim/base/ossimRefPtr.h>
25 #include <vector>
26 
27 class ossimVisitor;
28 class ossimConnectableContainer;
29 
30 class  OSSIMDLLEXPORT  ossimConnectableObject : public ossimObject,
31                                                 public ossimListenerManager,
32                                                 public ossimPropertyInterface
33 {
34 public:
35    typedef std::vector<ossimRefPtr<ossimConnectableObject> > ConnectableObjectList;
36    enum ossimConnectableObjectDirectionType
37    {
38       CONNECTABLE_DIRECTION_NONE   = 0,
39       CONNECTABLE_DIRECTION_INPUT  = 1,
40       CONNECTABLE_DIRECTION_OUTPUT = 2
41    };
42    /**
43     * Base constructor of this object.
44     */
45    ossimConnectableObject(ossimObject* owner=0);
46    ossimConnectableObject(ossimObject* owner,
47                           ossim_int32 inputListSize,
48                           ossim_int32 outputListSize,
49                           bool inputListIsFixedFlag=true,
50                           bool outputListIsFixedFlag=true);
51 
52    virtual ~ossimConnectableObject();
53    /**
54     * All connectable objects will have id's.  This allows us to
55     * set the id of this object.
56     */
57    void setId(const ossimId& id);
58 
59    /**
60     * Will allow us to get this object's id.
61     */
62    const ossimId& getId()const;
63 
64    /**
65     * Fetches the current owner, most likely a container but not limited to one.
66     */
67    const ossimObject* getOwner() const;
68 
69    /**
70     * Permits changing the object's owner.
71     */
72    virtual void changeOwner(ossimObject* owner);
73 
74    virtual void setDescription(const ossimString& description);
75    virtual ossimString getDescription()const;
76 
77    /**
78     * will check the direction specified to see if all slots are full.
79     * If any slot is null then false is returned.
80     * If a filter requires options testing they
81     * need to override this method.  The argument can be ored together. If you
82     * want both checked then pass
83     * CONNECTABLE_DIRECTION_INPUT | CONNECTABLE_DIRECTION_OUTPUT
84     */
85    virtual bool isConnected(
86       ossimConnectableObjectDirectionType direction = CONNECTABLE_DIRECTION_INPUT)const;
87 
88 
89    /*!
90     * These methods are now deprecated.  You can achieve the same thing by
91     * using the new visitor design pattern.  If this does not achieve exactly
92     * what you want then you can derive new rules by overriding the virtual
93     * visit method in ossimVisitor
94     *
95     * <pre>
96     *    ossimIdVisitor visitor(id, false, ossimVisitor::VISIT_CHILDREN |
97     *    ossimVisitor::VISIT_INPUTS);
98     *    connectableObject->accept(visitor);
99     *    ossimRefPtr<ossimConnectableObject> object = visitor.getObject();
100     * </pre>
101     */
102    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findConnectableObject(
103                              const ossimId& id));
104 
105    /*!
106     * These methods are now deprecated.  You can achieve the same thing by
107     * using the new visitor design pattern.  If this does not achieve exactly
108     * what you want then you can derive new rules by overriding the virtual
109     * visit method in ossimVisitor
110     *
111     * <pre>
112     *    ossimTypeIdVisitor visitor(typeId, true, ossimVisitor::VISIT_CHILDREN |
113     *    ossimVisitor::VISIT_INPUTS);
114     *    connectableObject->accept(visitor);
115     *    ossimRefPtr<ossimConnectableObject> object = visitor.getObject();
116     * </pre>
117     */
118    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findObjectOfType(
119                              RTTItypeid typeId,
120                              ossimConnectableObjectDirectionType directionType,
121                              bool recurse = true));
122 
123    /*!
124     * These methods are now deprecated.  You can achieve the same thing by
125     * using the new visitor design pattern.  If this does not
126     * achieve exactly what you want then you can derive new rules by overriding
127     * the virtual visit method in ossimVisitor
128     *
129     * <pre>
130     *    ossimTypeNameVisitor visitor(typeName, true,
131     *    ossimVisitor::VISIT_CHILDREN | ossimVisitor::VISIT_INPUTS);
132     *    connectableObject->accept(visitor);
133     *    ossimRefPtr<ossimConnectableObject> object = visitor.getObject();
134     * </pre>
135     */
136    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findObjectOfType(
137                              const ossimString& obj,
138                              ossimConnectableObjectDirectionType directionType,
139                              bool recurse = true));
140 
141    /*!
142     * These methods are now deprecated.  You can achieve the same thing by
143     * using the new visitor design pattern.  If this does not
144     * achieve exactly what you want then you can derive new rules by overriding
145     * the virtual visit method in ossimVisitor
146     *
147     * <pre>
148     *    ossimTypeNameVisitor visitor(typeName, true,
149     *    ossimVisitor::VISIT_CHILDREN | ossimVisitor::VISIT_INPUTS);
150     *    connectableObject->accept(visitor);
151     *    ossimRefPtr<ossimConnectableObject> object = visitor.getObject();
152     * </pre>
153     */
154    OSSIM_DEPRECATE_METHOD(virtual ossimConnectableObject* findInputObjectOfType(
155                              const ossimString& className));
156 
157    /**
158     * Return a valid index of the input list if the passed in object
159     * is found else return -1.
160     */
161    virtual ossim_int32 findInputIndex(const ossimConnectableObject* object);
162 
163    /**
164     * Return a valid index of the input list if the passed id
165     * is found else return -1.
166     */
167    virtual ossim_int32 findInputIndex(const ossimId& id);
168 
169    /**
170     * Return a valid index of the output list if the passed in object
171     * is found else return -1.
172     */
173    virtual ossim_int32 findOutputIndex(const ossimConnectableObject* object);
174 
175    /**
176     * Return a valid index of the output list if the passed in object
177     * is found else return -1.
178     */
179    virtual ossim_int32 findOutputIndex(const ossimId& id);
180 
181    /**
182     * Should return the first available index to connect to.  The
183     * connectMyInputTo that just takes another ossimConnectableObject as input
184     * and not an index will call this method.  By default this method will find
185     * the first open slot (not null) or append o the list if it's dynamic. If
186     * the list is dynamic it calls conConnectMyInputTo(index, object) on an
187     * index = to listSize.
188     */
189    virtual ossim_int32 getMyInputIndexToConnectTo(
190       ossimConnectableObject* object)const;
191 
192 
193    /**
194     * Should return the first available index to connect to.  The
195     * connectMyOutputTo that just takes another ossimConnectableObject as input\
196     * and not an index will call this method.  By default this method will find
197     * the first open slot (not null) or append to the list if it's dynamic. If
198     * the list is dynamic it calls canConnectMyOutputTo(index, object) on an
199     * index = to listSize.
200     */
201    virtual ossim_int32 getMyOutputIndexToConnectTo(
202       ossimConnectableObject* object)const;
203 
204    /**
205     * required to be overriden by derived classes
206     */
207    virtual bool canConnectMyInputTo(
208       ossim_int32 myInputIndex, const ossimConnectableObject* object)const=0;
209 
210    /**
211     * default implementation is to allow anyone to connect to us.
212     */
213    virtual bool canConnectMyOutputTo(ossim_int32 myOutputIndex,
214                                      const ossimConnectableObject* object)const;
215 
216    /**
217     * Will disconnect the object passed in.
218     */
219    virtual void disconnect(ossimConnectableObject* object=0);
220 
221    /**
222     * Will disconnect the object passed in.
223     */
224    virtual void disconnect(const ossimId& id);
225 
226    /**
227     * Will disconnect the object at the given input index and generate
228     * a connection event.
229     */
230    virtual ossimRefPtr<ossimConnectableObject> disconnectMyInput(
231       ossim_int32 inputIndex,
232       bool disconnectOutputFlag=true,
233       bool createEventFlag = true);
234 
235   /**
236    * Finds the index of the passed in input and calls
237    * disconnectMyInput(inputIndex, disconnectOutputFlag, createEventFlag);
238    */
239    virtual void disconnectMyInput(ossimConnectableObject* input,
240                                   bool disconnectOutputFlag=true,
241                                   bool createEventFlag = true);
242    /**
243     *
244     */
245    virtual void disconnectMyInputs(
246       ConnectableObjectList& inputList,
247       bool disconnectOutputFlag=true,
248       bool createEventFlag=true);
249 
250    /**
251     * Will disconnect the object at the given output index and generate
252     * a connection event.  If there is no object at that index then no
253     * event is generated and NULL is returned.  The disconnectOutputFlag
254     * says do you want this method to disconnect the output pointer to
255     * this object.
256     */
257    virtual ossimRefPtr<ossimConnectableObject> disconnectMyOutput(
258       ossim_int32 outputIndex,
259       bool disconnectInputFlag=true,
260       bool createEventFlag = true);
261 
262    /**
263     * Will disconnect the output object.  It will get the index of
264     * the object and call disconnectMyOutput(index, disconnectOutputFlag).
265     */
266    virtual void disconnectMyOutput(ossimConnectableObject* output,
267                                    bool disconnectInputFlag=true,
268                                    bool createEventFlag=true);
269 
270    virtual void disconnectMyOutputs(
271       ConnectableObjectList& outputList,
272       bool disconnectOutputFlag=true,
273       bool createEventFlag=true);
274 
275    /**
276     * Will disconnect all of the input objects.
277     */
278    virtual void disconnectAllInputs();
279 
280    /**
281     * Will disconnect all of the output objects.
282     */
283    virtual void disconnectAllOutputs();
284 
285    /**
286     * Will try to connect this objects input to the passed in object.
287     * It will return a valid index >= 0 if successful.  Will use the
288     * getMyInputIndexToConnectTo method to implement the connection
289     */
290    virtual ossim_int32 connectMyInputTo(ossimConnectableObject* inputObject,
291                                         bool makeOutputConnection=true,
292                                         bool createEventFlag=true);
293 
294    /**
295     * Will connect the specified input to the passed in object
296     */
297    virtual ossim_int32 connectMyInputTo(ossim_int32 inputIndex,
298                                         ossimConnectableObject* inputObject,
299                                         bool makeOutputConnection=true,
300                                         bool createEventFlag=true);
301 
302    virtual bool connectMyInputTo(
303       ConnectableObjectList& inputList,
304       bool makeOutputConnection=true,
305       bool createEventFlag = true);
306 
307    /**
308     * Will try to connect this objects output to the passed in object.
309     * It will return a valid index >= 0 if successful.  It will in turn call
310     * the passed in objects connect input command if makeInputConnection
311     * is set to true.
312     *
313     * Will use the getMyOutputIndexToConnectTo to implement this method
314     */
315    virtual ossim_int32 connectMyOutputTo(ossimConnectableObject* outputObject,
316                                          bool makeInputConnection=true,
317                                          bool createEventFlag=true);
318 
319    virtual bool connectMyOutputTo(
320       ConnectableObjectList& outputList,
321       bool makeInputConnection=true,
322       bool createEventFlag=true);
323 
324    /**
325     * Will disconnect itself from all inputs and reset to the passed in
326     * input list.  It will return true if all objects were successfully
327     * added.
328     */
329    virtual bool connectInputList(
330       ConnectableObjectList& inputList);
331 
332    /**
333     * Will disconnect itself from all outputs and reset to the passed in
334     * output list.  It will return true if all objects were successfully
335     * added.
336     */
337    virtual bool connectOutputList(
338       ConnectableObjectList& outputList);
339 
340    /**
341     * Returns the number of input objects.
342     */
343    virtual ossim_uint32 getNumberOfInputs()const;
344 
345    /**
346     * Return the number of output objects
347     */
348    virtual ossim_uint32 getNumberOfOutputs()const;
349 
350    /**
351     * returns the object at the specified index.
352     * if the index is not valid then NULL is
353     * returned
354     */
355    ossimConnectableObject* getInput(ossim_uint32 index=0);
356 
357    /**
358     * returns the object at the specified index.
359     * if the index is not valid then NULL is
360     * returned
361     */
362    const ossimConnectableObject* getInput(ossim_uint32 index=0)const;
363 
364    /**
365     * returns the object at the specified index.
366     * if the index is not valid then NULL is
367     * returned
368     */
369    ossimConnectableObject* getOutput(ossim_uint32 index=0);
370 
371    /**
372     * returns the object at the specified index.
373     * if the index is not valid then NULL is
374     * returned
375     */
376    const ossimConnectableObject* getOutput(ossim_uint32 index=0)const;
377 
378    /**
379     * Will set the number of inputs.  This will expand the list if the number
380     * of inputs is larger than the current number of inputs.  Will shrink
381     * the list if the current number of inputs is larger than the passed in
382     * inputs.
383     */
384    virtual void setNumberOfInputs(ossim_int32 numberOfInputs);
385 
386    virtual bool getInputListIsFixedFlag()const;
387 
388    virtual bool getOutputListIsFixedFlag()const;
389 
390    /**
391     * Will set the number of outputs.  This will expand the list if the
392     * number of outputs is larger than the current number of outputs.
393     * Will shrink the list if the current number of outputs is larger than
394     * the passed in outputs.
395     */
396    virtual void setNumberOfOutputs(ossim_int32 numberOfInputs);
397 
398    const ConnectableObjectList& getInputList()const;
399 
400    const ConnectableObjectList& getOutputList()const;
401 
402    ConnectableObjectList& getInputList();
403 
404    ConnectableObjectList& getOutputList();
405 
406    /*!
407     * These methods are now deprecated.  You can achieve the same thing by
408     * using the new visitor design pattern.  If this does not achieve exactly
409     * what you want then you can derive new rules by overriding the virtual
410     * visit method in ossimVisitor
411     *
412     * <pre>
413     *    ossimTypeNameVisitor visitor("<put type name here>",
414     *    false, ossimVisitor::VISIT_CHILDREN);
415     *    connectableObject->accept(visitor);
416     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
417     * </pre>
418     */
419     OSSIM_DEPRECATE_METHOD(virtual void findAllObjectsOfType(
420                               ConnectableObjectList& result,
421                               const RTTItypeid& typeInfo, bool recurse=true) );
422 
423    /*!
424     * These methods are now deprecated.  You can achieve the same thing by
425     * using the new visitor design pattern.  If this does not achieve exactly
426     * what you want then you can derive new rules by overriding the virtual
427     * visit method in ossimVisitor
428     *
429     * <pre>
430     *    ossimTypeNameVisitor visitor("<put type name here>", false,
431     *    ossimVisitor::VISIT_CHILDREN);
432     *    connectableObject->accept(visitor);
433     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
434     * </pre>
435     */
436    OSSIM_DEPRECATE_METHOD(virtual void findAllObjectsOfType(
437                              ConnectableObjectList& result,
438                              const ossimString& className,
439                              bool recurse=true));
440 
441 #if 0 /* Deprecated code. Left here until thoroughly debugged. (drb) */
442    /*!
443     * These methods are now deprecated.  You can achieve the same thing by
444     * using the new visitor design pattern.  If this does not
445     * achieve exactly what you want then you can derive new rules by overriding
446     * the virtual visit method in ossimVisitor
447     *
448     * <pre>
449     *    ossimTypeIdVisitor visitor(<put type id here>, false,
450     *    ossimVisitor::VISIT_CHILDREN | ossimVisitor::VISIT_INPUTS);
451     *    connectableObject->accept(visitor);
452     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
453     * </pre>
454     */
455    OSSIM_DEPRECATE_METHOD(virtual void findAllInputsOfType(
456       ConnectableObjectList& result,
457       const RTTItypeid& typeInfo,
458       bool propagateToInputs=true,
459       bool recurseChildren=false));
460 
461    /*!
462     * These methods are now deprecated.  You can achieve the same thing by
463     * using the new visitor design pattern.  If this does not
464     * achieve exactly what you want then you can derive new rules by overriding
465     * the virtual visit method in ossimVisitor
466     *
467     * <pre>
468     *    ossimTypeNameVisitor visitor("<put type name here>",
469     *    false, ossimVisitor::VISIT_CHILDREN | ossimVisitor::VISIT_INPUTS);
470     *    connectableObject->accept(visitor);
471     *    ossimCollectionVisitor::List& collection = visitor.getObjects();
472     * </pre>
473     */
474 
475    OSSIM_DEPRECATE_METHOD(virtual void findAllInputsOfType(
476                              ConnectableObjectList& result,
477                              const ossimString& className,
478                              bool propagateToInputs=true,
479                              bool recurseChildren=false));
480 #endif  /* deprecated code. (drb) */
481 
482    virtual void propagateEventToOutputs(ossimEvent& event);
483    virtual void propagateEventToInputs(ossimEvent& event);
484 
485    /* ------------------- PROPERTY INTERFACE -------------------- */
486    virtual void setProperty(ossimRefPtr<ossimProperty> property);
487    virtual void setProperty(const ossimString& name, const ossimString& value);
488    virtual ossimRefPtr<ossimProperty> getProperty(const ossimString& name)const;
489    virtual void getPropertyNames(std::vector<ossimString>& propertyNames)const;
490    /* ------------------ PROPERTY INTERFACE END ------------------- */
491 
492 
493    virtual bool loadState(const ossimKeywordlist& kwl,
494                           const char* prefix = 0);
495 
496    virtual bool saveState(ossimKeywordlist& kwl,
497                           const char* prefix = 0)const;
498 
499    /**
500     * Save the state of all inputs to a keyword list.  This will do a
501     * recursive call through all inputs and save their state to a
502     * keyword list.
503     *
504     * @param kwl Keyword list to save state to.
505     *
506     * @param saveThisStateFlag If the true the state of this object will be
507     * saved as well as all inputs. Default = true.
508     *
509     * @param  objectIndex Index to be used for prefix.  So if
510     * objectIndex = 1, the first object will have a prefix of: "object1."
511     * Default = 1.
512     *
513     * @param prefix Prefix to tack onto keyword.  If prefix = "myChain." and
514     * objectIndex = 1, then the first keyword would be
515     * "myChain.object1.some_keyword".
516     *
517     * @return Returns the next object index.  This is the last index used
518     * plus one.  Used internally to keep track of index to use for prefix.
519     */
520    virtual ossim_uint32 saveStateOfAllInputs(ossimKeywordlist& kwl,
521                                              bool saveThisStateFlag=true,
522                                              ossim_uint32 objectIndex=1,
523                                              const char* prefix=0) const;
524 
525    /**
526     * Inserts this object and all of its children and inputs into the container
527     * provided.
528     * @return Returns TRUE if successful.
529     */
530    virtual bool fillContainer(ossimConnectableContainer& container);
531 
532    /**
533     * Moves the input connection matching id up one in the connection list.
534     * @param id The id to move.
535     * @return true if action was performed, false if not.
536     */
537    bool moveInputUp(const ossimId& id);
538 
539    /**
540     * Moves the input connection matching id down one in the connection list.
541     * @param id The id to move.
542     * @return true if action was performed, false if not.
543     */
544    bool moveInputDown(const ossimId& id);
545 
546    /**
547     * Moves the input connection matching id to the top of the connection list.
548     * @param id The id to move.
549     * @return true if action was performed, false if not.
550     */
551    bool moveInputToTop(const ossimId& id);
552 
553    /**
554     * Moves the input connection matching id to the bottom of the connection
555     * list.
556     * @param id The id to move.
557     * @return true if action was performed, false if not.
558     */
559    bool moveInputToBottom(const ossimId& id);
560 
561    /**
562     * We will add a visitor interface for all connectable objects.
563     */
564    virtual void accept(ossimVisitor& visitor);
565 
566 protected:
567 
568    ossimConnectableObject* findObjectOfType(
569       ConnectableObjectList* connectableList,
570       ossimVisitor& visitor );
571 
572    ossimId      theId;
573    ossimString  theDescription;
574    ossimObject* theOwner;
575 
576    /**
577     * Indicates whether the theInputObjectList is fixed
578     */
579    bool theInputListIsFixedFlag;
580 
581    /**
582     * Indicates whether the theOutputObjectList is fixed
583     */
584    bool theOutputListIsFixedFlag;
585 
586    /**
587     * Holds a list of input objects.
588     */
589    ConnectableObjectList theInputObjectList;
590 
591    /**
592     * Holds a list of output objects.
593     */
594    ConnectableObjectList theOutputObjectList;
595 
596 private:
597 TYPE_DATA
598 };
599 
600 #endif /* #ifndef ossimConnectableObject_HEADER */
601