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" 
   32 class ObjectHierarchy::Node
 
   35   enum { ID_PushStack, ID_ApplyType, ID_FetchProp };
 
   36   virtual int id() 
const = 0;
 
   39   virtual Node* copy() 
const = 0;
 
   41   virtual void apply( std::vector<const ObjectImp*>& stack, 
int loc,
 
   44   virtual void apply( std::vector<ObjectCalcer*>& stack, 
int loc ) 
const = 0;
 
   52   virtual void checkDependsOnGiven( std::vector<bool>& dependsstack, 
int loc ) 
const = 0;
 
   58   virtual void checkArgumentsUsed( std::vector<bool>& usedstack ) 
const = 0;
 
   61 ObjectHierarchy::Node::~Node()
 
   66   : 
public ObjectHierarchy::Node
 
   70   PushStackNode( 
ObjectImp* imp ) : mimp( imp ) {}
 
   73   const ObjectImp* imp()
 const { 
return mimp; }
 
   77   void apply( std::vector<const ObjectImp*>& stack,
 
   79   void apply( std::vector<ObjectCalcer*>& stack, 
int loc ) 
const;
 
   81   void checkDependsOnGiven( std::vector<bool>& dependsstack, 
int loc ) 
const;
 
   82   void checkArgumentsUsed( std::vector<bool>& usedstack ) 
const;
 
   85 void PushStackNode::checkArgumentsUsed( std::vector<bool>& )
 const 
   89 void PushStackNode::apply( std::vector<ObjectCalcer*>& stack, 
int loc )
 const 
   94 void PushStackNode::checkDependsOnGiven( std::vector<bool>&, 
int )
 const {
 
   99 int PushStackNode::id()
 const { 
return ID_PushStack; }
 
  101 PushStackNode::~PushStackNode()
 
  106 ObjectHierarchy::Node* PushStackNode::copy()
 const 
  108   return new PushStackNode( mimp->copy() );
 
  111 void PushStackNode::apply( std::vector<const ObjectImp*>& stack,
 
  114   stack[loc] = mimp->copy();
 
  118   : 
public ObjectHierarchy::Node
 
  121   std::vector<int> mparents;
 
  123   ApplyTypeNode( 
const ObjectType* type, 
const std::vector<int>& parents )
 
  124     : mtype( type ), mparents( parents ) {}
 
  128   const ObjectType* type()
 const { 
return mtype; }
 
  129   const std::vector<int>& parents()
 const { 
return mparents; }
 
  132   void apply( std::vector<const ObjectImp*>& stack,
 
  134   void apply( std::vector<ObjectCalcer*>& stack, 
int loc ) 
const;
 
  136   void checkDependsOnGiven( std::vector<bool>& dependsstack, 
int loc ) 
const;
 
  137   void checkArgumentsUsed( std::vector<bool>& usedstack ) 
const;
 
  140 int ApplyTypeNode::id()
 const { 
return ID_ApplyType; }
 
  142 void ApplyTypeNode::checkArgumentsUsed( std::vector<bool>& usedstack )
 const 
  144   for ( 
uint i = 0; i < mparents.size(); ++i )
 
  146     usedstack[mparents[i]] = 
true;
 
  150 void ApplyTypeNode::checkDependsOnGiven( std::vector<bool>& dependsstack, 
int loc )
 const 
  153   for ( 
uint i = 0; i < mparents.size(); ++i )
 
  154     if ( dependsstack[mparents[i]] == 
true ) result = 
true;
 
  155   dependsstack[loc] = result;
 
  158 ApplyTypeNode::~ApplyTypeNode()
 
  162 ObjectHierarchy::Node* ApplyTypeNode::copy()
 const 
  164   return new ApplyTypeNode( mtype, mparents );
 
  167 void ApplyTypeNode::apply( std::vector<ObjectCalcer*>& stack, 
int loc )
 const 
  169   std::vector<ObjectCalcer*> parents;
 
  170   for ( 
uint i = 0; i < mparents.size(); ++i )
 
  171     parents.push_back( stack[ mparents[i] ] );
 
  175 void ApplyTypeNode::apply( std::vector<const ObjectImp*>& stack,
 
  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 );
 
  185 class FetchPropertyNode
 
  186   : 
public ObjectHierarchy::Node
 
  188   mutable int mpropgid;
 
  196   FetchPropertyNode( 
const int parent, 
const QByteArray& name, 
const int propgid = -1 )
 
  197     : mpropgid( propgid ), mparent( parent ), mname( name ) {}
 
  198   ~FetchPropertyNode();
 
  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; }
 
  207   void apply( std::vector<const ObjectImp*>& stack,
 
  209   void apply( std::vector<ObjectCalcer*>& stack, 
int loc ) 
const;
 
  212 FetchPropertyNode::~FetchPropertyNode()
 
  216 void FetchPropertyNode::checkArgumentsUsed( std::vector<bool>& usedstack )
 const 
  218   usedstack[mparent] = 
true;
 
  221 void FetchPropertyNode::checkDependsOnGiven( std::vector<bool>& dependsstack, 
int loc )
 const 
  223   dependsstack[loc] = dependsstack[mparent];
 
  226 ObjectHierarchy::Node* FetchPropertyNode::copy()
 const 
  228   return new FetchPropertyNode( mparent, mname, mpropgid );
 
  231 int FetchPropertyNode::id()
 const 
  236 void FetchPropertyNode::apply( std::vector<const ObjectImp*>& stack,
 
  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 );
 
  248 void FetchPropertyNode::apply( std::vector<ObjectCalcer*>& stack, 
int loc )
 const 
  250   if ( mpropgid == -1 )
 
  251     mpropgid = stack[mparent]->imp()->getPropGid( mname );
 
  252   assert( mpropgid != -1 );
 
  258   assert( a.size() == mnumberofargs );
 
  259   for ( 
uint i = 0; i < a.size(); ++i )
 
  260     assert( a[i]->inherits( margrequirements[i] ) );
 
  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 )
 
  267     mnodes[i]->apply( stack, mnumberofargs + i, doc );
 
  269   for ( 
uint i = mnumberofargs; i < stack.size() - mnumberofresults; ++i )
 
  271   if ( stack.size() < mnumberofargs + mnumberofresults )
 
  273     std::vector<ObjectImp*> ret;
 
  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] ) );
 
  286 int ObjectHierarchy::visit( 
const ObjectCalcer* o, std::map<const ObjectCalcer*, int>& seenmap,
 
  287                             bool needed, 
bool neededatend )
 
  291   std::map<const ObjectCalcer*, int>::iterator smi = seenmap.find( o );
 
  292   if ( smi != seenmap.end() )
 
  300       int ret = mnumberofargs + mnodes.size();
 
  301       std::vector<int> parents;
 
  302       parents.push_back( smi->second );
 
  306     else return smi->second;
 
  309   std::vector<ObjectCalcer*> p( o->
parents() );
 
  311   bool descendsfromgiven = 
false;
 
  312   std::vector<int> parents;
 
  313   parents.resize( p.size(), -1 );
 
  314   for ( 
uint i = 0; i < p.size(); ++i )
 
  316     int v = visit( p[i], seenmap, 
false );
 
  318     descendsfromgiven |= (v != -1);
 
  321   if ( ! descendsfromgiven && ! ( needed && o->
imp()->
isCache() ) )
 
  329       Node* node = 
new PushStackNode( o->
imp()->
copy() );
 
  330       mnodes.push_back( node );
 
  331       int ret = mnodes.size() + mnumberofargs - 1;
 
  339   return storeObject( o, p, parents, seenmap );
 
  344   for ( 
uint i = 0; i < mnodes.size(); ++i ) 
delete mnodes[i];
 
  348   : mnumberofargs( h.mnumberofargs ), mnumberofresults( h.mnumberofresults ),
 
  349     msaveinputtags( h.msaveinputtags ),
 
  350     margrequirements( h.margrequirements ), musetexts( h.musetexts ),
 
  351     mselectstatements( h.mselectstatements )
 
  353   mnodes.reserve( h.mnodes.size() );
 
  354   for ( 
uint i = 0; i < h.mnodes.size(); ++i )
 
  355     mnodes.push_back( h.mnodes[i]->copy() );
 
  360   assert( a.size() <= mnumberofargs );
 
  363   ret.mnumberofargs -= a.size();
 
  364   ret.margrequirements.resize( ret.mnumberofargs );
 
  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 )
 
  370     assert( ! a[i]->isCache() );
 
  371     *newnodesiter++ = 
new PushStackNode( a[i]->copy() );
 
  373   std::copy( ret.mnodes.begin(), ret.mnodes.end(), newnodesiter );
 
  374   ret.mnodes = newnodes;
 
  379 void ObjectHierarchy::init( 
const std::vector<ObjectCalcer*>& from, 
const std::vector<ObjectCalcer*>& to )
 
  381   msaveinputtags = 
false;
 
  382   mnumberofargs = from.size();
 
  383   mnumberofresults = to.size();
 
  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 )
 
  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 );
 
  396   for ( std::vector<ObjectCalcer*>::const_iterator i = to.begin(); i != to.end(); ++i )
 
  397     visit( *i, seenmap, 
true, 
true );
 
  399   mselectstatements.resize( margrequirements.size(), 
"" );
 
  402 ObjectHierarchy::ObjectHierarchy( 
const std::vector<ObjectCalcer*>& from, 
const ObjectCalcer* to )
 
  404   std::vector<ObjectCalcer*> tov;
 
  405   tov.push_back( const_cast<ObjectCalcer*>( to ) );
 
  409 ObjectHierarchy::ObjectHierarchy( 
const std::vector<ObjectCalcer*>& from, 
const std::vector<ObjectCalcer*>& to )
 
  417   for ( 
uint i = 0; i < mnumberofargs; ++i )
 
  421     e.
setAttribute( 
"requirement", margrequirements[i]->internalName() );
 
  424     if ( msaveinputtags )
 
  436   for ( 
uint i = 0; i < mnodes.size(); ++i )
 
  438     bool result = mnodes.size() - ( 
id - mnumberofargs - 1 ) <= mnumberofresults;
 
  442     if ( mnodes[i]->
id() == Node::ID_ApplyType )
 
  444       const ApplyTypeNode* node = 
static_cast<const ApplyTypeNode*
>( mnodes[i] );
 
  447       for ( 
uint i = 0; i < node->parents().size(); ++i )
 
  449         int parent = node->parents()[i] + 1;
 
  455     else if ( mnodes[i]->
id() == Node::ID_FetchProp )
 
  457       const FetchPropertyNode* node = 
static_cast<const FetchPropertyNode*
>( mnodes[i] );
 
  466       assert( mnodes[i]->
id() == ObjectHierarchy::Node::ID_PushStack );
 
  467       const PushStackNode* node = 
static_cast<const PushStackNode*
>( mnodes[i] );
 
  477 ObjectHierarchy::ObjectHierarchy()
 
  478   : mnumberofargs( 0 ), mnumberofresults( 0 ), msaveinputtags( false )
 
  484 #define KIG_GENERIC_PARSE_ERROR \ 
  486     error = i18n( "An error was encountered at line %1 in file %2.", \ 
  487               __LINE__, __FILE__ ); \ 
  498     if ( e.
tagName() != 
"input" ) 
break;
 
  504     obhi->mnumberofargs = qMax( 
id, obhi->mnumberofargs );
 
  510     obhi->musetexts.resize( obhi->mnumberofargs, 
"" );
 
  511     obhi->mselectstatements.resize( obhi->mnumberofargs, 
"" );
 
  512     obhi->margrequirements[
id - 1] = req;
 
  517       if ( esub.
tagName() == 
"UseText" )
 
  519         obhi->msaveinputtags = 
true;
 
  522       else if ( esub.
tagName() == 
"SelectStatement" )
 
  524         obhi->msaveinputtags = 
true;
 
  535     bool result = e.
tagName() == 
"result";
 
  536     if ( result ) ++obhi->mnumberofresults;
 
  539     int id = tmp.
toInt( &ok );
 
  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 ) );
 
  559       std::vector<int> parents;
 
  567         parents.push_back( pid - 1 );
 
  569       newnode = 
new ApplyTypeNode( type, parents );
 
  571     else if ( tmp == 
"fetch-property" )
 
  578       newnode = 
new FetchPropertyNode( parent - 1, propname );
 
  587       if ( ( ! imp ) && !error.
isEmpty() ) 
return 0;
 
  588       newnode = 
new PushStackNode( imp );
 
  590     obhi->mnodes.resize( qMax( 
size_t(
id - obhi->mnumberofargs), obhi->mnodes.size() ) );
 
  591     obhi->mnodes[
id - obhi->mnumberofargs - 1] = newnode;
 
  600   std::vector<ArgsParser::spec> specs;
 
  601   for ( 
uint i = 0; i < margrequirements.size(); ++i )
 
  608     specs.push_back( spec );
 
  615   assert( os.size() == mnumberofargs );
 
  616   for ( 
uint i = 0; i < os.size(); ++i )
 
  617     assert( os[i]->imp()->inherits( margrequirements[i] ) );
 
  619   std::vector<ObjectCalcer*> stack;
 
  620   stack.resize( mnodes.size() + mnumberofargs, 0 );
 
  621   std::copy( os.begin(), os.end(), stack.begin() );
 
  623   for( 
uint i = 0; i < mnodes.size(); ++i )
 
  625     mnodes[i]->apply( stack, mnumberofargs + i );
 
  626     stack[mnumberofargs + i]->calc( doc );
 
  629   std::vector<ObjectCalcer*> ret( stack.end() - mnumberofresults, stack.end() );
 
  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 )
 
  642     return static_cast<const ApplyTypeNode*
>( n )->type()->resultId();
 
  647   assert( mnumberofresults == 1 );
 
  651   std::vector<int> parents;
 
  652   parents.push_back( ret.mnodes.size() - 1);
 
  653   parents.push_back( ret.mnodes.size() );
 
  655   ret.mnodes.push_back( 
new ApplyTypeNode( type, parents ) );
 
  661   if ( ! ( lhs.mnumberofargs == rhs.mnumberofargs &&
 
  662            lhs.mnumberofresults == rhs.mnumberofresults &&
 
  663            lhs.margrequirements == rhs.margrequirements &&
 
  664            lhs.mnodes.size() == rhs.mnodes.size() ) )
 
  670   for ( 
uint i = 0; i < lhs.mnodes.size(); ++i )
 
  671     if ( lhs.mnodes[i] != lhs.mnodes[i] )
 
  679   std::vector<bool> dependsstack( mnodes.size() + mnumberofargs, false );
 
  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] )
 
  705   assert( c-> inherits( a ) );
 
  706   assert( c-> inherits( b ) );
 
  717 int ObjectHierarchy::storeObject( 
const ObjectCalcer* o, 
const std::vector<ObjectCalcer*>& po, std::vector<int>& pl,
 
  718                                   std::map<const ObjectCalcer*, int>& seenmap )
 
  720   for ( 
uint i = 0; i < po.size(); ++i )
 
  725       if ( po[i]->imp()->isCache() )
 
  727         pl[i] = visit( po[i], seenmap, 
true, 
false );
 
  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;
 
  738     else if ( (
uint) pl[i] < mnumberofargs )
 
  741       std::vector<ObjectCalcer*> opl = o->
parents();
 
  743       margrequirements[pl[i]] =
 
  746       musetexts[pl[i]] = margrequirements[pl[i]]->selectStatement();
 
  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 ) )
 
  753     assert( pl.size() == 1 );
 
  754     int parent = pl.front();
 
  760     mnodes.push_back( 
new FetchPropertyNode( parent, op->
imp()->
getPropName( propgid ), propgid ) );
 
  764   seenmap[o] = mnumberofargs + mnodes.size() - 1;
 
  765   return mnumberofargs + mnodes.size() - 1;
 
  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 ) );
 
  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;
 
static const ObjectImpFactory * instance()
Instances of this class represent a certain ObjectImp type. 
const ObjectImpType * idOfLastResult() const 
static ObjectHierarchy * buildSafeObjectHierarchy(const QDomElement &parent, QString &error)
Deserialize the ObjectHierarchy data from the xml element parent . 
QDomNode appendChild(const QDomNode &newChild)
This is an ObjectCalcer that keeps an ObjectImp, and never calculates a new one. 
QString attribute(const QString &name, const QString &defValue) const
static CopyObjectType * instance()
bool inherits(const ObjectImpType *t) const 
Does the ObjectImp type represented by this instance inherit the ObjectImp type represented by t ...
void serialize(QDomElement &parent, QDomDocument &doc) const 
saves the ObjectHierarchy data in children xml tags of parent . 
const ObjectImpType * type
static const ObjectImpType * stype()
The ObjectImpType representing the base ObjectImp class. 
This is an ObjectCalcer that uses one of the various ObjectType's to calculate its ObjectImp...
#define KIG_GENERIC_PARSE_ERROR
QDomNode nextSibling() const
const ObjectImpType * lowermost(const ObjectImpType *a, const ObjectImpType *b, const ObjectImpType *c)
QDomElement toElement() const
std::vector< ObjectImp * > calc(const Args &a, const KigDocument &doc) const 
QString number(int n, int base)
virtual const ObjectImpType * type() const =0
Returns the lowermost ObjectImpType that this object is an instantiation of. 
bool operator==(const ObjectHierarchy &lhs, const ObjectHierarchy &rhs)
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
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 . 
const char * selectStatement() const 
Returns a translatable string of the form "Select this %1". 
ObjectHierarchy withFixedArgs(const Args &a) const 
this creates a new ObjectHierarchy, that takes a.size() less arguments, but uses copies of the Object...
An ObjectCalcer is an object that represents an algorithm for calculating an ObjectImp from other Obj...
std::vector< const ObjectImp * > Args
static ObjectTypeFactory * instance()
This is an ObjectCalcer that has a single parent, and gets a certain property from it in its calc() m...
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. 
QDomText createTextNode(const QString &value)
The ObjectType class is a thing that represents the "behaviour" for a certain type. 
static const ObjectImpType * typeFromInternalName(const char *n)
Returns the type with name n. 
ArgsParser argParser() const 
QString serialize(const ObjectImp &d, QDomElement &parent, QDomDocument &doc) const 
adds data to parent , and returns a type string. 
const char * getPropName(int propgid) const 
std::vector< ObjectCalcer * > buildObjects(const std::vector< ObjectCalcer * > &os, const KigDocument &) const 
build a set of objects that interdepend according to this ObjectHierarchy. 
QDomNode firstChild() const
QByteArray toLatin1() const
bool allGivenObjectsUsed() const 
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 is the class holding the real data in a Kig document. 
virtual ObjectImp * copy() const =0
Returns a copy of this ObjectImp. 
virtual const ObjectImp * imp() const =0
Returns the ObjectImp of this ObjectCalcer. 
QString fromLatin1(const char *str, int size)
The ObjectImp class represents the behaviour of an object after it is calculated. ...
virtual bool isCache() const 
QDomElement createElement(const QString &tagName)
virtual std::vector< ObjectCalcer * > parents() const =0
Returns the parent ObjectCalcer's of this ObjectCalcer. 
bool resultDoesNotDependOnGiven() const 
const ObjectType * find(const char *name) const 
ObjectHierarchy transformFinalObject(const Transformation &t) const 
This ObjectImp represents an invalid object.