• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

kig

  • sources
  • kde-4.12
  • kdeedu
  • kig
  • misc
object_hierarchy.cc
Go to the documentation of this file.
1 // Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
2 
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License
5 // as published by the Free Software Foundation; either version 2
6 // of the License, or (at your option) any later version.
7 
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 // 02110-1301, USA.
17 
18 #include "object_hierarchy.h"
19 
20 #include "../objects/object_holder.h"
21 #include "../objects/other_type.h"
22 #include "../objects/object_imp.h"
23 #include "../objects/object_imp_factory.h"
24 #include "../objects/object_type_factory.h"
25 #include "../objects/bogus_imp.h"
26 #include "../objects/transform_types.h"
27 #include "../objects/object_type.h"
28 
29 #include <kglobal.h>
30 #include <qdom.h>
31 
32 class ObjectHierarchy::Node
33 {
34 public:
35  enum { ID_PushStack, ID_ApplyType, ID_FetchProp };
36  virtual int id() const = 0;
37 
38  virtual ~Node();
39  virtual Node* copy() const = 0;
40 
41  virtual void apply( std::vector<const ObjectImp*>& stack, int loc,
42  const KigDocument& ) const = 0;
43 
44  virtual void apply( std::vector<ObjectCalcer*>& stack, int loc ) const = 0;
45 
46  // this function is used to check whether the final objects depend
47  // on the given objects. The dependsstack contains a set of
48  // booleans telling which parts of the hierarchy certainly depend on
49  // the given objects. In this function, the node should check
50  // whether any of its parents have true set, and if so, set its own
51  // value to true.
52  virtual void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const = 0;
53  // this function is used to check whether the given objects are all
54  // used by one or more of the final objects. The usedstack contains
55  // a set of booleans telling which parts of the hierarchy are
56  // certainly ancestors of the final objects. In this function, the
57  // node should set all of its parents' booleans to true.
58  virtual void checkArgumentsUsed( std::vector<bool>& usedstack ) const = 0;
59 };
60 
61 ObjectHierarchy::Node::~Node()
62 {
63 }
64 
65 class PushStackNode
66  : public ObjectHierarchy::Node
67 {
68  ObjectImp* mimp;
69 public:
70  PushStackNode( ObjectImp* imp ) : mimp( imp ) {}
71  ~PushStackNode();
72 
73  const ObjectImp* imp() const { return mimp; }
74 
75  int id() const;
76  Node* copy() const;
77  void apply( std::vector<const ObjectImp*>& stack,
78  int loc, const KigDocument& ) const;
79  void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
80 
81  void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
82  void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
83 };
84 
85 void PushStackNode::checkArgumentsUsed( std::vector<bool>& ) const
86 {
87 }
88 
89 void PushStackNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
90 {
91  stack[loc] = new ObjectConstCalcer( mimp->copy() );
92 }
93 
94 void PushStackNode::checkDependsOnGiven( std::vector<bool>&, int ) const {
95  // pushstacknode depends on nothing..
96  return;
97 }
98 
99 int PushStackNode::id() const { return ID_PushStack; }
100 
101 PushStackNode::~PushStackNode()
102 {
103  delete mimp;
104 }
105 
106 ObjectHierarchy::Node* PushStackNode::copy() const
107 {
108  return new PushStackNode( mimp->copy() );
109 }
110 
111 void PushStackNode::apply( std::vector<const ObjectImp*>& stack,
112  int loc, const KigDocument& ) const
113 {
114  stack[loc] = mimp->copy();
115 }
116 
117 class ApplyTypeNode
118  : public ObjectHierarchy::Node
119 {
120  const ObjectType* mtype;
121  std::vector<int> mparents;
122 public:
123  ApplyTypeNode( const ObjectType* type, const std::vector<int>& parents )
124  : mtype( type ), mparents( parents ) {}
125  ~ApplyTypeNode();
126  Node* copy() const;
127 
128  const ObjectType* type() const { return mtype; }
129  const std::vector<int>& parents() const { return mparents; }
130 
131  int id() const;
132  void apply( std::vector<const ObjectImp*>& stack,
133  int loc, const KigDocument& ) const;
134  void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
135 
136  void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
137  void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
138 };
139 
140 int ApplyTypeNode::id() const { return ID_ApplyType; }
141 
142 void ApplyTypeNode::checkArgumentsUsed( std::vector<bool>& usedstack ) const
143 {
144  for ( uint i = 0; i < mparents.size(); ++i )
145  {
146  usedstack[mparents[i]] = true;
147  }
148 }
149 
150 void ApplyTypeNode::checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const
151 {
152  bool result = false;
153  for ( uint i = 0; i < mparents.size(); ++i )
154  if ( dependsstack[mparents[i]] == true ) result = true;
155  dependsstack[loc] = result;
156 }
157 
158 ApplyTypeNode::~ApplyTypeNode()
159 {
160 }
161 
162 ObjectHierarchy::Node* ApplyTypeNode::copy() const
163 {
164  return new ApplyTypeNode( mtype, mparents );
165 }
166 
167 void ApplyTypeNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
168 {
169  std::vector<ObjectCalcer*> parents;
170  for ( uint i = 0; i < mparents.size(); ++i )
171  parents.push_back( stack[ mparents[i] ] );
172  stack[loc] = new ObjectTypeCalcer( mtype, parents );
173 }
174 
175 void ApplyTypeNode::apply( std::vector<const ObjectImp*>& stack,
176  int loc, const KigDocument& doc ) const
177 {
178  Args args;
179  for ( uint i = 0; i < mparents.size(); ++i )
180  args.push_back( stack[mparents[i]] );
181  args = mtype->sortArgs( args );
182  stack[loc] = mtype->calc( args, doc );
183 }
184 
185 class FetchPropertyNode
186  : public ObjectHierarchy::Node
187 {
188  mutable int mpropgid;
189  int mparent;
190  const QByteArray mname;
191 public:
192  // propgid is a cache of the global id of property "name",
193  // just as it is in PropertyObject. We
194  // don't want to ever save this value, since we cannot guarantee it
195  // remains consistent if we add properties some place..
196  FetchPropertyNode( const int parent, const QByteArray& name, const int propgid = -1 )
197  : mpropgid( propgid ), mparent( parent ), mname( name ) {}
198  ~FetchPropertyNode();
199  Node* copy() const;
200 
201  void checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const;
202  void checkArgumentsUsed( std::vector<bool>& usedstack ) const;
203  int parent() const { return mparent; }
204  const QByteArray& propinternalname() const { return mname; }
205 
206  int id() const;
207  void apply( std::vector<const ObjectImp*>& stack,
208  int loc, const KigDocument& ) const;
209  void apply( std::vector<ObjectCalcer*>& stack, int loc ) const;
210 };
211 
212 FetchPropertyNode::~FetchPropertyNode()
213 {
214 }
215 
216 void FetchPropertyNode::checkArgumentsUsed( std::vector<bool>& usedstack ) const
217 {
218  usedstack[mparent] = true;
219 }
220 
221 void FetchPropertyNode::checkDependsOnGiven( std::vector<bool>& dependsstack, int loc ) const
222 {
223  dependsstack[loc] = dependsstack[mparent];
224 }
225 
226 ObjectHierarchy::Node* FetchPropertyNode::copy() const
227 {
228  return new FetchPropertyNode( mparent, mname, mpropgid );
229 }
230 
231 int FetchPropertyNode::id() const
232 {
233  return ID_FetchProp;
234 }
235 
236 void FetchPropertyNode::apply( std::vector<const ObjectImp*>& stack,
237  int loc, const KigDocument& d ) const
238 {
239  assert( stack[mparent] );
240  if ( mpropgid == -1 ) mpropgid = stack[mparent]->getPropGid( mname );
241  if ( mpropgid != -1 )
242  stack[loc] = stack[mparent]->property(
243  stack[mparent]->getPropLid( mpropgid ), d );
244  else
245  stack[loc] = new InvalidImp();
246 }
247 
248 void FetchPropertyNode::apply( std::vector<ObjectCalcer*>& stack, int loc ) const
249 {
250  if ( mpropgid == -1 )
251  mpropgid = stack[mparent]->imp()->getPropGid( mname );
252  assert( mpropgid != -1 );
253  stack[loc] = new ObjectPropertyCalcer( stack[mparent], mpropgid, false );
254 }
255 
256 std::vector<ObjectImp*> ObjectHierarchy::calc( const Args& a, const KigDocument& doc ) const
257 {
258  assert( a.size() == mnumberofargs );
259  for ( uint i = 0; i < a.size(); ++i )
260  assert( a[i]->inherits( margrequirements[i] ) );
261 
262  std::vector<const ObjectImp*> stack;
263  stack.resize( mnodes.size() + mnumberofargs, 0 );
264  std::copy( a.begin(), a.end(), stack.begin() );
265  for( uint i = 0; i < mnodes.size(); ++i )
266  {
267  mnodes[i]->apply( stack, mnumberofargs + i, doc );
268  };
269  for ( uint i = mnumberofargs; i < stack.size() - mnumberofresults; ++i )
270  delete stack[i];
271  if ( stack.size() < mnumberofargs + mnumberofresults )
272  {
273  std::vector<ObjectImp*> ret;
274  ret.push_back( new InvalidImp );
275  return ret;
276  }
277  else
278  {
279  std::vector<ObjectImp*> ret;
280  for ( uint i = stack.size() - mnumberofresults; i < stack.size(); ++i )
281  ret.push_back( const_cast<ObjectImp*>( stack[i] ) );
282  return ret;
283  };
284 }
285 
286 int ObjectHierarchy::visit( const ObjectCalcer* o, std::map<const ObjectCalcer*, int>& seenmap,
287  bool needed, bool neededatend )
288 {
289  using namespace std;
290 
291  std::map<const ObjectCalcer*, int>::iterator smi = seenmap.find( o );
292  if ( smi != seenmap.end() )
293  {
294  if ( neededatend )
295  {
296  // neededatend means that this object is one of the resultant
297  // objects. Therefore, its node has to appear at the end,
298  // because that's where we expect it.. We therefore copy it
299  // there using CopyObjectType..
300  int ret = mnumberofargs + mnodes.size();
301  std::vector<int> parents;
302  parents.push_back( smi->second );
303  mnodes.push_back( new ApplyTypeNode( CopyObjectType::instance(), parents ) );
304  return ret;
305  }
306  else return smi->second;
307  }
308 
309  std::vector<ObjectCalcer*> p( o->parents() );
310  // we check if o descends from the given objects..
311  bool descendsfromgiven = false;
312  std::vector<int> parents;
313  parents.resize( p.size(), -1 );
314  for ( uint i = 0; i < p.size(); ++i )
315  {
316  int v = visit( p[i], seenmap, false );
317  parents[i] = v;
318  descendsfromgiven |= (v != -1);
319  };
320 
321  if ( ! descendsfromgiven && ! ( needed && o->imp()->isCache() ) )
322  {
323  if ( needed )
324  {
325  assert( ! o->imp()->isCache() );
326  // o is an object that does not depend on the given objects, but
327  // is needed by other objects, so we just have to just save its
328  // current value here.
329  Node* node = new PushStackNode( o->imp()->copy() );
330  mnodes.push_back( node );
331  int ret = mnodes.size() + mnumberofargs - 1;
332  seenmap[o] = ret;
333  return ret;
334  }
335  else
336  return -1;
337  };
338 
339  return storeObject( o, p, parents, seenmap );
340 }
341 
342 ObjectHierarchy::~ObjectHierarchy()
343 {
344  for ( uint i = 0; i < mnodes.size(); ++i ) delete mnodes[i];
345 }
346 
347 ObjectHierarchy::ObjectHierarchy( const ObjectHierarchy& h )
348  : mnumberofargs( h.mnumberofargs ), mnumberofresults( h.mnumberofresults ),
349  msaveinputtags( h.msaveinputtags ),
350  margrequirements( h.margrequirements ), musetexts( h.musetexts ),
351  mselectstatements( h.mselectstatements )
352 {
353  mnodes.reserve( h.mnodes.size() );
354  for ( uint i = 0; i < h.mnodes.size(); ++i )
355  mnodes.push_back( h.mnodes[i]->copy() );
356 }
357 
358 ObjectHierarchy ObjectHierarchy::withFixedArgs( const Args& a ) const
359 {
360  assert( a.size() <= mnumberofargs );
361  ObjectHierarchy ret( *this );
362 
363  ret.mnumberofargs -= a.size();
364  ret.margrequirements.resize( ret.mnumberofargs );
365 
366  std::vector<Node*> newnodes( mnodes.size() + a.size() );
367  std::vector<Node*>::iterator newnodesiter = newnodes.begin();
368  for ( uint i = 0; i < a.size(); ++i )
369  {
370  assert( ! a[i]->isCache() );
371  *newnodesiter++ = new PushStackNode( a[i]->copy() );
372  };
373  std::copy( ret.mnodes.begin(), ret.mnodes.end(), newnodesiter );
374  ret.mnodes = newnodes;
375 
376  return ret;
377 }
378 
379 void ObjectHierarchy::init( const std::vector<ObjectCalcer*>& from, const std::vector<ObjectCalcer*>& to )
380 {
381  msaveinputtags = false;
382  mnumberofargs = from.size();
383  mnumberofresults = to.size();
384  margrequirements.resize( from.size(), ObjectImp::stype() );
385  musetexts.resize( margrequirements.size(), "" );
386  std::map<const ObjectCalcer*, int> seenmap;
387  for ( uint i = 0; i < from.size(); ++i )
388  seenmap[from[i]] = i;
389  for ( std::vector<ObjectCalcer*>::const_iterator i = to.begin(); i != to.end(); ++i )
390  {
391  std::vector<ObjectCalcer*> parents = (*i)->parents();
392  for ( std::vector<ObjectCalcer*>::const_iterator j = parents.begin();
393  j != parents.end(); ++j )
394  visit( *j, seenmap, true );
395  }
396  for ( std::vector<ObjectCalcer*>::const_iterator i = to.begin(); i != to.end(); ++i )
397  visit( *i, seenmap, true, true );
398 
399  mselectstatements.resize( margrequirements.size(), "" );
400 }
401 
402 ObjectHierarchy::ObjectHierarchy( const std::vector<ObjectCalcer*>& from, const ObjectCalcer* to )
403 {
404  std::vector<ObjectCalcer*> tov;
405  tov.push_back( const_cast<ObjectCalcer*>( to ) );
406  init( from, tov );
407 }
408 
409 ObjectHierarchy::ObjectHierarchy( const std::vector<ObjectCalcer*>& from, const std::vector<ObjectCalcer*>& to )
410 {
411  init( from, to );
412 }
413 
414 void ObjectHierarchy::serialize( QDomElement& parent, QDomDocument& doc ) const
415 {
416  int id = 1;
417  for ( uint i = 0; i < mnumberofargs; ++i )
418  {
419  QDomElement e = doc.createElement( "input" );
420  e.setAttribute( "id", id++ );
421  e.setAttribute( "requirement", margrequirements[i]->internalName() );
422  // we don't save these atm, since the user can't define them.
423  // we only load them from builtin macro's.
424  if ( msaveinputtags )
425  {
426  QDomElement ut = doc.createElement( "UseText" );
427  ut.appendChild( doc.createTextNode( QString::fromLatin1(musetexts[i].c_str() ) ) );
428  e.appendChild( ut );
429  QDomElement ss = doc.createElement( "SelectStatement" );
430  ss.appendChild( doc.createTextNode( QString::fromLatin1(mselectstatements[i].c_str() ) ) );
431  e.appendChild( ss );
432  }
433  parent.appendChild( e );
434  }
435 
436  for ( uint i = 0; i < mnodes.size(); ++i )
437  {
438  bool result = mnodes.size() - ( id - mnumberofargs - 1 ) <= mnumberofresults;
439  QDomElement e = doc.createElement( result ? "result" : "intermediate" );
440  e.setAttribute( "id", id++ );
441 
442  if ( mnodes[i]->id() == Node::ID_ApplyType )
443  {
444  const ApplyTypeNode* node = static_cast<const ApplyTypeNode*>( mnodes[i] );
445  e.setAttribute( "action", "calc" );
446  e.setAttribute( "type", QString::fromLatin1( node->type()->fullName() ) );
447  for ( uint i = 0; i < node->parents().size(); ++i )
448  {
449  int parent = node->parents()[i] + 1;
450  QDomElement arge = doc.createElement( "arg" );
451  arge.appendChild( doc.createTextNode( QString::number( parent ) ) );
452  e.appendChild( arge );
453  };
454  }
455  else if ( mnodes[i]->id() == Node::ID_FetchProp )
456  {
457  const FetchPropertyNode* node = static_cast<const FetchPropertyNode*>( mnodes[i] );
458  e.setAttribute( "action", "fetch-property" );
459  e.setAttribute( "property", QString( node->propinternalname() ) );
460  QDomElement arge = doc.createElement( "arg" );
461  arge.appendChild( doc.createTextNode( QString::number( node->parent() + 1 ) ) );
462  e.appendChild( arge );
463  }
464  else
465  {
466  assert( mnodes[i]->id() == ObjectHierarchy::Node::ID_PushStack );
467  const PushStackNode* node = static_cast<const PushStackNode*>( mnodes[i] );
468  e.setAttribute( "action", "push" );
469  QString type = ObjectImpFactory::instance()->serialize( *node->imp(), e, doc );
470  e.setAttribute( "type", type );
471  };
472 
473  parent.appendChild( e );
474  };
475 }
476 
477 ObjectHierarchy::ObjectHierarchy()
478  : mnumberofargs( 0 ), mnumberofresults( 0 ), msaveinputtags( false )
479 {
480 }
481 
482 ObjectHierarchy* ObjectHierarchy::buildSafeObjectHierarchy( const QDomElement& parent, QString& error )
483 {
484 #define KIG_GENERIC_PARSE_ERROR \
485  { \
486  error = i18n( "An error was encountered at line %1 in file %2.", \
487  __LINE__, __FILE__ ); \
488  return 0; \
489  }
490 
491  ObjectHierarchy* obhi = new ObjectHierarchy();
492 
493  bool ok = true;
494  QString tmp;
495  QDomElement e = parent.firstChild().toElement();
496  for (; !e.isNull(); e = e.nextSibling().toElement() )
497  {
498  if ( e.tagName() != "input" ) break;
499 
500  tmp = e.attribute( "id" );
501  uint id = tmp.toInt( &ok );
502  if ( !ok ) KIG_GENERIC_PARSE_ERROR;
503 
504  obhi->mnumberofargs = qMax( id, obhi->mnumberofargs );
505 
506  tmp = e.attribute( "requirement" );
507  const ObjectImpType* req = ObjectImpType::typeFromInternalName( tmp.toLatin1() );
508  if ( req == 0 ) req = ObjectImp::stype(); // sucks, i know..
509  obhi->margrequirements.resize( obhi->mnumberofargs, ObjectImp::stype() );
510  obhi->musetexts.resize( obhi->mnumberofargs, "" );
511  obhi->mselectstatements.resize( obhi->mnumberofargs, "" );
512  obhi->margrequirements[id - 1] = req;
513  obhi->musetexts[id - 1] = req->selectStatement();
514  QDomElement esub = e.firstChild().toElement();
515  for ( ; !esub.isNull(); esub = esub.nextSibling().toElement() )
516  {
517  if ( esub.tagName() == "UseText" )
518  {
519  obhi->msaveinputtags = true;
520  obhi->musetexts[id - 1] = esub.text().toLatin1().data();
521  }
522  else if ( esub.tagName() == "SelectStatement" )
523  {
524  obhi->msaveinputtags = true;
525  obhi->mselectstatements[id - 1] = esub.text().toLatin1().data();
526  }
527  else
528  {
529  // broken file ? ignore...
530  }
531  }
532  }
533  for (; !e.isNull(); e = e.nextSibling().toElement() )
534  {
535  bool result = e.tagName() == "result";
536  if ( result ) ++obhi->mnumberofresults;
537 
538  tmp = e.attribute( "id" );
539  int id = tmp.toInt( &ok );
540  if ( !ok ) KIG_GENERIC_PARSE_ERROR;
541 
542  tmp = e.attribute( "action" );
543  Node* newnode = 0;
544  if ( tmp == "calc" )
545  {
546  // ApplyTypeNode
547  QByteArray typen = e.attribute( "type" ).toLatin1();
548  const ObjectType* type = ObjectTypeFactory::instance()->find( typen );
549  if ( ! type )
550  {
551  error = i18n( "This Kig file uses an object of type \"%1\", "
552  "which this Kig version does not support. "
553  "Perhaps you have compiled Kig without support "
554  "for this object type, "
555  "or perhaps you are using an older Kig version.", QString( typen ) );
556  return 0;
557  }
558 
559  std::vector<int> parents;
560  for ( QDomNode p = e.firstChild(); !p.isNull(); p = p.nextSibling() )
561  {
562  QDomElement q = p.toElement();
563  if ( q.isNull() ) KIG_GENERIC_PARSE_ERROR; // see above
564  if ( q.tagName() != "arg" ) KIG_GENERIC_PARSE_ERROR;
565  int pid = q.text().toInt(&ok );
566  if ( !ok ) KIG_GENERIC_PARSE_ERROR;
567  parents.push_back( pid - 1 );
568  };
569  newnode = new ApplyTypeNode( type, parents );
570  }
571  else if ( tmp == "fetch-property" )
572  {
573  // FetchPropertyNode
574  QByteArray propname = e.attribute( "property" ).toLatin1();
575  QDomElement arge = e.firstChild().toElement();
576  int parent = arge.text().toInt( &ok );
577  if ( !ok ) KIG_GENERIC_PARSE_ERROR;
578  newnode = new FetchPropertyNode( parent - 1, propname );
579  }
580  else
581  {
582  // PushStackNode
583  if ( e.attribute( "action" ) != "push" ) KIG_GENERIC_PARSE_ERROR;
584  QString typen = e.attribute( "type" );
585  if ( typen.isNull() ) KIG_GENERIC_PARSE_ERROR;
586  ObjectImp* imp = ObjectImpFactory::instance()->deserialize( typen, e, error );
587  if ( ( ! imp ) && !error.isEmpty() ) return 0;
588  newnode = new PushStackNode( imp );
589  };
590  obhi->mnodes.resize( qMax( size_t(id - obhi->mnumberofargs), obhi->mnodes.size() ) );
591  obhi->mnodes[id - obhi->mnumberofargs - 1] = newnode;
592  };
593 
594  // if we are here, all went fine
595  return obhi;
596 }
597 
598 ArgsParser ObjectHierarchy::argParser() const
599 {
600  std::vector<ArgsParser::spec> specs;
601  for ( uint i = 0; i < margrequirements.size(); ++i )
602  {
603  const ObjectImpType* req = margrequirements[i];
604  ArgsParser::spec spec;
605  spec.type = req;
606  spec.usetext = musetexts[i];
607  spec.selectstat = mselectstatements[i];
608  specs.push_back( spec );
609  };
610  return ArgsParser( specs );
611 }
612 
613 std::vector<ObjectCalcer*> ObjectHierarchy::buildObjects( const std::vector<ObjectCalcer*>& os, const KigDocument& doc ) const
614 {
615  assert( os.size() == mnumberofargs );
616  for ( uint i = 0; i < os.size(); ++i )
617  assert( os[i]->imp()->inherits( margrequirements[i] ) );
618 
619  std::vector<ObjectCalcer*> stack;
620  stack.resize( mnodes.size() + mnumberofargs, 0 );
621  std::copy( os.begin(), os.end(), stack.begin() );
622 
623  for( uint i = 0; i < mnodes.size(); ++i )
624  {
625  mnodes[i]->apply( stack, mnumberofargs + i );
626  stack[mnumberofargs + i]->calc( doc );
627  };
628 
629  std::vector<ObjectCalcer*> ret( stack.end() - mnumberofresults, stack.end() );
630 
631  return ret;
632 }
633 
634 const ObjectImpType* ObjectHierarchy::idOfLastResult() const
635 {
636  const Node* n = mnodes.back();
637  if ( n->id() == Node::ID_PushStack )
638  return static_cast<const PushStackNode*>( n )->imp()->type();
639  else if ( n->id() == Node::ID_FetchProp )
640  return ObjectImp::stype();
641  else
642  return static_cast<const ApplyTypeNode*>( n )->type()->resultId();
643 }
644 
645 ObjectHierarchy ObjectHierarchy::transformFinalObject( const Transformation& t ) const
646 {
647  assert( mnumberofresults == 1 );
648  ObjectHierarchy ret( *this );
649  ret.mnodes.push_back( new PushStackNode( new TransformationImp( t ) ) );
650 
651  std::vector<int> parents;
652  parents.push_back( ret.mnodes.size() - 1);
653  parents.push_back( ret.mnodes.size() );
654  const ObjectType* type = ApplyTransformationObjectType::instance();
655  ret.mnodes.push_back( new ApplyTypeNode( type, parents ) );
656  return ret;
657 }
658 
659 bool operator==( const ObjectHierarchy& lhs, const ObjectHierarchy& rhs )
660 {
661  if ( ! ( lhs.mnumberofargs == rhs.mnumberofargs &&
662  lhs.mnumberofresults == rhs.mnumberofresults &&
663  lhs.margrequirements == rhs.margrequirements &&
664  lhs.mnodes.size() == rhs.mnodes.size() ) )
665  return false;
666 
667  // this isn't entirely correct, but it will do, because we don't
668  // really want to know whether the hierarchies are different, but
669  // whether rhs has changed with regard to lhs..
670  for ( uint i = 0; i < lhs.mnodes.size(); ++i )
671  if ( lhs.mnodes[i] != lhs.mnodes[i] )
672  return false;
673 
674  return true;
675 }
676 
677 bool ObjectHierarchy::resultDoesNotDependOnGiven() const
678 {
679  std::vector<bool> dependsstack( mnodes.size() + mnumberofargs, false );
680 
681  for ( uint i = 0; i < mnumberofargs; ++i )
682  dependsstack[i] = true;
683  for ( uint i = 0; i < mnodes.size(); ++i )
684  mnodes[i]->checkDependsOnGiven( dependsstack, i + mnumberofargs );
685  for ( uint i = dependsstack.size() - mnumberofresults; i < dependsstack.size(); ++i )
686  if ( !dependsstack[i] )
687  return true;
688  return false;
689 }
690 
691 // returns the "minimum" of a and b ( in the partially ordered set of
692 // ObjectImpType's, using the inherits member function as comparison,
693 // if you for some reason like this sort of non-sense ;) ). This
694 // basically means: return the type that inherits the other type,
695 // because if another type inherits the lowermost type, then it will
696 // also inherit the other..
697 // mp: if a and b are not directly comparable, as a last resort return c,
698 // which is the "actual" ImpType of the object (see bug #157736 on
699 // bugs.kde.org)
700 const ObjectImpType* lowermost( const ObjectImpType* a, const ObjectImpType* b,
701  const ObjectImpType* c )
702 {
703  if ( a->inherits( b ) ) return a;
704  if ( b->inherits( a ) ) return b;
705  assert( c-> inherits( a ) );
706  assert( c-> inherits( b ) );
707  return c; // this is a last resort!
708 }
709 
710 // this function is part of the visit procedure really. It is
711 // factored out, because it recurses for cache ObjectImp's. What this
712 // does is, it makes sure that object o is calcable, by putting
713 // appropriate Node's in mnodes.. po is o->parents() and pl contains
714 // the location of objects that are already in mnodes and -1
715 // otherwise.. -1 means we have to store their ObjectImp, unless
716 // they're cache ObjectImp's etc.
717 int ObjectHierarchy::storeObject( const ObjectCalcer* o, const std::vector<ObjectCalcer*>& po, std::vector<int>& pl,
718  std::map<const ObjectCalcer*, int>& seenmap )
719 {
720  for ( uint i = 0; i < po.size(); ++i )
721  {
722  if ( pl[i] == -1 )
723  {
724  // we can't store cache ObjectImp's..
725  if ( po[i]->imp()->isCache() )
726  {
727  pl[i] = visit( po[i], seenmap, true, false );
728  }
729  else
730  {
731  Node* argnode = new PushStackNode( po[i]->imp()->copy() );
732  mnodes.push_back( argnode );
733  int argloc = mnumberofargs + mnodes.size() - 1;
734  seenmap[po[i]] = argloc;
735  pl[i] = argloc;
736  };
737  }
738  else if ( (uint) pl[i] < mnumberofargs )
739  {
740  ObjectCalcer* parent = o->parents()[i];
741  std::vector<ObjectCalcer*> opl = o->parents();
742 
743  margrequirements[pl[i]] =
744  lowermost( margrequirements[pl[i]],
745  o->impRequirement( parent, opl ), parent->imp()->type() );
746  musetexts[pl[i]] = margrequirements[pl[i]]->selectStatement();
747  };
748  };
749  if ( dynamic_cast<const ObjectTypeCalcer*>( o ) )
750  mnodes.push_back( new ApplyTypeNode( static_cast<const ObjectTypeCalcer*>( o )->type(), pl ) );
751  else if ( dynamic_cast<const ObjectPropertyCalcer*>( o ) )
752  {
753  assert( pl.size() == 1 );
754  int parent = pl.front();
755  ObjectCalcer* op = po.front();
756  assert( op );
757  int propgid = static_cast<const ObjectPropertyCalcer*>( o )->propGid();
758 // assert( propid < op->imp()->propertiesInternalNames().size() );
759 // mnodes.push_back( new FetchPropertyNode( parent, op->imp()->propertiesInternalNames()[propid], propgid ) );
760  mnodes.push_back( new FetchPropertyNode( parent, op->imp()->getPropName( propgid ), propgid ) );
761  }
762  else
763  assert( false );
764  seenmap[o] = mnumberofargs + mnodes.size() - 1;
765  return mnumberofargs + mnodes.size() - 1;
766 }
767 
768 ObjectHierarchy::ObjectHierarchy( const ObjectCalcer* from, const ObjectCalcer* to )
769 {
770  std::vector<ObjectCalcer*> fromv;
771  fromv.push_back( const_cast<ObjectCalcer*>( from ) );
772  std::vector<ObjectCalcer*> tov;
773  tov.push_back( const_cast<ObjectCalcer*>( to ) );
774  init( fromv, tov );
775 }
776 
777 bool ObjectHierarchy::allGivenObjectsUsed() const
778 {
779  std::vector<bool> usedstack( mnodes.size() + mnumberofargs, false );
780  for ( uint i = mnodes.size() - mnumberofresults; i < mnodes.size(); ++i )
781  usedstack[i + mnumberofargs] = true;
782  for ( int i = mnodes.size() - 1; i >= 0; --i )
783  if ( usedstack[i + mnumberofargs] )
784  mnodes[i]->checkArgumentsUsed( usedstack );
785  for ( uint i = 0; i < mnumberofargs; ++i )
786  if ( ! usedstack[i] ) return false;
787  return true;
788 }
789 
ObjectImpFactory::instance
static const ObjectImpFactory * instance()
Definition: object_imp_factory.cc:37
ObjectImpType
Instances of this class represent a certain ObjectImp type.
Definition: object_imp.h:95
ObjectHierarchy::idOfLastResult
const ObjectImpType * idOfLastResult() const
Definition: object_hierarchy.cc:634
ObjectHierarchy
Definition: object_hierarchy.h:30
ObjectHierarchy::buildSafeObjectHierarchy
static ObjectHierarchy * buildSafeObjectHierarchy(const QDomElement &parent, QString &error)
Deserialize the ObjectHierarchy data from the xml element parent .
Definition: object_hierarchy.cc:482
ObjectConstCalcer
This is an ObjectCalcer that keeps an ObjectImp, and never calculates a new one.
Definition: object_calcer.h:232
CopyObjectType::instance
static CopyObjectType * instance()
Definition: other_type.cc:96
ObjectImpType::inherits
bool inherits(const ObjectImpType *t) const
Does the ObjectImp type represented by this instance inherit the ObjectImp type represented by t ...
Definition: object_imp.cc:224
ObjectHierarchy::serialize
void serialize(QDomElement &parent, QDomDocument &doc) const
saves the ObjectHierarchy data in children xml tags of parent .
Definition: object_hierarchy.cc:414
ObjectHierarchy::~ObjectHierarchy
~ObjectHierarchy()
Definition: object_hierarchy.cc:342
ArgsParser::spec::type
const ObjectImpType * type
Definition: argsparser.h:113
ObjectImp::stype
static const ObjectImpType * stype()
The ObjectImpType representing the base ObjectImp class.
Definition: object_imp.cc:284
ObjectTypeCalcer
This is an ObjectCalcer that uses one of the various ObjectType's to calculate its ObjectImp...
Definition: object_calcer.h:183
KIG_GENERIC_PARSE_ERROR
#define KIG_GENERIC_PARSE_ERROR
ArgsParser::spec::usetext
std::string usetext
Definition: argsparser.h:113
lowermost
const ObjectImpType * lowermost(const ObjectImpType *a, const ObjectImpType *b, const ObjectImpType *c)
Definition: object_hierarchy.cc:700
ObjectHierarchy::calc
std::vector< ObjectImp * > calc(const Args &a, const KigDocument &doc) const
Definition: object_hierarchy.cc:256
ObjectImp::type
virtual const ObjectImpType * type() const =0
Returns the lowermost ObjectImpType that this object is an instantiation of.
operator==
bool operator==(const ObjectHierarchy &lhs, const ObjectHierarchy &rhs)
Definition: object_hierarchy.cc:659
ObjectImpFactory::deserialize
ObjectImp * deserialize(const QString &type, const QDomElement &parent, QString &error) const
loads data from parent , and returns a new ObjectImp from the type string type .
Definition: object_imp_factory.cc:288
ObjectImpType::selectStatement
const char * selectStatement() const
Returns a translatable string of the form "Select this %1".
Definition: object_imp.cc:245
ObjectHierarchy::withFixedArgs
ObjectHierarchy withFixedArgs(const Args &a) const
this creates a new ObjectHierarchy, that takes a.size() less arguments, but uses copies of the Object...
Definition: object_hierarchy.cc:358
ObjectCalcer
An ObjectCalcer is an object that represents an algorithm for calculating an ObjectImp from other Obj...
Definition: object_calcer.h:66
Args
std::vector< const ObjectImp * > Args
Definition: objects/common.h:47
Transformation
Class representing a transformation.
Definition: kigtransform.h:37
ObjectTypeFactory::instance
static ObjectTypeFactory * instance()
Definition: object_type_factory.cc:51
TransformationImp
Definition: bogus_imp.h:232
ObjectPropertyCalcer
This is an ObjectCalcer that has a single parent, and gets a certain property from it in its calc() m...
Definition: object_calcer.h:276
ArgsParser::spec
Definition: argsparser.h:113
ArgsParser
This class is meant to take care of checking the types of the parents to ObjectCalcer's, and to put them in the correct order.
Definition: argsparser.h:106
ObjectType
The ObjectType class is a thing that represents the "behaviour" for a certain type.
Definition: object_type.h:32
ObjectImpType::typeFromInternalName
static const ObjectImpType * typeFromInternalName(const char *n)
Returns the type with name n.
Definition: object_imp.cc:270
ObjectHierarchy::argParser
ArgsParser argParser() const
Definition: object_hierarchy.cc:598
ObjectImpFactory::serialize
QString serialize(const ObjectImp &d, QDomElement &parent, QDomDocument &doc) const
adds data to parent , and returns a type string.
Definition: object_imp_factory.cc:79
ObjectImp::getPropName
const char * getPropName(int propgid) const
Definition: object_imp.cc:356
ObjectHierarchy::buildObjects
std::vector< ObjectCalcer * > buildObjects(const std::vector< ObjectCalcer * > &os, const KigDocument &) const
build a set of objects that interdepend according to this ObjectHierarchy.
Definition: object_hierarchy.cc:613
ObjectHierarchy::allGivenObjectsUsed
bool allGivenObjectsUsed() const
Definition: object_hierarchy.cc:777
ObjectCalcer::impRequirement
virtual const ObjectImpType * impRequirement(ObjectCalcer *o, const std::vector< ObjectCalcer * > &os) const =0
An ObjectCalcer expects its parents to have an ObjectImp of a certain type.
KigDocument
KigDocument is the class holding the real data in a Kig document.
Definition: kig_document.h:36
ObjectImp::copy
virtual ObjectImp * copy() const =0
Returns a copy of this ObjectImp.
ObjectCalcer::imp
virtual const ObjectImp * imp() const =0
Returns the ObjectImp of this ObjectCalcer.
ApplyTransformationObjectType::instance
static const ApplyTransformationObjectType * instance()
Definition: transform_types.cc:834
ArgsParser::spec::selectstat
std::string selectstat
Definition: argsparser.h:113
ObjectImp
The ObjectImp class represents the behaviour of an object after it is calculated. ...
Definition: object_imp.h:226
ObjectImp::isCache
virtual bool isCache() const
Definition: object_imp.cc:306
ObjectCalcer::parents
virtual std::vector< ObjectCalcer * > parents() const =0
Returns the parent ObjectCalcer's of this ObjectCalcer.
object_hierarchy.h
ObjectHierarchy::resultDoesNotDependOnGiven
bool resultDoesNotDependOnGiven() const
Definition: object_hierarchy.cc:677
ObjectTypeFactory::find
const ObjectType * find(const char *name) const
Definition: object_type_factory.cc:63
ObjectHierarchy::transformFinalObject
ObjectHierarchy transformFinalObject(const Transformation &t) const
Definition: object_hierarchy.cc:645
uint
unsigned int uint
Definition: object_imp.h:87
InvalidImp
This ObjectImp represents an invalid object.
Definition: bogus_imp.h:61
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:35:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kig

Skip menu "kig"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal