/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

/*  This code generated by: 
 *      Author : thomas
 *      Date   : Thu Jun 19 2003
 */



#ifndef CLASSIFIERCODEDOCUMENT_H
#define CLASSIFIERCODEDOCUMENT_H

#include <qmap.h>
#include <qstring.h>
#include <qptrlist.h>

#include "attribute.h"
#include "classifier.h"
#include "codeaccessormethod.h"
#include "codedocument.h"
#include "codeoperation.h"
#include "codeclassfield.h"
#include "operation.h"
#include "umlrole.h"
#include "umlassociationlist.h"

/**
  * class ClassifierCodeDocument
  * A CodeDocument which represents a UMLClassifier (e.g. a Class or Interface) 
  */

class ClassifierCodeDocument : public CodeDocument
{
	friend class HierarchicalCodeBlock;
	Q_OBJECT
public:

	// Constructors/Destructors
	//  


	/**
	 * Empty Constructor
	 */
	ClassifierCodeDocument ( UMLClassifier * parent , CodeGenerator * gen);

	/**
	 * Empty Destructor
	 */
	virtual ~ClassifierCodeDocument ( );

	/**
	 * Add a CodeClassField object to the m_classfieldVector List
	 */
	bool addCodeClassField ( CodeClassField * add_object );

	/**
	 * Remove a CodeClassField object from m_classfieldVector List
	 */
	bool removeCodeClassField ( CodeClassField * remove_object );

	/**
	 * Get the list of CodeClassField objects held by m_classfieldVector
	 * @return QPtrList<CodeClassField> list of CodeClassField objects held by
	 * m_classfieldVector
	 */
	QPtrList<CodeClassField> * getCodeClassFieldList ( );

	// some Utility methods

	/**
	 * Return if the parent classifier is an interface
	 */
	bool parentIsInterface();

	/**
	 * Return if the parent classifier is a class
	 */
	bool parentIsClass();

	/**
	 * Tell if one or more codeclassfields are derived from any kind of association.
	 */
	bool hasAssociationClassFields();
	/**
	 * Tell if one or more codeclassfields are derived from attributes.
	 */
	bool hasAttributeClassFields();

	/**
	 * Tell if any of the accessor classfields will be of lists of objects.
	 */
	bool hasObjectVectorClassFields();

	/**
	 * Does this object have any classfields declared?
	 */
	bool hasClassFields();

	/**
	 * Get a list of codeoperation objects held by this classifiercodedocument.
         * @return      QPtrList<CodeOperation>
         */
        QPtrList<CodeOperation> getCodeOperations ( );

	/** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
         * @return      QPtrList<CodeClassField>
	 */
	QPtrList<CodeClassField> getSpecificClassFields (CodeClassField::ClassFieldType cfType);

	/** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
         * @return      QPtrList<CodeClassField>
	 */
	QPtrList<CodeClassField> getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic);

	/** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
         * @return      QPtrList<CodeClassField>
	 */
	QPtrList<CodeClassField> getSpecificClassFields (CodeClassField::ClassFieldType cfType, Uml::Scope visibility);

	/** Get a list of codeclassifier objects held by this classifiercodedocument that meet the passed criteria.
         * @return      QPtrList<CodeClassField>
	 */
	QPtrList<CodeClassField> getSpecificClassFields (CodeClassField::ClassFieldType cfType, bool isStatic, Uml::Scope visibility);

	/** Using the parent object's UML ID, find the cooresponding
	 * codeclassfield object in this classifiercodedocument. Returns
	 * NULL if no such codeclassfield object exists in this document.
	 */
	CodeClassField * findCodeClassFieldFromParentID (int id, int role_id = -1);

	/**
	 * Get the value of m_parentclassifier
	 * @return the value of m_parentclassifier
	 */
	UMLClassifier * getParentClassifier ( );

	// a utility method that allows user to easily add classfield methods to this document
	void addCodeClassFieldMethods(QPtrList<CodeClassField> &list );

       /**
         * Utility method to appropriately populate the code classfields for this document.
         */
        virtual void initCodeClassFields ( );

	// cause this classifier code document to synchronize to current policy
	virtual void synchronize();

	/** Will add the code operation in the correct place in the document.
	 *  @return bool which is true IF the code operation was added successfully
 	 */
	virtual bool addCodeOperation (CodeOperation *opBlock) = 0;

       /**
         * Save the XMI representation of this object
         * @return      bool    status of save
         */
        virtual bool saveToXMI ( QDomDocument & doc, QDomElement & root );

        /**
         * load params from the appropriate XMI element node.
         */
        virtual void loadFromXMI ( QDomElement & root );

	virtual CodeClassFieldDeclarationBlock * newDeclarationCodeBlock (CodeClassField * cf) = 0;
	virtual CodeAccessorMethod * newCodeAccessorMethod ( CodeClassField *cp, CodeAccessorMethod::AccessorType type) = 0;
	virtual CodeOperation * newCodeOperation ( UMLOperation * op) = 0;


protected:

	/**
	 * little utility method to load codeclassifields from XMI element node.
	 */
	void loadClassFieldsFromXMI( QDomElement & childElem);

        /**
         * @return      CodeClassField
         * @param       attribute attribute which is parent of this class field.
         */
        virtual CodeClassField * newCodeClassField (UMLAttribute * attribute ) = 0;

        /**
         * @return      CodeClassField
         * @param       role 
         */
        virtual CodeClassField * newCodeClassField (UMLRole * role ) = 0;

        /** set attributes of the node that represents this class
         * in the XMI document.
         */
        virtual void setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement);

        /** set the class attributes of this object from
         * the passed element node.
         */
        virtual void setAttributesFromNode ( QDomElement & element);

	// find a specific textblock held by any code class field in this document 
	// by its tag
	TextBlock * findCodeClassFieldTextBlockByTag (QString tag);

        // add the declaration text blocks for various classfields
        void declareClassFields (QPtrList<CodeClassField> & list , CodeGenObjectWithTextBlocks * parent);

	virtual void updateContent( ) = 0;
 
	// force syncronization of child classfields to their parent objects
	void syncClassFields( );

	// IF the classifier object is modified, this will get called.
	// Possible mods include changing the filename and package
	// based on values the classifier has.
        virtual void syncNamesToParent( );

private:

	QPtrList<CodeClassField> m_classfieldVector;
	UMLClassifier* m_parentclassifier;

	// using the passed list, update our inventory of CodeClassFields which are
	// based on UMLRoles (e.g. dervied from associations with other classifiers).
 	void updateAssociationClassFields ( UMLAssociationList &assocList ); 

	// update code operations in this document using the parent classifier
	void updateOperations( );

	/**
         * Maps CodeClassFields to UMLObjects. Used to prevent re-adding a class
     	 * field.
         */
        QMap<UMLObject *,CodeClassField *> * m_classFieldMap;

        /**
         * Init from a UMLClassifier object.
         * @param       classifier 
         */
        void init ( UMLClassifier * classifier );

public slots:

	/**
	 * Syncronize this document to the attributes/associations of the parent classifier.
	 */
	void addAttributeClassField(UMLObject *at=0, bool syncToParentIfAdded = true);
	void addAssociationClassField (UMLAssociation * assoc=0, bool syncToParentIfAdded = true);
	void removeAttributeClassField(UMLObject *at);
	void removeAssociationClassField(UMLAssociation *assoc);
	void addOperation (UMLOperation * obj);
	void removeOperation (UMLOperation * obj);
	void syncToParent( );

};

#endif // CLASSIFIERCODEDOCUMENT_H
