Database Storage Engine Project M2 API

= About the milestone=

This milestone includes building the API for the database system.

We will release a preview of the API before the 1st of June in order to have plenty of time for the community to comment.

= Todo=
 * Develop basic API and post it on the forums (done)
 * Explore comments on the basic API (done)
 * Complete the API (done)
 * Make sure it is possible to add/have support for current en future metadata related to single questions & whole surveys . (done)
 * Add methods to add and remove observers (done)

= API (updated 08-11)=

Below you find the API.

Survey
A survey is a collection of sections. Surveys can have various metadata like a respondent e-mail adres, a name, ...

assoc(key => value) listMetadata
Lists all metadata belonging to the survey.

void addMetadata($key, $value)
Adds the given metadata to the survey.

void updateMetadata($key, $newValue)
Updates the given metadata with the new value.

void removeMetaData($key)
Removes the given metadata from the survey.

void '''set($key, $value)
Magic set method for the attributes.

mixed '''get
Magic get method for the attributes.

Section
A section is a part of a survey, grouping questions together. Using conditions it is possible to loop or branch over sections.

assoc(key => value) listMetadata
Lists all metadata belonging to the section.

void addMetadata($key, $value)
Adds the given metadata to the section.

void updateMetadata($key, $newValue)
Updates the given metadata with the new value.

void removeMetaData($key)
Removes the given metadata from the section.

void '''set($key, $value)
Magic set method for the attributes.

mixed '''get
Magic get method for the attributes.

QuestionType
A survey can have various types of questions, ranging from string & integers up to fileinput and matrix types. Question types will have policies which will be implemented as special question types.

string renderForAnswer(DbseQuestion $question, array $vars, $parentTemplate)
Returns the answer template for the question type. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

string renderForOptions(DbseQuestion $question, array $vars, $parentTemplate)
Returns the options template for the question type which is used for configuring the question. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

mixed listSettings
Returns a list of all settings and their types.

mixed getFields(DbseQuestion $question)
Returns a list of all fields required by this questiontype and their types.

bool checkResponse(DbseQuestion $question, $value)
Returns true if the given value is a valid response to the question.

void setSettting(DbseQuestion $question, $key, $value)
Sets the setting with the given key to the given value. Multiple settings can be set at once by passing a hashmap mapping keys to values as the second argument.

mixed getSettings(DbseQuestion $question)
Returns a list of all settings and their values.

QuestionTypePolicy
A question type policy is a helper class which implements specific question type behavior.

QuestionTypePolicy will have subclasses: basic question types like IntegerQuestionType, StringQuestionType, DateQuestionType ... and structures like MatrixQuestionType, ArrayQuestionType, ...

string renderForAnswer(DbseQuestion $question, array $vars, $parentTemplate)
Returns the answer template for the question type. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

string renderForOptions(DbseQuestion $question, array $vars, $parentTemplate)
Returns the options template for the question type which is used for configuring the question. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

mixed listSettings
Returns a list of all settings and their types.

mixed getFields(DbseQuestion $question)
Returns a list of all fields required by this questiontype and their types.

bool checkResponse(DbseQuestion $question, $value)
Returns true if the given value is a valid response to the question.

void setSettting(DbseQuestion $question, $key, $value)
Sets the setting with the given key to the given value. Multiple settings can be set at once by passing a hashmap mapping keys to values as the second argument.

mixed getSettings(DbseQuestion $question)
Returns a list of all settings and their values.

string getFieldName(DbseQuestion $question, mixed $vars, string $key)
Returns a standardized string name for input fields of a question.

Question
A question is a combination of a string (the question) a QuestionType and possible various options - depending on the type.

assoc(key => value) listMetadata
Lists all metadata belonging to the question.

void addMetadata($key, $value)
Adds the given metadata to the question.

void updateMetadata($key, $newValue)
Updates the given metadata with the new value.

void removeMetaData($key)
Removes the given metadata from the question.

string renderForAnswer(array $vars, $parentTemplate)
Returns the answer template for the question. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

string renderForOptions(array $vars, $parentTemplate)
Returns the options template for the question which is used for configuring the question. The vars variable can be accessed in the template. If parentTemplate is set to false, no parent template is used. If it is set to NULL, the default template is used. Else a template filename should be given.

mixed listSettings
Returns a list of all settings and their types.

mixed getFields
Returns a list of all fields required by this question and their types.

bool checkResponse($value)
Returns true if the given value is a valid response to the question.

void setSettting($key, $value)
Sets the setting with the given key to the given value. Multiple settings can be set at once by passing a hashmap mapping keys to values as the second argument.

mixed getSettings
Returns a list of all settings and their values.

DbseQuestion[] getChildren
Returns a list of all the child questions of this question.

void '''set($key, $value)
Magic set method for the attributes.

mixed '''get
Magic get method for the attributes.

ModelAnswer
A model answer for a closed question.

assoc(key => value) listMetadata
Lists all metadata belonging to the model answer.

void addMetadata($key, $value)
Adds the given metadata to the model answer.

void updateMetadata($key, $newValue)
Updates the given metadata with the new value.

void removeMetaData($key)
Removes the given metadata from the model answer.

void '''set($key, $value)
Magic set method for the attributes.

mixed '''get
Magic get method for the attributes.

Response
A response is a combination of a participant_id, question_id, value, start and end time.

void '''set($key, $value)
Magic set method for the attributes.

mixed '''get
Magic get method for the attributes.

ModelAnswerManagementController
This controller will handle the management of model answers. Model answers should only be edited for closed surveys.

void storeModelAnswer(DbseModelAnswer $model_answer)
Stores the given model answer to the database. If the model answer has no ID, it will be considered a new model answer. In this case ModelAnswer->id will be set to the ID appointed to this model answer. The model answer must have a valid question id.

ModelAnswer[] listModelAnswers($question_id)
Returns all model answers of the given question.

void moveUp($modelAnswerID, $places)
Moves the model answer one place to the front of the question.

void moveDown($modelAnswerID, $places)
Moves the model answer one place to the end of the question.

void reorder(assoc(modelAnswerId => orderNumber))
Changes the order of the given model answers to the given order numbers. O6rders must be unique. When there are clashes, an exception will be thrown (defined later).

ModelAnswer getModelAnswer($modelAnswerID)
Returns the model answer belonging to the given model answer ID.

void removeModelAnswer($modelAnswerID)
Removes the model answer with the given model answer ID.

SurveyManagementController
This controller will handle the management of surveys.

Survey[] listSurveys
Lists all surveys.

void storeSurvey(DbseSurvey $survet )
Stores the given survey to the database. If the survey has no ID, it will be considered a new survey. In this case Survey->id will be set to the ID appointed to this survey.

Survey getSurvey($surveyID)
Returns the wanted survey.

void removeSurvey($surveyID)
Removes survey data and all answers.

void openSurvey($surveyID)
Changes the state of the survey to open. Also generates the database response tables (or updates them if they already existed). The state of the survey should never be changed by any means other than this method or the closeSurvey method.

void closeSurvey($surveyID)
Changes the state of the survey to closed. The state of the survey should never be changed by any means other than this method or the openSurvey method.

string[] listDatabaseEngines
Returns a list containing the engineID's of all installed DBSE engines.

SectionManagementController
This controller will handle the management of sections. Sections should only be edited if their survey is closed.

Section[] listSections($surveyID)
Lists all sections in the given survey.

void storeSection(DbseSection $section)
Stores the given section to the database. If the section has no ID, it will be considered a new section. In this case Section->id will be set to the ID appointed to this section. The section must have a valid survey id.

Section getSection($sectionID)
Returns the wanted section.

void removeSection($sectionID)
Removes section data and all answers.

void moveUp($sectionId, $places)
Moves the section one place to the front of the survey.

void moveDown($sectionId, $places)
Moves the section one place to the end of the survey.

void reorder(assoc(sectionId => orderNumber))
Changes the order of the given sections to the given order numbers. Orders must be unique. When there are clashes, an exception will be thrown (defined later).

DbseSection getPreviousSection($section_id)
Returns the section before the given section.

DbseSection getNextSection($section_id)
Returns the section after the given section.

void notifySurveyCreated($survey_id)
Called on creation of survey.

void notifySurveyRemoved($survey_id)
Called on removal of survey.

void notifySurveyChanged($survey_id)
Called on update of survey.

void notifySectionCreated($section_id)
Called on creation of section.

void notifySectionRemoved($section_id)
Called on removal of section.

void notifySectionChanged($section_id)
Called on update of section.

void notifyQuestionCreated($question_id)
Called on creation of question.

void notifyQuestionRemoved($question_id)
Called on removal of question.

void notifyQuestionChanged($question_id)
Called on update of question.

void notifyResponse(Response $response)
Called on submission of a response.

QuestionManagementController
This controller will handle the management of questions. Questions should only be changed if their survey is closed.

Question[] listQuestions($sectionID)
Lists all questions in the given section.

void storeQuestion(DbseQuestion $question)
Stores the given question to the database. If the question has no ID, it will be considered a new question. In this case Question->id will be set to the ID appointed to this question. The question must have a valid section id.

Question getQuestion($questionID)
Returns the wanted question.

void removeQuestion($questionID)
Removes question data and all answers.

void moveUp($questionID, $places)
Moves the question one place to the front of the section.

void moveDown($questionID, $places)
Moves the question one place to the end of the section.

void reorder(assoc(questionID => orderNumber))
Changes the order of the given questions to the given order numbers. Orders must be unique. When there are clashes, an exception will be thrown (defined later).

DbseQuestion getPreviousQuestion(questionID)
Returns the question before the given question.

DbseQuestion getNextQuestion(questionID)
Returns the question after the given question.

ResponseAccessController
This controller provides methodes to store and retrieve survey answers.

void addResponse($surveyID, $participantID, $questionID, $value, $starttime, $endtime, $iteration=0)
Adds the given answer and metadata for the given question to the answers of the given participant. If there already was an answer to the given question for the given participant, the answer will be overridden. The iteration parameter is used to express this is the answer for the i'th loop. If the given answer value is invalid for the given question, an exception will be thrown.

void finishSurvey($surveyID, $participantID, $endtime)
Marks the survey was finished at the given endtime by the given participant.

Response[] getResponse($surveyID, $participantID, $questionID)
Returns the responses of the given participant to the given question and its metadata. Can be more than one response since there might be multiple iterations.

Response[] getResponsesOfParticipant($surveyID, $participant_id)
Returns a list of all answers by the participant to the survey.

Response[] getResponsesToQuestion($surveyID, $questionID)
Returns all responses to the given question and their metadata.

Response[] getResponses($surveyID)
Returns all responses to the survey.

mixed exportResponses($surveyID)
Returns a double string array containing all response information from the survey.

void dropTables($surveyID, $bCheckOpen = true)
Drops the response tables for the given survey. If bCheckOpen is true, a check will be done to make sure the survey is not open. Else the check will be omitted.

removeAllResponses($surveyID)
Removes all responses from the survey response tables.

boolean hasFinished($surveyID, $participantID)
Returns true if the given participant already finished the survey. Returns false if the participant did not complete the survey.

static ObserverController getInstance
Returns a statical instance to the ObserverController.

void addObserver(DBSEObserver $observer)
Adds an observer to the ObserverController.

void removeObserver(DBSEObserver $observer)
Removes an observer from the ObserverController.

void notifyObservers(callback $function, mixed $parameter)
Notifies all registered observers with the specific function and the given parameters.

Global notes

 * Exceptions will be used for reporting errors. The exceptions thrown by each method will be added later in the development process. For a documentation on the thrown errors, see the code documentation.

= Discussions=

Comments and ideas here please:

Comments from Machaven:
1. All the functions that do not return anything (void)
 * Should functions not return true/false (bool) depending on success or failure?

2. void updateMetaDate(key, value, newValue)
 * Should this be spelled: updateMetaData?
 * Why is the original value required to change the metadata? Are the keys not unique?

3. How are errors handled?
 * Can we trigger some action on error, set logging or retrieve error information?

Comments from Jason:
From May

1. There has been some discussion about the use of the word token to represent each unique participant
 * this may be better expressed using a different word internally. Since survey participants/token recipients will be represented as "users" maybe "userID" would be a better label than tokens - ie instead of "Answer getAnswer(token, questionID)", "Answer getAnswer(userID, questionID)"

2. The AnswerAccess controller, should it also be storing responses?
 * So, there should be an equivalent of "getAnswer", being "putAnswer" (or "saveAnswer")

3. Once answers are being stored, either in a flatfile table, or a normalised one, there will be some kind of unique id for the "collection" of answers, so they can be grouped together.
 * A collection of survey responses, with their unique identifier, become the "sheet of answers" to a particular survey. In the case of a controlled survey - where the user has been specifically invited, so we know who they are, they'll have a unique userID from the users table. In the case of open/anonymous or general public surveys, this unique identifier will have to be something else - where is that reflected in the getAnswers, and where will it be reflected in the putAnswer(s) call?

New June Comments

I've had a thought that the moveUp and moveDown methods should take an option of how many positions to move them. When you have 20 questions in a section, and you want to move your question to the top, moving it up one at a time can be really annoying. Can we have void moveUp(sectionId,positions) so if we want to move something 5 places up in the order, it could have a 5 for the positions? Default, of course, would be 1.

Comments from Hai:

 * Add functions for reordering questions (something that would take an array and/or an assoc. map)
 * Make sure you handle scalability for conditions well. This includes:
 * ability to link survey elements to multiple conditions, each condition linkable to multiple actions.
 * providing functions for various condition actions, such as question hiding, branching etc. (sorry, I know this is extremely vague, I'll try to specify later on)