#ifndef AbstractContextH
#define AbstractContextH

#define BOOST_THREAD_USE_LIB
#include "Context.h"
#include <boost/thread/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
#include "util/Log.h"
#include "util/ThreadPoolCachedEx.h"
#include <boost/weak_ptr.hpp>

class AbstractContext : public Context
{
private:
    static const int VERY_LOW_PERFORMANCE_THRESHOLD  = 120000;
    static const int LOW_PERFORMANCE_THRESHOLD = 20000;

    ContextManager* contextManager;
	std::map<AgString, VariableDataPtr> variableData;
    std::map<VariableDefinitionPtr, int> variableOder;
    int variableCounter;
    boost::mutex variableDataLock; //many readers, one writer
    std::map<AgString, FunctionDataPtr> *functionData;
    std::map<FunctionDefinitionPtr, int> functionOder;
    int functionCounter;
    boost::mutex functionDataLock;
    std::map<AgString, EventDataPtr> eventData;
    std::map<EventDefinitionPtr, int> eventOder;
    int eventCounter;
    boost::mutex eventDataLock;
    std::vector<ActionDefinitionPtr>  actionDefinitions;
    boost::mutex actionDefinitionsLock;

    AgString name;
    AgString description;
   
	AgString type;
    AgString group;
    AgString iconId;
    Context* parent;
	
    bool setupComplete;
	
    bool started;
    boost::optional<int> index;

    bool permissionCheckingEnabled;
    PermissionsPtr permissions;
	PermissionsPtr childrenViewPermissions;
	PermissionCheckerPtr permissionChecker;
    std::vector<Context *>  children;
    std::map<AgString,Context *> childrenMap;
    boost::mutex childrenLock;
    bool valueCheckingEnabled;
    bool childrenConcurrencyEnabled;
    bool childrenSortingEnabled;
    bool fireUpdateEvents;
    ContextStatusPtr status;
    std::map<AgString, VariableStatusPtr> variableStatuses;
    bool variableStatusesUpdated;
    boost::mutex variableStatusesLock;

    AgString path;

    bool shouldSeeChild(CallerControllerPtr caller, Context* cur);
    bool canSee(CallerControllerPtr caller, Context* con);
    void setContextManager(ContextManager* contextManager);

    void move(const AgString & oldPath, Context* newParent, const AgString & newName);
    Context* getChildWithoutCheckingPerms(const AgString & name);
    AgString createPath();
	VariableDefinitionPtr getAndCheckVariableDefinition(const AgString & name) ;
	DataTablePtr executeDefaultGetter(VariableDefinitionPtr def, CallerControllerPtr caller, bool check, bool createDefault) ;
	DataTablePtr getVariable(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;
	DataTablePtr checkVariableValue(VariableDefinitionPtr def, DataTablePtr val) ;
    AgString  checkVariableValueFormat(VariableDefinitionPtr def, DataTablePtr table);
	DataTablePtr executeGetter(VariableDataPtr data, CallerControllerPtr caller, RequestControllerPtr request) ;
	DataTablePtr executeGetterMethod(VariableDataPtr data, CallerControllerPtr caller, RequestControllerPtr request) ;
	void contextInfoChanded();
    DataTablePtr callFunction(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
	DataTablePtr executeImplementation(FunctionDataPtr data, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
	DataTablePtr executeImplementationMethod(FunctionDataPtr data, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
    DataTablePtr getDefaultFunctionOutput(FunctionDefinitionPtr def);
    FunctionDefinitionPtr getAndCheckFunctionDefinition(const AgString & name);
    EventDefinitionPtr getAndCheckEventDefinition(const AgString & name);
    virtual EventPtr fireEvent(EventDefinitionPtr ed, EventPtr event, int  listener, CallerControllerPtr caller, FireEventRequestControllerPtr request);

	void processEnrichments(EventPtr event, EventProcessingRulePtr rule, CallerControllerPtr caller);
    void lock(RequestControllerPtr request, boost::mutex lock) ;
	DataRecordPtr varDefToDataRecord(VariableDefinitionPtr vd, CallerControllerPtr caller);
    VariableDefinitionPtr varDefFromDataRecord(DataRecordPtr rec, CallerControllerPtr caller);

	void setVariable(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value) ;
	void executeSetter(VariableDataPtr data, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value);
	bool executeSetterMethod(VariableDataPtr data, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value);
    DataRecordPtr funcDefToDataRecord(FunctionDefinitionPtr fd, CallerControllerPtr caller);
    DataRecordPtr evtDefToDataRecord(EventDefinitionPtr ed, CallerControllerPtr caller);
    EventDefinitionPtr evtDefFromDataRecord(DataRecordPtr rec, CallerControllerPtr caller);
	DataTablePtr createVariableStatusesTable();
    std::map<AgString, VariableStatusPtr> getVariableStatuses();
    void ensureVariableStatuses() ;
    DataTablePtr createContextInfoTable();
    void init();

    FunctionDefinitionPtr funcDefFromDataRecord(DataRecordPtr rec, CallerControllerPtr caller);

    static TableFormatPtr initVARIABLE_DEFINITION_FORMAT();
    static TableFormatPtr initEF_VARIABLE_ADDED();
    static TableFormatPtr initFUNCTION_DEFINITION_FORMAT();
    static TableFormatPtr initEF_FUNCTION_ADDED();
    static TableFormatPtr initEVENT_DEFINITION_FORMAT();
    static TableFormatPtr initEF_EVENT_ADDED();
    static TableFormatPtr initVFT_CHILDREN();
    static TableFormatPtr initINFO_DEFINITION_FORMAT();
    static TableFormatPtr initACTION_DEF_FORMAT();
    static TableFormatPtr initRESOURCE_MASKS_FORMAT();
    static TableFormatPtr initFIFT_GET_COPY_DATA();
    static TableFormatPtr initFIFT_GET_COPY_DATA_RECIPIENTS();
    static TableFormatPtr initREPLICATE_INPUT_FORMAT();
    static TableFormatPtr initFIFT_REPLICATE_FIELDS();
    static TableFormatPtr initREPLICATE_OUTPUT_FORMAT();
    static TableFormatPtr initREPLICATE_TO_CHILDREN_OUTPUT_FORMAT();
    static TableFormatPtr initEF_UPDATED();
    static TableFormatPtr initEF_CHANGE();

    static VariableDefinitionPtr initVD_INFO();
    static VariableDefinitionPtr initVD_FUNCTIONS();
    static VariableDefinitionPtr initVD_EVENTS();
    static VariableDefinitionPtr initVD_ACTIONS();
    static VariableDefinitionPtr initVD_CHILDREN();
    static VariableDefinitionPtr initVD_VARIABLES();
    static FunctionDefinitionPtr initFD_GET_COPY_DATA();
    static FunctionDefinitionPtr initFD_COPY();
    static FunctionDefinitionPtr initFD_COPY_TO_CHILDREN();
    static EventDefinitionPtr initED_INFO();
    static EventDefinitionPtr initED_CHILD_ADDED();
    static EventDefinitionPtr initED_CHILD_REMOVED();
    static EventDefinitionPtr initED_VARIABLE_ADDED();
    static EventDefinitionPtr initED_VARIABLE_REMOVED();
    static EventDefinitionPtr initED_FUNCTION_ADDED();
    static EventDefinitionPtr initED_FUNCTION_REMOVED();
    static EventDefinitionPtr initED_EVENT_ADDED();
    static EventDefinitionPtr initED_EVENT_REMOVED();
    static EventDefinitionPtr initED_ACTION_ADDED();
    static EventDefinitionPtr initED_ACTION_REMOVED();
    static EventDefinitionPtr initED_ACTION_STATE_CHANGED();
    static EventDefinitionPtr initED_INFO_CHANGED();
    static EventDefinitionPtr initED_UPDATED();
    static EventDefinitionPtr initED_CHANGE();
    static EventDefinitionPtr initED_DESTROYED();
    static TableFormatPtr initVFT_VARIABLE_STATUSES();

    class StartContextTask : public Callable<int>
    {
        Context* context;

    public:
        StartContextTask(Context * ownignContext) {
            this->context = ownignContext;
        }
        virtual int call() {
            boost::posix_time::ptime startTime = boost::posix_time::microsec_clock::local_time();
            context->start();
            boost::posix_time::time_duration dur = boost::posix_time::microsec_clock::local_time() - startTime;
            LOG_CONTEXT_CHILDREN_DEBUG("Started context  '" + context->getPath().toUtf8() + "' in " + boost::lexical_cast<std::string>(dur.total_milliseconds()) + " ms");
            return 0;
        }
    };

    class StopContextTask : public Callable<int>
    {
        Context* context;

    public:
        StopContextTask(Context * ownignContext) {
            this->context = ownignContext;
        }
        virtual int call() {
            boost::posix_time::ptime startTime = boost::posix_time::microsec_clock::local_time();
            context->stop();
            boost::posix_time::time_duration dur = boost::posix_time::microsec_clock::local_time() - startTime;

            LOG_CONTEXT_CHILDREN_DEBUG("Stopped context  '" + context->getPath().toUtf8() + "' in " + boost::lexical_cast<std::string>(dur.total_milliseconds()) + " ms");
            return 0;
        }
    };

public:
    static TableFormatPtr VARIABLE_DEFINITION_FORMAT;
    static TableFormatPtr EF_VARIABLE_ADDED;
    static TableFormatPtr FUNCTION_DEFINITION_FORMAT;
    static TableFormatPtr EF_FUNCTION_ADDED;
    static TableFormatPtr EVENT_DEFINITION_FORMAT;
    static TableFormatPtr EF_EVENT_ADDED;
    static TableFormatPtr VFT_CHILDREN;
    static TableFormatPtr INFO_DEFINITION_FORMAT;
    static TableFormatPtr ACTION_DEF_FORMAT;
    static TableFormatPtr RESOURCE_MASKS_FORMAT;
    static TableFormatPtr FIFT_GET_COPY_DATA;
    static TableFormatPtr FIFT_GET_COPY_DATA_RECIPIENTS;
    static TableFormatPtr REPLICATE_INPUT_FORMAT;
    static TableFormatPtr FIFT_REPLICATE_FIELDS;
    static TableFormatPtr REPLICATE_OUTPUT_FORMAT;
    static TableFormatPtr REPLICATE_TO_CHILDREN_OUTPUT_FORMAT;
    static TableFormatPtr EF_UPDATED;
    static TableFormatPtr EF_CHANGE;
    static TableFormatPtr EFT_INFO;
    static TableFormatPtr EFT_VARIABLE_REMOVED;
    static TableFormatPtr EFT_EVENT_REMOVED;
    static TableFormatPtr EFT_FUNCTION_REMOVED;
    static TableFormatPtr EFT_CHILD_REMOVED;
    static TableFormatPtr EFT_CHILD_ADDED;
    static TableFormatPtr EFT_ACTION_REMOVED;
    static VariableDefinitionPtr VD_INFO;
    static VariableDefinitionPtr VD_VARIABLES;
    static VariableDefinitionPtr VD_FUNCTIONS;
    static VariableDefinitionPtr VD_EVENTS;
    static VariableDefinitionPtr VD_ACTIONS;
    static VariableDefinitionPtr VD_CHILDREN;
    static FunctionDefinitionPtr FD_GET_COPY_DATA;
    static FunctionDefinitionPtr FD_COPY;
    static FunctionDefinitionPtr FD_COPY_TO_CHILDREN;
	static EventDefinitionPtr ED_INFO;
    static EventDefinitionPtr ED_CHILD_ADDED;
    static EventDefinitionPtr ED_CHILD_REMOVED;
    static EventDefinitionPtr ED_VARIABLE_ADDED;
    static EventDefinitionPtr ED_VARIABLE_REMOVED;
    static EventDefinitionPtr ED_FUNCTION_ADDED;
    static EventDefinitionPtr ED_FUNCTION_REMOVED;
    static EventDefinitionPtr ED_EVENT_ADDED;
    static EventDefinitionPtr ED_EVENT_REMOVED;
    static EventDefinitionPtr ED_ACTION_ADDED;
    static EventDefinitionPtr ED_ACTION_REMOVED;
    static EventDefinitionPtr ED_ACTION_STATE_CHANGED;
    static EventDefinitionPtr ED_INFO_CHANGED;
    static EventDefinitionPtr ED_UPDATED;
    static EventDefinitionPtr ED_CHANGE;
    static EventDefinitionPtr ED_DESTROYED;
    static TableFormatPtr VFT_VARIABLE_STATUSES;
    static const int DEFAULT_EVENT_LEVEL = -1;
    static PermissionsPtr DEFAULT_PERMISSIONS;




	static const int INDEX_HIGHEST = 400;
    static const int INDEX_VERY_HIGH = 300;
    static const int INDEX_HIGH = 200;
    static const int INDEX_HIGHER = 100;
    static const int INDEX_NORMAL;
    static const int INDEX_LOWER = -100;
    static const int INDEX_LOW = -200;
    static const int INDEX_VERY_LOW = -300;
    static const int INDEX_LOWEST = -400;
    static const int DELTA_HIGHEST = 40;
    static const int DELTA_VERY_HIGH = 30;
    static const int DELTA_HIGH = 20;
    static const int DELTA_HIGHER = 10;
    static const int DELTA_LOWER = -10;
    static const int DELTA_LOW = -20;
    static const int DELTA_VERY_LOW = -30;
    static const int DELTA_LOWEST = -400;

    void setup(ContextManager* contextManager);
    void setup();

    virtual void setupPermissions();
    virtual void setupMyself();

	void setupChildren() ;
    void teardown();
    void start();
    void stop();
    virtual int compareTo(Comparable *other);
    virtual std::list<Context*>  getChildren(CallerControllerPtr caller);

    virtual std::list<Context*>  getChildren();
    virtual std::list<Context*> getVisibleChildren(CallerControllerPtr caller);
    virtual std::list<Context*> getVisibleChildren();
    bool isMapped();
    std::list<Context*>  getMappedChildren(CallerControllerPtr caller);
    std::list<Context*>  getMappedChildren();
	
    AgString getName();
    AgString getDescription();
   
	void setDescription(const AgString & description);
    Context* getParent();
    bool hasParent(Context *parentContext);
    Context* getRoot();
    Context* get(const AgString & contextPath, CallerControllerPtr caller);
    Context* get(const AgString & contextName);
	PermissionsPtr getPermissions();

    void removeVariableDefinition(VariableDefinitionPtr def);
    void removeFunctionDefinition(FunctionDefinitionPtr def);
    void removeEventDefinition(EventDefinitionPtr def);

    void setName(const AgString &name);

    void setParent(Context* parent);

    bool isChildrenSortingEnabled();

    bool isChildrenConcurrencyEnabled();

    bool checkPermissions(PermissionsPtr needPermissions, CallerControllerPtr caller, Context* accessedContext);
    void addChild(Context* child);
    void addChild(Context* child, boost::optional<int>  index);
    void removeFromParent();
    void destroy(bool moving);

    void removeChild(Context* child);
    void removeChild(const AgString & name);


    void destroyChild(Context* child, bool moving);
    void destroyChild(const AgString & name, bool moving);
    void removeAllChildren();

    void move(Context * newParent, const AgString & newName);

    Context* getChild(const AgString & name, CallerControllerPtr caller);
    Context* getChild(const AgString & name);

    AgString getPath();
	
    virtual bool addEventListener(const AgString & name, ContextEventListenerPtr listener);
    virtual bool addEventListener(const AgString & name, ContextEventListenerPtr listener, bool weak);
    virtual bool removeEventListener(const AgString & name, ContextEventListenerPtr listener);
    std::list<VariableDefinitionPtr> getVariableDefinitions(CallerControllerPtr caller);
    std::list<VariableDefinitionPtr> getVariableDefinitions(CallerControllerPtr caller, bool includeHidden);
    std::list<VariableDefinitionPtr> getVariableDefinitions();
    std::list<VariableDefinitionPtr> getVariableDefinitions(CallerControllerPtr caller, const AgString & group);
    std::list<VariableDefinitionPtr> getVariableDefinitions(const AgString & group);
    PermissionCheckerPtr getPermissionChecker();
    PermissionsPtr getChildrenViewPermissions();
    ContextManager* getContextManager();

    bool isSetupComplete();
 
	bool isStarted();
    bool isInitializedInfo();
    bool isInitializedChildren();
    bool isInitializedVariables();
    bool isInitializedFunctions();
    bool isInitializedEvents();
	
	std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller);
	std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller, bool includeHidden);
	std::list< FunctionDefinitionPtr >  getFunctionDefinitions();
	std::list< FunctionDefinitionPtr >  getFunctionDefinitions(CallerControllerPtr caller, const AgString & group);
	std::list< FunctionDefinitionPtr >  getFunctionDefinitions(const AgString & group);

	boost::shared_mutex getChildrenLock();

    AgString getType();
 
	bool isPermissionCheckingEnabled();
    AgString getIconId();
    boost::optional<int> getIndex();
	
    AgString getGroup();
    virtual AgString  getLocalRoot();
    bool isProxy();
    bool isDistributed();
	
    virtual AgString getRemoteRoot();
    AgString getRemotePath();
   
    AgString getRemotePrimaryRoot();
    void setType(const AgString & type);

    void setIndex(int  index);
    void setGroup(const AgString & group);
	std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller);
	std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller, bool includeHidden);
	std::list< EventDefinitionPtr >  getEventDefinitions();
	std::list< EventDefinitionPtr >  getEventDefinitions(CallerControllerPtr caller, const AgString & group);
	std::list< EventDefinitionPtr >  getEventDefinitions(const AgString & group);
	ActionDefinitionPtr getActionDefinition(const AgString & name);
	ActionDefinitionPtr getActionDefinition(const AgString & name, CallerControllerPtr caller);
	ActionDefinitionPtr getDefaultActionDefinition(CallerControllerPtr caller);
	std::list< ActionDefinitionPtr >  getActionDefinitions(CallerControllerPtr caller);
	void addActionDefinition(ActionDefinitionPtr def);
	std::list< ActionDefinitionPtr >  getActionDefinitions(CallerControllerPtr caller, bool includeHidden);
	std::list< ActionDefinitionPtr >  getActionDefinitions();
	void removeActionDefinition(const AgString & name);

	DataTablePtr executeDefaultGetter(const AgString & name, CallerControllerPtr caller);
	DataTablePtr executeDefaultGetter(const AgString & name, CallerControllerPtr caller, bool check);
	DataTablePtr executeDefaultGetter(const AgString & name, CallerControllerPtr caller, bool check, bool createDefault);

    int hashCode();
    bool equals(AbstractContext* obj);
	DataTablePtr getVariable(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request);
	DataTablePtr getVariable(const AgString & name, CallerControllerPtr caller);
	DataTablePtr getVariable(const AgString & name);

    AgObjectPtr getVariableObject(const AgString & name, CallerControllerPtr caller);

    DataTablePtr getDefaultValue(VariableDefinitionPtr def);
    void executeDefaultSetter(const AgString & name, CallerControllerPtr caller, DataTablePtr value) ;
    void executeDefaultSetter(VariableDefinitionPtr def, CallerControllerPtr caller, DataTablePtr value) ;

    void setVariable(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value) ;
    void setVariable(const AgString & name, CallerControllerPtr caller, DataTablePtr value) ;
    void setVariable(const AgString & name, DataTablePtr value) ;
    void setVariable(const AgString & name, CallerControllerPtr caller, std::list<AgObjectPtr> value) ;
    void setVariable(const AgString & name, std::list<AgObjectPtr> value) ;

    bool setVariableField(const AgString & variable, const AgString & field, AgObjectPtr value, CallerControllerPtr cc) ;
    bool setVariableField(const AgString & variable, const AgString & field, int record, AgObjectPtr value, CallerControllerPtr cc) ;
    void setVariableField(const AgString & variable, const AgString & field, AgObjectPtr value, const AgString & compareField, AgObjectPtr compareValue, CallerControllerPtr cc) ;
    void addVariableRecord(const AgString & variable, CallerControllerPtr cc, DataRecordPtr record) ;
    void addVariableRecord(const AgString & variable, CallerControllerPtr cc, std::list<AgObjectPtr> recordData) ;
    void removeVariableRecords(const AgString & variable, CallerControllerPtr cc, const AgString & field, AgObjectPtr value) ;

    DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
    DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, DataTablePtr parameters) ;
    DataTablePtr callFunction(const AgString & name, DataTablePtr parameters) ;
    DataTablePtr callFunction(const AgString & name) ;
    DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller) ;
    DataTablePtr callFunction(const AgString & name, CallerControllerPtr caller, std::list<AgObjectPtr> parameters) ;
    DataTablePtr callFunction(const AgString & name, std::list<AgObjectPtr> parameters) ;

    void addVariableDefinition(VariableDefinitionPtr def);
    void removeVariableDefinition(const AgString & name);

    void addFunctionDefinition(FunctionDefinitionPtr def);

	void removeFunctionDefinition(const AgString & name);

    void addEventDefinition(EventDefinitionPtr def);

	void removeEventDefinition(const AgString & name);


	VariableDataPtr getVariableData(const AgString & name);
	VariableDefinitionPtr getVariableDefinition(const AgString & name);
    VariableDefinitionPtr getVariableDefinition(const AgString & name, CallerControllerPtr caller);
	FunctionDataPtr getFunctionData(const AgString & name);
    FunctionDefinitionPtr getFunctionDefinition(const AgString & name);
	FunctionDefinitionPtr getFunctionDefinition(const AgString & name, CallerControllerPtr caller);
	EventDataPtr getEventData(const AgString & name);
	EventDefinitionPtr getEventDefinition(const AgString & name);
	EventDefinitionPtr getEventDefinition(const AgString & name, CallerControllerPtr caller);


    EventPtr fireEvent(const AgString & name, int level, CallerControllerPtr caller, FireEventRequestControllerPtr request, PermissionsPtr permissions, DataTablePtr data);
    EventPtr fireEvent(const AgString & name, DataTablePtr data, int level, int64_t  id, AgDatePtr creationtime, int  listener, CallerControllerPtr caller, FireEventRequestControllerPtr request);
    EventPtr fireEvent(const AgString & name, DataTablePtr data);
    EventPtr fireEvent(const AgString & name, CallerControllerPtr caller, DataTablePtr data);
    EventPtr fireEvent(const AgString & name, int level, DataTablePtr data);
    EventPtr fireEvent(const AgString & name, int level, CallerControllerPtr caller, DataTablePtr data);
    EventPtr fireEvent(const AgString & name);
	EventPtr fireEvent(const AgString & name, CallerControllerPtr caller);
    EventPtr fireEvent(const AgString &name, std::list<AgObjectPtr> data);
    EventPtr fireEvent(const AgString &name, const AgString &data);

	std::list<EventPtr>  getEventHistory(const AgString & name);

    AgString toString();
    AgString toDetailedString();
	void accept(ContextVisitorPtr visitor) ;

    DataTablePtr getVvariables(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;

    DataTablePtr getVfunctions(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;

    DataTablePtr getVevents(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;

	DataTablePtr getVactions(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;

    ContextStatusPtr getStatus();
    void setStatus(int status, const AgString & comment);

    void updateVariableStatus(const AgString & variable, VariableStatusPtr status, bool persistent) ;

    VariableStatusPtr getVariableStatus(const AgString & name) ;
    DataTablePtr getVchildren(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;
    DataTablePtr getVinfo(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;

    DataTablePtr callFgetCopyData(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
    DataTablePtr callFcopy(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;
	DataTablePtr callFcopyToChildren(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters) ;

    AbstractContext(const AgString &name);
    virtual ~AbstractContext();

protected:
    void setPermissions(PermissionsPtr permissions);
	void setPermissionChecker(PermissionCheckerPtr permissionChecker);
    void setFireUpdateEvents(bool fireUpdateEvents);
    bool isFireUpdateEvents();
	void setChildrenViewPermissions(PermissionsPtr childrenViewPermissions);
    void setChildrenSortingEnabled(bool childrenSortingEnabled);
	void setValueCheckingEnabled(bool valueCheckingEnabled);
	void setChildrenConcurrencyEnabled(bool childrenConcurrencyEnabled);
	void checkPermissions(PermissionsPtr needPermissions, CallerControllerPtr caller);
	void destroyChildren(bool moving);
    void reorderChild(Context* child, int index);
	void movePrepare(const AgString & oldPath, const AgString & oldName, const AgString & newPath, const AgString & newName) ;
	void moveInternal(const AgString & oldPath, const AgString & oldName, const AgString & newPath, const AgString & newName) ;
	void moveFinalize(const AgString & oldPath, const AgString & oldName, const AgString & newPath, const AgString & newName);
    void setPermissionCheckingEnabled(bool permissionCheckingEnabled);
    void setIconId(const AgString & iconId);
	ActionDefinitionPtr actDefFromDataRecord(DataRecordPtr rec);
	DataTablePtr executeDefaultGetterImpl(VariableDefinitionPtr vd, CallerControllerPtr caller);
    virtual DataTablePtr getVariableImpl(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request) ;
	void variableUpdated(VariableDefinitionPtr def, CallerControllerPtr caller, DataTablePtr value) ;
    void fireUpdatedEvent(VariableDefinitionPtr def, CallerControllerPtr caller, DataTablePtr value);
    void fireChangeEvent(VariableDefinitionPtr def, CallerControllerPtr caller, AgDatePtr timestamp, DataTablePtr value);
    virtual void setupVariables() ;
	void executeDefaultSetterImpl(VariableDefinitionPtr vd, CallerControllerPtr caller, DataTablePtr value);
    virtual bool setVariableImpl(VariableDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr value);
    virtual void setupFunctions();
    virtual DataTablePtr callFunctionImpl(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters);
    void setupEvents();
    void postEvent(EventPtr ev, EventDefinitionPtr ed, CallerControllerPtr caller, FireEventRequestControllerPtr request) ;
    void updateEvent(EventPtr ev, EventDefinitionPtr ed, CallerControllerPtr caller, FireEventRequestControllerPtr request) ;
    EventPtr fireEvent(EventDefinitionPtr ed, DataTablePtr data, int level, boost::optional<int64_t>  id, AgDatePtr creationtime, int  listener, CallerControllerPtr caller, FireEventRequestControllerPtr request, PermissionsPtr permissions);
    EventPtr fireEvent(EventPtr event);
	EventProcessingRulePtr getEventProcessingRule(EventPtr event);
	void processBindings(EventPtr event);
	CallerControllerPtr getEventProcessingCallerController();
    EventDefinitionPtr getChangeEventDefinition();
    AgString encodeFormat(TableFormatPtr format, CallerControllerPtr caller);
    virtual TableFormatPtr decodeFormat(const AgString & source, CallerControllerPtr caller);
    DataRecordPtr varDefToDataRecord(VariableDefinitionPtr vd);
	VariableDefinitionPtr varDefFromDataRecord(DataRecordPtr rec);
	DataRecordPtr funcDefToDataRecord(FunctionDefinitionPtr fd);
	FunctionDefinitionPtr funcDefFromDataRecord(DataRecordPtr rec);
	DataRecordPtr evtDefToDataRecord(EventDefinitionPtr ed);
	EventDefinitionPtr evtDefFromDataRecord(DataRecordPtr rec);
	DataRecordPtr actDefToDataRecord(ActionDefinitionPtr def);
    void executeTasks(std::list< boost::shared_ptr<Callable<int> > >  tasks);
	void enableStatus();
	void fireStatusChanged(int status, const AgString & comment, int oldStatus);
    void enableVariableStatuses(bool persistent);
	DataTablePtr fetchVariableStatuses() ;
	void clearVariableStatuses() ;
    void saveVariableStatuses() ;
	void persistVariableStatuses(DataTablePtr statuses) ;
    DataTablePtr copyTo(FunctionDefinitionPtr def, CallerControllerPtr caller, RequestControllerPtr request, DataTablePtr parameters, std::list<Context*> &children);

};

namespace AbstractContextStrings
{
    static const AgString V_INFO = "info";
    static const AgString IMPLEMENTATION_METHOD_PREFIX = "callF";
    static const AgString SETTER_METHOD_PREFIX = "setV";
    static const AgString GETTER_METHOD_PREFIX = "getV";

    static const AgString V_CHILDREN= "children";
    static const AgString V_VARIABLES= "variables";
    static const AgString V_FUNCTIONS= "functions";
    static const AgString V_EVENTS= "events";
    static const AgString V_ACTIONS= "actions";
    static const AgString V_VARIABLE_STATUSES= "variableStatuses";
    static const AgString F_GET_COPY_DATA= "getCopyData";
    static const AgString F_COPY= "copy";
    static const AgString F_COPY_TO_CHILDREN= "copyToChildren";
    static const AgString E_INFO= "info";
    static const AgString E_UPDATED= "updated";
    static const AgString E_CHANGE= "change";
    static const AgString E_DESTROYED= "destroyed";
    static const AgString E_INFO_CHANGED= "infoChanged";
    static const AgString E_VARIABLE_ADDED= "variableAdded";
    static const AgString E_VARIABLE_REMOVED= "variableRemoved";
    static const AgString E_FUNCTION_ADDED= "functionAdded";
    static const AgString E_FUNCTION_REMOVED= "functionRemoved";
    static const AgString E_EVENT_ADDED= "eventAdded";
    static const AgString E_EVENT_REMOVED= "eventRemoved";
    static const AgString E_ACTION_ADDED= "actionAdded";
    static const AgString E_ACTION_REMOVED= "actionRemoved";
    static const AgString E_ACTION_STATE_CHANGED= "actionStateChanged";
    static const AgString E_CHILD_REMOVED= "childRemoved";
    static const AgString E_CHILD_ADDED= "childAdded";
    static const AgString E_VARIABLE_STATUS_CHANGED= "variableStatusChanged";
    static const AgString VF_INFO_DESCRIPTION= "description";
    static const AgString VF_INFO_TYPE= "type";
    static const AgString VF_INFO_GROUP= "group";
    static const AgString VF_INFO_ICON= "icon";
    static const AgString VF_INFO_LOCAL_ROOT= "localRoot";
    static const AgString VF_INFO_PEER_ROOT= "peerRoot";
    static const AgString VF_INFO_PEER_PRIMARY_ROOT= "peerPrimaryRoot";
    static const AgString VF_INFO_REMOTE_ROOT= "remoteRoot";
    static const AgString VF_INFO_REMOTE_PATH= "remotePath";
    static const AgString VF_INFO_REMOTE_PRIMARY_ROOT= "remotePrimaryRoot";
    static const AgString VF_INFO_MAPPED= "mapped";
    static const AgString VF_CHILDREN_NAME= "name";
    static const AgString VF_VARIABLE_STATUSES_COMMENT= "comment";
    static const AgString VF_VARIABLE_STATUSES_STATUS= "status";
    static const AgString VF_VARIABLE_STATUSES_NAME= "name";
    static const AgString FIF_COPY_DATA_RECIPIENTS= "recipients";
    static const AgString FIF_COPY_DATA_GROUP= "group";
    static const AgString FOF_COPY_DATA_NAME= "name";
    static const AgString FOF_COPY_DATA_DESCRIPTION= "description";
    static const AgString FOF_COPY_DATA_REPLICATE= "replicate";
    static const AgString FOF_COPY_DATA_FIELDS= "fields";
    static const AgString FOF_COPY_DATA_VALUE= "value";
    static const AgString FIF_REPLICATE_FIELDS_NAME= "name";
    static const AgString FIF_REPLICATE_FIELDS_DESCRIPTION= "description";
    static const AgString FIF_REPLICATE_FIELDS_REPLICATE= "replicate";
    static const AgString FIF_COPY_DATA_RECIPIENTS_RECIPIENT= "recipient";
    static const AgString EF_INFO_INFO= "info";
    static const AgString EF_EVENT_REMOVED_NAME= "name";
    static const AgString EF_FUNCTION_REMOVED_NAME= "name";
    static const AgString EF_VARIABLE_REMOVED_NAME= "name";
    static const AgString EF_ACTION_REMOVED_NAME= "name";
    static const AgString EF_CHILD_REMOVED_CHILD= "child";
    static const AgString EF_CHILD_ADDED_CHILD= "child";
    static const AgString FIELD_REPLICATE_CONTEXT= "context";
    static const AgString FIELD_REPLICATE_VARIABLE= "variable";
    static const AgString FIELD_REPLICATE_SUCCESSFUL= "successful";
    static const AgString FIELD_REPLICATE_ERRORS= "errors";
    static const AgString EF_UPDATED_VARIABLE= "variable";
    static const AgString EF_UPDATED_VALUE= "value";
    static const AgString EF_UPDATED_USER= "user";
    static const AgString EF_CHANGE_VARIABLE= "variable";
    static const AgString EF_CHANGE_VALUE= "value";
    static const AgString EF_CHANGE_DATA= "data";
    static const AgString FIELD_VD_NAME= "name";
    static const AgString FIELD_VD_FORMAT= "format";
    static const AgString FIELD_VD_DESCRIPTION= "description";
    static const AgString FIELD_VD_READABLE= "readable";
    static const AgString FIELD_VD_WRITABLE= "writable";
    static const AgString FIELD_VD_HELP= "help";
    static const AgString FIELD_VD_GROUP= "group";
    static const AgString FIELD_VD_ICON_ID= "iconId";
    static const AgString FIELD_VD_HELP_ID= "helpId";
    static const AgString FIELD_VD_CACHE_TIME= "cacheTime";
    static const AgString FIELD_FD_NAME= "name";
    static const AgString FIELD_FD_INPUTFORMAT= "inputformat";
    static const AgString FIELD_FD_OUTPUTFORMAT= "outputformat";
    static const AgString FIELD_FD_DESCRIPTION= "description";
    static const AgString FIELD_FD_HELP= "help";
    static const AgString FIELD_FD_GROUP= "group";
    static const AgString FIELD_FD_ICON_ID= "iconId";
    static const AgString FIELD_ED_NAME= "name";
    static const AgString FIELD_ED_FORMAT= "format";
    static const AgString FIELD_ED_DESCRIPTION= "description";
    static const AgString FIELD_ED_HELP= "help";
    static const AgString FIELD_ED_LEVEL= "level";
    static const AgString FIELD_ED_GROUP= "group";
    static const AgString FIELD_ED_ICON_ID= "iconId";

    static const AgString CALLER_CONTROLLER_PROPERTY_DEBUG= "debug";
    static const AgString CALLER_CONTROLLER_PROPERTY_NO_UPDATED_EVENTS= "no_updated_events";
    static const AgString CALLER_CONTROLLER_PROPERTY_NO_CHANGE_EVENTS= "no_change_events";
}
#endif
