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.