diff --git a/ccm-cms-types-survey/.svnignore b/ccm-cms-types-survey/.svnignore new file mode 100755 index 000000000..378eac25d --- /dev/null +++ b/ccm-cms-types-survey/.svnignore @@ -0,0 +1 @@ +build diff --git a/ccm-cms-types-survey/application.xml b/ccm-cms-types-survey/application.xml new file mode 100755 index 000000000..b84e7b51f --- /dev/null +++ b/ccm-cms-types-survey/application.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + The Survey Content Type for the Red Hat CCM CMS. In contrast to simplesurvey + application this one is integrated into the cms. So the surveys will be content + items and as such will have all the features of a content item. + + diff --git a/ccm-cms-types-survey/pdl/com/arsdigita/content-types/Survey.pdl b/ccm-cms-types-survey/pdl/com/arsdigita/content-types/Survey.pdl new file mode 100755 index 000000000..8a6104d5b --- /dev/null +++ b/ccm-cms-types-survey/pdl/com/arsdigita/content-types/Survey.pdl @@ -0,0 +1,478 @@ +model com.arsdigita.cms.contenttypes; + +import com.arsdigita.formbuilder.*; + +object type Survey extends ContentPage { + component FormSection[1..1] formSection = join ct_surveys.form_id + to bebop_form_sections.form_section_id; +// Date[0..1] startDate = ct_surveys.start_date DATE; +// Date[0..1] endDate = ct_surveys.end_date DATE; + Boolean[0..1] responsesPublic = ct_surveys.responses_public CHAR(1); + reference key ( ct_surveys.survey_id ); +} + +object type SurveyResponse extends ContentItem { + + Survey[1..1] survey = join ct_surveys_responses.survey_id + to ct_surveys.survey_id; + User[1..1] user = join ct_surveys_responses.user_id + to users.user_id; + Date[1..1] entryDate = ct_surveys_responses.entry_date DATE; + + component Answer[1..n] answers = join ct_surveys_responses.response_id + to ct_surveys_answers.response_id; + + // XXX hack to allow us to filter a data query + BigDecimal[1..1] surveyID = ct_surveys_responses.survey_id INTEGER; + BigDecimal[1..1] userID = ct_surveys_responses.user_id INTEGER; + + reference key (ct_surveys_responses.response_id); +} + +object type SurveyAnswer extends ContentItem{ + + BigDecimal[1..1] id = ct_surveys_answers.answer_id INTEGER; + Component[1..1] label = join ct_surveys_answers.label_id + to bebop_components.component_id; + Component[1..1] widget = join ct_surveys_answers.widget_id + to bebop_components.component_id; + String[0..1] value = ct_surveys_answers.value VARCHAR(4000); + + object key (id); +} + +/* From simplesurvey... + +query GetAnswersForResponse { + BigDecimal answerID; + String attributeString; + String answerValue; + + do { + select ss_answers.answer_id, + ss_answers.response_id, + ss_answers.value, + bebop_components.attribute_string + from ss_answers, bebop_components + where ss_answers.response_id = :responseID + and ss_answers.label_id = bebop_components.component_id + order by ss_answers.response_id, ss_answers.answer_id + } map { + answerID = ss_answers.answer_id; + attributeString = bebop_components.attribute_string; + answerValue = ss_answers.value; + } +} + + +query GetFormLabels { + BigDecimal labelID; + String attributeString; + + do { + select bebop_components.component_id, + bebop_components.attribute_string + from bebop_component_hierarchy, acs_objects, bebop_components, ss_surveys + where bebop_component_hierarchy.container_id = ss_surveys.form_id + and ss_surveys.survey_id = :surveyID + and bebop_component_hierarchy.component_id = + acs_objects.object_id + and acs_objects.default_domain_class = 'com.arsdigita.formbuilder.WidgetLabel' + and bebop_components.component_id = bebop_component_hierarchy.component_id + order by bebop_components.component_id + } map { + labelID = bebop_components.component_id; + attributeString = bebop_components.attribute_string; + } +} + +query GetAnswersToQuestion { + BigDecimal answerID; + String answerValue; + + do { + select ss_answers.answer_id, + ss_answers.value + from ss_answers, ss_responses + where ss_answers.response_id = ss_responses.response_id + and ss_answers.label_id = :labelID + and ss_responses.entry_date > :startDate + and ss_responses.entry_date < :endDate + + } map { + answerID = ss_answers.answer_id; + answerValue = ss_answers.value; + } +} + +query getCorrectAnswerToQuestion { + // This returns one correct answer value corresponding to the question's label + String answerValue; + do { + select value from ss_correct_answers + where label_id = :labelID + } map { + answerValue = value; + } +} + +query getCorrectAnswers { + // This returns all labels to one survey + String answerValue; + BigInteger widgetID; + String parameterName; + String parameterModel; + String domainClass; + + do { + select sca.value, + bc.component_id as widget_id, + bw.parameter_name, + bw.parameter_model, + o.default_domain_class + from bebop_component_hierarchy bch, + bebop_components bc, + bebop_widgets bw, + ss_surveys s, + ss_correct_answers sca, + acs_objects o + where bch.container_id = s.form_id + and sca.widget_id = bch.component_id + and bc.component_id = bch.component_id + and bc.component_id = bw.widget_id + and bc.component_id = o.object_id + and s.survey_id = :surveyID + } map { + widgetID = widget_id; + answerValue = sca.value; + parameterName = bw.parameter_name; + parameterModel = bw.parameter_model; + domainClass = o.default_domain_class; + } + } + +query correctAnswerExists { + Boolean answerExists; + do { + select 1 as answer_exists_p from ss_correct_answers + where label_id = :labelID and widget_id = :widgetID + } map { + answerExists = answer_exists_p; + } +} +data operation insertCorrectAnswer { + do { + insert into ss_correct_answers( label_id, widget_id, value ) + values ( :labelID, :widgetID, :value ) + } +} +data operation updateCorrectAnswer { + do { + update ss_correct_answers set value = :value + where label_id = :labelID and widget_id = :widgetID + } +} + +data operation updateAnswerValue { + do { + update bebop_options set answer_value = :answerValue + where option_id = :optionID + } +} +query GetAllAnswers { + BigDecimal responseID; + BigDecimal labelID; + String answerValue; + + do { + select ss_answers.value, + ss_answers.response_id, + ss_answers.label_id + from ss_answers + where ss_answers.response_id in (select response_id from ss_responses + where survey_id = :surveyID) + order by ss_answers.response_id, ss_answers.label_id + } map { + answerValue = ss_answers.value; + responseID = ss_answers.response_id; + labelID = ss_answers.label_id; + } +} + +query GetWidgetClassAfterLabel { + String widgetClass; + + do { + select acs_objects.default_domain_class + from bebop_component_hierarchy, acs_objects + where bebop_component_hierarchy.component_id = acs_objects.object_id + and bebop_component_hierarchy.container_id = (select container_id from bebop_component_hierarchy + where component_id = :labelID) + and bebop_component_hierarchy.order_number = (select order_number + 1 from + bebop_component_hierarchy where component_id = :labelID) + } map { + widgetClass = acs_objects.default_domain_class; + } +} + +query GetOneAnswerQuestionStatistics { + String value; + BigDecimal numberOfAnswers; + + do { + select count(ss_answers.answer_id) number_of_answers, + ss_answers.value + from ss_answers + where ss_answers.label_id = :labelID + group by ss_answers.value + } map { + value = ss_answers.value; + numberOfAnswers = number_of_answers; + } +} + +query getAnswerOption { + String questionText; + String answerText; + BigDecimal answerValue; + BigDecimal optionID; + + do { + select h2.component_id as option_id, + op.label as answer_text, + op.answer_value, + bc.attribute_string as question_text + from bebop_component_hierarchy h1, + bebop_component_hierarchy h2, + bebop_component_hierarchy h3, + bebop_components bc, + bebop_options op, + acs_objects o2 + where h2.container_id = h1.component_id + and h2.component_id = op.option_id + and bc.component_id = h3.component_id + and o2.object_id = h3.component_id + and h3.order_number = h1.order_number - 1 + and h3.container_id = h1.container_id + and h2.component_id = op.option_id + and op.option_id = :optionID + and o2.default_domain_class = 'com.arsdigita.formbuilder.WidgetLabel' + } map { + optionID = option_id; + answerValue = answer_value; + questionText = question_text; + answerText = answer_text; + } +} +query getSurveyStatistics { + BigDecimal score; + BigDecimal surveyNumber; + BigDecimal surveyPercentage; + + do { + select score, + survey_number, + round((survey_number/total)*100) as survey_percentage + from ( select r1.score, + count(*) survey_number, + r2.total + from ss_responses r1, + (select count(*) as total from ss_responses r3 + where r3.survey_id = :surveyID) r2 + where r1.survey_id = :surveyID + group by r1.score, r2.total) s + } map { + surveyNumber = survey_number; + score = score; + surveyPercentage = survey_percentage; + } +} + +query GetTotalNumberOfAnswers { + BigDecimal numberOfAnswers; + + do { + select count(*) number_of_answers + from ss_answers where label_id = :labelID + } map { + numberOfAnswers = number_of_answers; + } +} + +query getAnswerOptions { +// Returns all singleselect/select multiple questions with one row per possible answer +// for the selected survey. Yes, we are assuming that the label is always directly before the widget on the form. + String questionText; + String answerText; + BigDecimal optionID; + BigDecimal labelID; + BigDecimal widgetID; + BigDecimal answerValue; + do { + select h1.component_id as widget_id, + h2.component_id as option_id, + bc.attribute_string as label_text, + bc.component_id as label_id, + op.label as option_text, + op.answer_value + from bebop_component_hierarchy h1, + bebop_component_hierarchy h2, + bebop_component_hierarchy h3, + bebop_options op, + bebop_components bc, + ss_surveys s, + acs_objects o2 + where h2.container_id = h1.component_id + and h1.container_id = s.form_id + and bc.component_id = h3.component_id + and o2.object_id = h3.component_id + and h2.component_id = op.option_id + and h3.order_number = h1.order_number - 1 + and h3.container_id = h1.container_id + and o2.default_domain_class = 'com.arsdigita.formbuilder.WidgetLabel' and s.survey_id = :surveyID + order by widget_id + } map { + widgetID = widget_id; + optionID = option_id; + questionText = label_text; + answerText = option_text; + labelID = label_id; + answerValue = answer_value; + } +} + + +data operation saveScore { + // Saves the score of the completed survey (only relevant for knowledge test surveys) + do { + update ss_responses set score =( + select count(*) from + ss_answers a, + ss_correct_answers ca + where a.widget_id = ca.widget_id + and a.value = ca.value + and a.response_id = :responseID + ) where response_id = :responseID + } +} + +data operation saveAssessmentScore { +// Saves the score of the completed survey (only relevant for personal assessment surveys) + do { + update ss_responses set score = + (select s.sum_points/t.total + from (select count(*) as total from ss_answers where response_id=:responseID) t, + (select sum(a.value) as sum_points + from bebop_options bo, + ss_surveys s, + ss_answers a, + bebop_component_hierarchy h1, + bebop_component_hierarchy h2 + where s.form_id = h1.container_id + and h2.container_id = h1.component_id + and h2.component_id = bo.option_id + and bo.label = a.value + and a.response_id = :responseID) s) + where response_id = :responseID + } +} +query getResponseResults{ +// Returns the user's answer vs the correct answer for a survey response of a knowledge test survey + BigDecimal questionNumber; + BigDecimal answerID; + String userAnswer; + String correctAnswer; + do { + select rownum as question_number, + a.answer_id, + a.value as user_answer, + ca.value as correct_answer + from ss_answers a, + ss_correct_answers ca + where a.widget_id(+) = ca.widget_id + and a.response_id = :responseID + order by a.widget_id + } map { + questionNumber = question_number; + answerID = a.answer_id; + userAnswer = a.user_answer; + correctAnswer = ca.correct_answer; + } +} + +query getAssessmentResults { + // Returns the score of a user based on a personal assessment kind of survey (i.e. average answer option value) + BigDecimal answerCount; // The number of answers for which the user received this point value + BigDecimal answerValue; // THe point value for this answer + do { select count(*) as answer_count, + bo.answer_value + from bebop_options bo, + ss_surveys s, + ss_answers a, + bebop_component_hierarchy h1, + bebop_component_hierarchy h2 + where s.form_id = h1.container_id + and h2.container_id = h1.component_id + and h2.component_id = bo.option_id + and bo.label = a.value + and a.response_id = :responseID + group by bo.answer_value + } map { + answerCount = answer_count; + answerValue = answer_value; + } +} + +query getUserScore { +// Returns the user's score given a responseID for a knowledge test kind of survey + BigDecimal userScore; + BigDecimal maxScore; + do { select max(r.score) as user_score, + count(value) as max_score + from ss_responses r, + ss_correct_answers sca, + bebop_component_hierarchy bch, + bebop_components bc, + bebop_widgets bw, + ss_surveys s + where bch.container_id = s.form_id + and sca.widget_id = bch.component_id + and bc.component_id = bch.component_id + and bc.component_id = bw.widget_id + and s.survey_id = r.survey_id + and r.response_id = :responseID + } map { + userScore = user_score; + maxScore = max_score; + } +} + +query questionsAnswered { + Boolean questionsAnswered; + + do { + select decode(count(*),0,0,1) as questions_answered_p + from ss_answers a + where a.response_id = :responseID + } map { + questionsAnswered = questions_answered_p; + } +} + +query getAllUsersScore { +// Returns the number of users that achieved each score for this +// particular survey + BigDecimal userCount; + BigDecimal surveyScore; + do { select count(response_id) as user_count, r.score + from ss_responses r + where r.survey_id = :surveyID + group by score + } map { + userCount = user_count; + surveyScore = r.score; + } +} + +*/ + diff --git a/ccm-cms-types-survey/sql/ccm-cms-types-survey/postgres-create.sql b/ccm-cms-types-survey/sql/ccm-cms-types-survey/postgres-create.sql new file mode 100644 index 000000000..a733590e2 --- /dev/null +++ b/ccm-cms-types-survey/sql/ccm-cms-types-survey/postgres-create.sql @@ -0,0 +1,3 @@ +begin; +\i ddl/postgres/create.sql +end; \ No newline at end of file diff --git a/ccm-cms-types-survey/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Survey.xml b/ccm-cms-types-survey/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Survey.xml new file mode 100644 index 000000000..68c0bf50b --- /dev/null +++ b/ccm-cms-types-survey/src/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Survey.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + diff --git a/ccm-cms-types-survey/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/Survey.xml b/ccm-cms-types-survey/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/Survey.xml new file mode 100644 index 000000000..d2e47b103 --- /dev/null +++ b/ccm-cms-types-survey/src/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/Survey.xml @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/ccm-cms-types-survey/src/ccm-cms-types-survey.config b/ccm-cms-types-survey/src/ccm-cms-types-survey.config new file mode 100755 index 000000000..369521b94 --- /dev/null +++ b/ccm-cms-types-survey/src/ccm-cms-types-survey.config @@ -0,0 +1,7 @@ + + + + + diff --git a/ccm-cms-types-survey/src/ccm-cms-types-survey.load b/ccm-cms-types-survey/src/ccm-cms-types-survey.load new file mode 100755 index 000000000..fd406540b --- /dev/null +++ b/ccm-cms-types-survey/src/ccm-cms-types-survey.load @@ -0,0 +1,18 @@ + + + +
+
+ + + +
+
+
+ + + + + + + diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/Survey.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/Survey.java new file mode 100755 index 000000000..e66735cb3 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/Survey.java @@ -0,0 +1,206 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.ContentPage; +import com.arsdigita.cms.ContentType; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.persistence.DataCollection; +import java.math.BigDecimal; +import com.arsdigita.domain.DataObjectNotFoundException; + +import com.arsdigita.formbuilder.PersistentForm; + + +import com.arsdigita.util.Assert; + +/** + * A survey content type that represents a survey. This is + * based on the simplesurvey application. + * + * @author Sören Bernstein + * + */ +public class Survey extends ContentPage { + + /** PDL property name for formSection */ + public static final String FORM_SECTION = "formSection"; + /** PDL property name for startDate */ +// public static final String START_DATE = "startDate"; + /** PDL property name for endDate */ +// public static final String END_DATE = "endDate"; + /** PDL property name for responsesPublic */ + public static final String RESPONSES_PUBLIC = "responsesPublic"; + + /** Data object type for this domain object */ + public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.simplesurvey.Survey"; + + /** + * Default constructor. This creates a new (empty) Survey. + **/ + public Survey() { + this(BASE_DATA_OBJECT_TYPE); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id and + * Address.BASE_DATA_OBJECT_TYPE. + * + * @param id The id for the retrieved + * DataObject. + **/ + public Survey(BigDecimal id) throws DataObjectNotFoundException { + this(new OID(BASE_DATA_OBJECT_TYPE, id)); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id. + * + * @param id The OID for the retrieved + * DataObject. + **/ + public Survey(OID id) throws DataObjectNotFoundException { + super(id); + } + + /** + * Constructor. Retrieves or creates a content item using the + * DataObject argument. + * + * @param obj The DataObject with which to create or + * load a content item + */ + public Survey(DataObject obj) { + super(obj); + } + + /** + * Constructor. Creates a new content item using the given data + * object type. Such items are created as draft versions. + * + * @param type The String data object type of the + * item to create + */ + public Survey(String type) { + super(type); + } + + /** + * For new content items, sets the associated content type if it + * has not been already set. + */ + @Override + public void beforeSave() { + super.beforeSave(); + + Assert.exists(getContentType(), ContentType.class); + } + + /* accessors *****************************************************/ + public void setForm(PersistentForm persistentForm) { + set(FORM_SECTION, persistentForm); + } + + public PersistentForm getForm() { + return new PersistentForm((DataObject) get(FORM_SECTION)); + } + + /* + public void setStartDate(Date startDate) { + set(START_DATE, startDate); + } + + public Date getStartDate() { + return (Date)get(START_DATE); + } + + public void setEndDate(Date endDate) { + set(END_DATE, endDate); + } + + public Date getEndDate() { + return (Date)get(END_DATE); + } + */ + + public boolean responsesArePublic() { + return ((Boolean) get(RESPONSES_PUBLIC)).booleanValue(); + } + + public void setResponsesPublic(Boolean responsesPublic) { + set(RESPONSES_PUBLIC, responsesPublic); + } + + /* Class methods *********************************************************/ + + public static Survey retrieve(BigDecimal id) + throws DataObjectNotFoundException { + + Survey survey = new Survey(id); + + return survey; + } + + public static Survey retrieve(DataObject obj) { + Survey survey = new Survey(obj); + + return survey; + } +/* + public SurveyResponseCollection getResponses() { + return SurveyResponse.retrieveBySurvey(this); + } + + public SurveyResponseCollection getUserResponses(User user) { + return SurveyResponse.retrieveBySurvey(this, user); + } + + public boolean hasUserResponded(User user) { + SurveyResponseCollection responses = getUserResponses(user); + + if (responses.next()) { + responses.close(); + return true; + } + return false; + } +*/ + + /* + public DataQuery getLabelDataQuery() { + String queryName = "com.arsdigita.simplesurvey.GetFormLabels"; + DataQuery dataQuery = + SessionManager.getSession().retrieveQuery(queryName); + dataQuery.setParameter("surveyID", getID()); + + return dataQuery; + } + + public boolean isLive() { + Date currentDate = new Date(); + + return getStartDate().compareTo(currentDate) < 0 && + getEndDate().compareTo(currentDate) > 0; + } + */ + /* + * Retrieves most recent survey that isn't completed + */ + public static Survey getMostRecentSurvey() { + DataCollection surveys = SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + surveys.addFilter("startDate <= sysdate and endDate > sysdate"); + surveys.addOrder("startDate desc"); + + Survey survey = null; + if (surveys.next()) { + survey = new Survey(surveys.getDataObject()); + } + surveys.close(); + + return survey; + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyAnswer.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyAnswer.java new file mode 100755 index 000000000..8f3af9c8b --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyAnswer.java @@ -0,0 +1,119 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentType; +import com.arsdigita.db.Sequences; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.formbuilder.PersistentLabel; +import com.arsdigita.formbuilder.PersistentWidget; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.util.Assert; +import java.math.BigDecimal; + +/** + * A SurveyAnswer object represents a response by a user to + * a survey at a certain point in time. A survey response consists + * of a collection of answers to questions in the survey. + * + * @author Sören Bernstein + * + * Based on simplesurvey application + */ +public class SurveyAnswer extends ContentItem { + + /** PDL property name for id */ + public static final String ID = "id"; + /** PDL property name for label */ + public static final String LABEL = "label"; + /** PDL property name for widget */ + public static final String WIDGET = "widget"; + /** PDL property name for value */ + public static final String VALUE = "value"; + /** PDL property name for response */ + public static final String RESPONSE = "response"; + /** Data object type for this domain object */ + public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.cms.contenttypes.SurveyAnswer"; + + /** + * Default constructor. This creates a new (empty) Survey. + **/ + public SurveyAnswer() { + this(BASE_DATA_OBJECT_TYPE); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id and + * Address.BASE_DATA_OBJECT_TYPE. + * + * @param id The id for the retrieved + * DataObject. + **/ + public SurveyAnswer(BigDecimal id) throws DataObjectNotFoundException { + this(new OID(BASE_DATA_OBJECT_TYPE, id)); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id. + * + * @param id The OID for the retrieved + * DataObject. + **/ + public SurveyAnswer(OID oid) throws DataObjectNotFoundException { + super(oid); + } + + /** + * Constructor. Retrieves or creates a content item using the + * DataObject argument. + * + * @param obj The DataObject with which to create or + * load a content item + */ + public SurveyAnswer(DataObject obj) { + super(obj); + } + + /** + * Constructor. Creates a new content item using the given data + * object type. Such items are created as draft versions. + * + * @param type The String data object type of the + * item to create + */ + public SurveyAnswer(String type) { + super(type); + } + + /* accessors *****************************************************/ + public BigDecimal getID() { + return (BigDecimal) get(ID); + } + +/* Class methods ********/ + public static SurveyAnswer create(PersistentLabel label, + PersistentWidget widget, + String value) { + SurveyAnswer answer = new SurveyAnswer(); + answer.setup(label, widget, value); + return answer; + } + + protected void setup(PersistentLabel label, + PersistentWidget widget, + String value) { + try { + set(ID, Sequences.getNextValue("ss_answers_seq")); + } catch (java.sql.SQLException e) { + throw new com.arsdigita.util.UncheckedWrapperException(e); + } + set(LABEL, label); + set(WIDGET, widget); + set(VALUE, value); + } + +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyInitializer.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyInitializer.java new file mode 100755 index 000000000..c834e88d0 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyInitializer.java @@ -0,0 +1,31 @@ +package com.arsdigita.cms.contenttypes; + +import org.apache.log4j.Logger; + +/** + * + * @author Sören Bernstein; + */ +public class SurveyInitializer extends ContentTypeInitializer { + + public final static String versionId = + "$Id: SurveyInitializer.java $" + + "$Author: quasi $" + + "$DateTime: 2010/02/18 $"; + private static final Logger s_log = Logger.getLogger(SurveyInitializer.class); + + public SurveyInitializer() { + super("ccm-cms-types-survey.pdl.mf", + Survey.BASE_DATA_OBJECT_TYPE); + } + + public String[] getStylesheets() { + return new String[]{ + "/static/content-types/com/arsdigita/cms/contenttypes/Survey.xsl" + }; + } + + public String getTraversalXML() { + return "/WEB-INF/traversal-adapters/com/arsdigita/cms/contenttypes/Survey.xml"; + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyLoader.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyLoader.java new file mode 100755 index 000000000..668eeb57d --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyLoader.java @@ -0,0 +1,23 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.contenttypes.AbstractContentTypeLoader; + +/** + * Loader. + * + * @author Sören Bernstein + */ +public class SurveyLoader extends AbstractContentTypeLoader { + + public final static String versionId = + "$Id: SurveyLoader.java $" + + "$Author: quasi $" + + "$DateTime: 2010/02/18 $"; + private static final String[] TYPES = { + "/WEB-INF/content-types/com/arsdigita/cms/contenttypes/Survey.xml" + }; + + public String[] getTypes() { + return TYPES; + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources.properties b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources.properties new file mode 100755 index 000000000..cb2ec50ec --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources.properties @@ -0,0 +1,58 @@ +cms.contenttypes.ui.survey.ui.admin.and=and +cms.contenttypes.ui.survey.ui.admin.add_new_survey=Add new Survey +cms.contenttypes.ui.survey.ui.admin.add_new_poll=Add new Poll +cms.contenttypes.ui.survey.ui.admin.surveys=Surveys +cms.contenttypes.ui.survey.ui.admin.polls=Polls +cms.contenttypes.ui.survey.ui.admin.back_to_question_list=Back to question list +cms.contenttypes.ui.survey.ui.admin.question=Question: +cms.contenttypes.ui.survey.ui.admin.back_to_response_list=Back to response list +cms.contenttypes.ui.survey.ui.admin.name=Name: +cms.contenttypes.ui.survey.ui.admin.description=Description: +cms.contenttypes.ui.survey.ui.admin.start_date=Start Date: +cms.contenttypes.ui.survey.ui.admin.end_date=End Date: +cms.contenttypes.ui.survey.ui.admin.back_to_survey_list=Back to survey list +cms.contenttypes.ui.survey.ui.admin.questions_of_the_survey=Questions of the Survey +cms.contenttypes.ui.survey.ui.admin.responses_to_the_survey=Responses to the Survey +cms.contenttypes.ui.survey.ui.admin.export_response_data=Export Response Data +cms.contenttypes.ui.survey.ui.admin.administration=Administration +cms.contenttypes.ui.survey.ui.admin.active=active +cms.contenttypes.ui.survey.ui.admin.inactive=inactive +cms.contenttypes.ui.survey.ui.admin.view_responses=View Responses +cms.contenttypes.ui.survey.ui.admin.edit_controls=Edit controls +cms.contenttypes.ui.survey.ui.admin.edit_properties=Edit properties +cms.contenttypes.ui.survey.ui.admin.delete=Delete +cms.contenttypes.ui.survey.ui.admin.should_quiz_responses_be_public=Should responses be public? +cms.contenttypes.ui.survey.ui.admin.set_correct_answers=Set correct answers +cms.contenttypes.ui.survey.ui.admin.what_type_of_quiz_is_this= What type of quiz is this? +cms.contenttypes.ui.survey.ui.admin.knowledge_test_quiz=Knowledge Test +cms.contenttypes.ui.survey.ui.admin.personal_assessment_quiz=Personal Assessment +cms.contenttypes.ui.survey.ui.admin.question=Question +cms.contenttypes.ui.survey.ui.admin.answer=Answer +cms.contenttypes.ui.survey.ui.admin.edit_value=Edit Value +cms.contenttypes.ui.survey.ui.admin.current_value=Current Value +cms.contenttypes.ui.survey.ui.admin.submit=Submit +cms.contenttypes.ui.survey.ui.admin.done_editing=Done Editing +cms.contenttypes.ui.survey.ui.admin.set_answer_values=Set answer values + + +cms.contenttypes.ui.survey.ui.Yes=Yes +cms.contenttypes.ui.survey.ui.No=No + +cms.contenttypes.ui.survey.ui.you_have_scored_out_of_a_possible=You have scored {0} out of a possible {1} point(s). +cms.contenttypes.ui.survey.ui.you_have_scored=You have scored +cms.contenttypes.ui.survey.ui.answers_worth=answer(s) worth +cms.contenttypes.ui.survey.ui.view_all_results= View public statistics +cms.contenttypes.ui.survey.ui.points=points +cms.contenttypes.ui.survey.ui.administer=Administer +cms.contenttypes.ui.survey.ui.active_surveys=Active Surveys +cms.contenttypes.ui.survey.ui.active_polls=Active Polls +cms.contenttypes.ui.survey.ui.simple_survey_index_page=Simple Survey Index Page +cms.contenttypes.ui.survey.ui.this_survey_is_not_currently_active=This survey is not currently active +cms.contenttypes.ui.survey.ui.you_have_already_completed_this_survey=You have already completed this survey +cms.contenttypes.ui.survey.ui.thankyou_for_completing_the_survey=Thank you for completing this survey! +cms.contenttypes.ui.survey.ui.question_number=Question Number +cms.contenttypes.ui.survey.ui.user_answer=User Answer +cms.contenttypes.ui.survey.ui.correct_answer=Correct Answer +cms.contenttypes.ui.survey.ui.score=Score +cms.contenttypes.ui.survey.ui.number_of_surveys=Number of Surveys +cms.contenttypes.ui.survey.ui.percentage=Surveys in percent diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_de.properties b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_de.properties new file mode 100755 index 000000000..f9320ff44 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_de.properties @@ -0,0 +1,59 @@ +cms.contenttypes.ui.survey.ui.admin.and=und +cms.contenttypes.ui.survey.ui.admin.add_new_survey=Neue Umfrage hinzuf\u00FCgen +cms.contenttypes.ui.survey.ui.admin.surveys=Umfragens +cms.contenttypes.ui.survey.ui.admin.back_to_question_list=Zur\u00FCck zur Fragenliste +cms.contenttypes.ui.survey.ui.admin.question=Frage: +cms.contenttypes.ui.survey.ui.admin.back_to_response_list=Zur\u00FCck zur Antwortliste +cms.contenttypes.ui.survey.ui.admin.name=Name: +cms.contenttypes.ui.survey.ui.admin.description=Beschreibung: +cms.contenttypes.ui.survey.ui.admin.start_date=Startdatum: +cms.contenttypes.ui.survey.ui.admin.end_date=Enddatum: +cms.contenttypes.ui.survey.ui.admin.back_to_survey_list=Zur\u00FCck zur Umfrageliste +cms.contenttypes.ui.survey.ui.admin.questions_of_the_survey=Fragen der Umfrage +cms.contenttypes.ui.survey.ui.admin.responses_to_the_survey=Antworten der Umfrage +cms.contenttypes.ui.survey.ui.admin.export_response_data=Antworten exportieren +cms.contenttypes.ui.survey.ui.admin.administration=Administration +cms.contenttypes.ui.survey.ui.admin.active=aktiv +cms.contenttypes.ui.survey.ui.admin.inactive=inaktiv +cms.contenttypes.ui.survey.ui.admin.view_responses=Antworten ansehen +cms.contenttypes.ui.survey.ui.admin.edit_controls=Edit controls +cms.contenttypes.ui.survey.ui.admin.edit_properties=Eigenschaften bearbeiten +cms.contenttypes.ui.survey.ui.admin.delete=L\u00F6schen +cms.contenttypes.ui.survey.ui.admin.should_quiz_responses_be_public=Sollen die Antworten \u00F6ffentlich sein? +cms.contenttypes.ui.survey.ui.admin.question=Frage +cms.contenttypes.ui.survey.ui.admin.answer=Antwort +cms.contenttypes.ui.survey.ui.admin.edit_value=Wert bearbeiten +cms.contenttypes.ui.survey.ui.admin.current_value=Aktueller Wert +cms.contenttypes.ui.survey.ui.admin.submit=Absenden +cms.contenttypes.ui.survey.ui.admin.done_editing=Bearbeitung beenden +cms.contenttypes.ui.survey.ui.admin.set_answer_values=Antwortwert setzen + + + +cms.contenttypes.ui.survey.ui.admin.set_correct_answers=Set correct answers +cms.contenttypes.ui.survey.ui.admin.what_type_of_quiz_is_this= What type of quiz is this? +cms.contenttypes.ui.survey.ui.admin.knowledge_test_quiz=Knowledge Test +cms.contenttypes.ui.survey.ui.admin.personal_assessment_quiz=Personal Assessment +cms.contenttypes.ui.survey.ui.you_have_scored_out_of_a_possible=You have scored {0} out of a possible {1} point(s). +cms.contenttypes.ui.survey.ui.you_have_scored=You have scored +cms.contenttypes.ui.survey.ui.answers_worth=answer(s) worth + +cms.contenttypes.ui.survey.ui.Yes=Ja +cms.contenttypes.ui.survey.ui.No=Nein + + +cms.contenttypes.ui.survey.ui.view_all_results= View public statistics +cms.contenttypes.ui.survey.ui.points=points +cms.contenttypes.ui.survey.ui.administer=Administer +cms.contenttypes.ui.survey.ui.active_surveys=Active Surveys +cms.contenttypes.ui.survey.ui.active_polls=Active Polls +cms.contenttypes.ui.survey.ui.simple_survey_index_page=Simple Survey Index Page +cms.contenttypes.ui.survey.ui.this_survey_is_not_currently_active=This survey is not currently active +cms.contenttypes.ui.survey.ui.you_have_already_completed_this_survey=You have already completed this survey +cms.contenttypes.ui.survey.ui.thankyou_for_completing_the_survey=Thank you for completing this survey! +cms.contenttypes.ui.survey.ui.question_number=Question Number +cms.contenttypes.ui.survey.ui.user_answer=User Answer +cms.contenttypes.ui.survey.ui.correct_answer=Correct Answer +cms.contenttypes.ui.survey.ui.score=Score +cms.contenttypes.ui.survey.ui.number_of_surveys=Number of Surveys +cms.contenttypes.ui.survey.ui.percentage=Surveys in percent diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_fr.properties b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_fr.properties new file mode 100755 index 000000000..573405bdd --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResources_fr.properties @@ -0,0 +1,60 @@ +cms.contenttypes.ui.survey.ui.admin.and=et +cms.contenttypes.ui.survey.ui.admin.add_new_survey=Ajouter un nouveau sondage +cms.contenttypes.ui.survey.ui.admin.add_new_poll=Ajouter un nouveau scrutin +cms.contenttypes.ui.survey.ui.admin.surveys=Sondages +cms.contenttypes.ui.survey.ui.admin.polls=Scrutins +cms.contenttypes.ui.survey.ui.admin.back_to_question_list=Retour \u00E0 la liste des questions +cms.contenttypes.ui.survey.ui.admin.question=Question: +cms.contenttypes.ui.survey.ui.admin.back_to_response_list=Retour \u00E0 la liste des r\u00E9ponses +cms.contenttypes.ui.survey.ui.admin.name=Titre: +cms.contenttypes.ui.survey.ui.admin.description=Description: +cms.contenttypes.ui.survey.ui.admin.start_date=Date de d\u00E9marrage: +cms.contenttypes.ui.survey.ui.admin.end_date=Date de fin: +cms.contenttypes.ui.survey.ui.admin.back_to_survey_list=Retour \u00E0 la liste des sondages +cms.contenttypes.ui.survey.ui.admin.questions_of_the_survey=Questions de l'enqu\u00EAte +cms.contenttypes.ui.survey.ui.admin.responses_to_the_survey=Responses de l'enqu\u00EAte +cms.contenttypes.ui.survey.ui.admin.export_response_data=Exporter les r\u00E9ponses +cms.contenttypes.ui.survey.ui.admin.administration=Administration +cms.contenttypes.ui.survey.ui.admin.active=actif +cms.contenttypes.ui.survey.ui.admin.inactive=inactif +cms.contenttypes.ui.survey.ui.admin.view_responses=Voir les r\u00E9ponses +cms.contenttypes.ui.survey.ui.admin.edit_controls=Modifier les contr\u00F4les +cms.contenttypes.ui.survey.ui.admin.edit_properties=Modifier les propri\u00E9t\u00E9s +cms.contenttypes.ui.survey.ui.admin.delete=Effacer +cms.contenttypes.ui.survey.ui.admin.should_quiz_responses_be_public=Est-e que les r\u00E9ponses sont public? +cms.contenttypes.ui.survey.ui.admin.set_correct_answers=Indiquer les bonnes r\u00E9ponses. +cms.contenttypes.ui.survey.ui.admin.what_type_of_quiz_is_this=Quel est le type de ce quiz? +cms.contenttypes.ui.survey.ui.admin.knowledge_test_quiz=Tests de connaissances +cms.contenttypes.ui.survey.ui.admin.personal_assessment_quiz=Evaluation personnelle +cms.contenttypes.ui.survey.ui.admin.question=Question +cms.contenttypes.ui.survey.ui.admin.answer=R\u00E9ponse +cms.contenttypes.ui.survey.ui.admin.edit_value=Modifier la valeur +cms.contenttypes.ui.survey.ui.admin.current_value=Valeur courante +cms.contenttypes.ui.survey.ui.admin.submit=Soumettre +cms.contenttypes.ui.survey.ui.admin.done_editing=Modifications effectu\u00E9es +cms.contenttypes.ui.survey.ui.admin.set_answer_values=Indiquer la valeur des r\u00E9ponses + +cms.contenttypes.ui.survey.ui.Yes=oui +cms.contenttypes.ui.survey.ui.No=Non + + +cms.contenttypes.ui.survey.ui.you_have_scored_out_of_a_possible=Vous avez marqu\u00E9 {0} point(s) sur un total de {1}. +cms.contenttypes.ui.survey.ui.you_have_scored=Vous avez marqu\u00E9 +cms.contenttypes.ui.survey.ui.answers_worth=answer(s) worth +cms.contenttypes.ui.survey.ui.view_all_results=Voir les statistiques publique +cms.contenttypes.ui.survey.ui.points=points +cms.contenttypes.ui.survey.ui.administer=Administrer +cms.contenttypes.ui.survey.ui.active_surveys=Enqu\u00EAtes actives +cms.contenttypes.ui.survey.ui.active_polls=Scrutins actifs +cms.contenttypes.ui.survey.ui.simple_survey_index_page=Sommaire des enqu\u00EAtes actives +cms.contenttypes.ui.survey.ui.this_survey_is_not_currently_active=Cette enqu\u00EAte n'est active actuellement +cms.contenttypes.ui.survey.ui.you_have_already_completed_this_survey=Vous avez d\u00E9j\u00E0 r\u00E9pondu \u00E0 cette enqu\u00EAte +cms.contenttypes.ui.survey.ui.thankyou_for_completing_the_survey=Merci d'avoir r\u00E9pondu \u00E0 cette enqu\u00EAte +cms.contenttypes.ui.survey.ui.question_number=Question Num\u00E9ro +cms.contenttypes.ui.survey.ui.user_answer=R\u00E9ponse de l'utilisateur +cms.contenttypes.ui.survey.ui.correct_answer=Bonne r\u00E9ponse +cms.contenttypes.ui.survey.ui.score=Score +cms.contenttypes.ui.survey.ui.number_of_surveys=Nombre d'enqu\u00EAtes +cms.contenttypes.ui.survey.ui.percentage=Pourcentages sur les enqu\u00EAtes +cms.contenttypes.ui.survey.ui.you_have_already_completed_this_survey=TRANSLATE THIS: You have already completed this survey (cms.contenttypes.ui.survey.ui.you_have_already_completed_this_survey) + diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResponse.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResponse.java new file mode 100755 index 000000000..a58a2f363 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/SurveyResponse.java @@ -0,0 +1,156 @@ +package com.arsdigita.cms.contenttypes; + +import com.arsdigita.cms.ContentItem; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.formbuilder.PersistentLabel; +import com.arsdigita.formbuilder.PersistentWidget; +import com.arsdigita.kernel.User; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.OID; +import com.arsdigita.simplesurvey.Survey; +import java.math.BigDecimal; +import java.util.Date; + +/** + * A SurveyResponse object represents a response by a user to + * a survey at a certain point in time. A survey response consists + * of a collection of answers to questions in the survey. + * + * @author Sören Bernstein + * + * Based on simplesurvey application + */ +public class SurveyResponse extends ContentItem { + + /** PDL property name for survey */ + public static final String SURVEY = "survey"; + /** PDL property name for user */ + public static final String USER = "user"; + /** PDL property name for entryDate */ + public static final String ENTRY_DATE = "entryDate"; + /** PDL property name for answers */ + public static final String ANSWERS = "answers"; + /** Data object type for this domain object */ + public static final String BASE_DATA_OBJECT_TYPE = "com.arsdigita.cms.contenttypes.SurveyResponse"; + + /** + * Default constructor. This creates a new (empty) Survey. + **/ + public SurveyResponse() { + this(BASE_DATA_OBJECT_TYPE); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id and + * Address.BASE_DATA_OBJECT_TYPE. + * + * @param id The id for the retrieved + * DataObject. + **/ + public SurveyResponse(BigDecimal id) throws DataObjectNotFoundException { + this(new OID(BASE_DATA_OBJECT_TYPE, id)); + } + + /** + * Constructor. The contained DataObject is retrieved + * from the persistent storage mechanism with an OID + * specified by id. + * + * @param id The OID for the retrieved + * DataObject. + **/ + protected SurveyResponse(OID oid) throws DataObjectNotFoundException { + super(oid); + } + + /** + * Constructor. Retrieves or creates a content item using the + * DataObject argument. + * + * @param obj The DataObject with which to create or + * load a content item + */ + public SurveyResponse(DataObject obj) { + super(obj); + } + + /** + * Constructor. Creates a new content item using the given data + * object type. Such items are created as draft versions. + * + * @param type The String data object type of the + * item to create + */ + public SurveyResponse(String type) { + super(type); + } + + /* accessors *****************************************************/ + public void addAnswer(PersistentLabel label, PersistentWidget widget, String value) { + + SurveyAnswer answer = SurveyAnswer.create(label, widget, value); + add(ANSWERS, answer); + } + + public Date getEntryDate() { + return (Date) get(ENTRY_DATE); + } + + /* Class methods **********************************************************/ + public static SurveyResponse create(Survey survey, User user) { + SurveyResponse response = new SurveyResponse(); + response.setup(survey, user); + return response; + } + + protected void setup(Survey survey, User user) { + set(ENTRY_DATE, new Date()); + + // XXX hack - see pdl file + set(USER + "ID", user.getID()); + set(SURVEY + "ID", survey.getID()); + } + + public static SurveyResponse retrieve(DataObject obj) { + return new SurveyResponse(obj); + } + + /* + public static SurveyResponseCollection retrieveBySurvey(Survey survey) { + DataCollection responses = + SessionManager.getSession().retrieve(BASE_DATA_OBJECT_TYPE); + + responses.addEqualsFilter(SURVEY + "ID", + survey.getID()); + + return new SurveyResponseCollection(responses); + } + + public static SurveyResponseCollection retrieveBySurvey(Survey survey, User user) { + SurveyResponseCollection responses = retrieveBySurvey(survey); + + responses.addEqualsFilter(USER + "ID", + user.getID()); + + return responses; + } +*/ + + public boolean questionsAnswered() { + + // Returns true of questions have been answered on this response + BigDecimal responseID = this.getID(); +// DataQuery dq = SessionManager.getSession().retrieveQuery("com.arsdigita.simplesurvey.questionsAnswered"); +// dq.setParameter("responseID", responseID); +// dq.next(); +// Boolean questionsAnswered = (Boolean) dq.get(QUESTIONS_ANSWERED); +// dq.close(); +// return questionsAnswered.booleanValue(); + +// HACK: Brauche ich diese Funktion? + return true; + + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyProcessListener.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyProcessListener.java new file mode 100755 index 000000000..a1dc8cdf0 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyProcessListener.java @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.simplesurvey.ui; + + +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; + +import com.arsdigita.formbuilder.PersistentComponent; +import com.arsdigita.formbuilder.PersistentForm; +import com.arsdigita.formbuilder.PersistentLabel; +import com.arsdigita.formbuilder.PersistentWidget; + +import com.arsdigita.kernel.KernelHelper; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.OID; +import java.util.Map; +import java.util.HashMap; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; + +import com.arsdigita.simplesurvey.Survey; +import com.arsdigita.simplesurvey.Response; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.simplesurvey.ui.Question; +import com.arsdigita.bebop.parameters.ParameterData; +import com.arsdigita.persistence.DataAssociationCursor; +import com.arsdigita.persistence.DataOperation; +import com.arsdigita.persistence.SessionManager; +import java.util.Iterator; + +import com.arsdigita.formbuilder.util.FormBuilderUtil; + +import com.arsdigita.kernel.User; + +import java.math.BigDecimal; + +import org.apache.log4j.Logger; + +/** + * The process lister that processes a survey response entered by a user. + * + * @author Peter Marklund + * @version $Id: SurveyProcessListener.java 759 2005-09-02 15:25:32Z sskracic $ + */ +public class SurveyProcessListener + implements FormProcessListener { + + public static final String SURVEY_ID_NAME = "__ss_survey_id__"; + public static final String RESPONSE_ID = "__ss_response_id__"; + + public static final BigDecimal THE_PUBLIC_USER = new BigDecimal(-200); + private static final String KNOWLEDGE_TEST = "knowledge_test"; + protected RequestLocal m_persistentForm = new RequestLocal(); + private RequestLocal m_nameQuestionMap = new RequestLocal(); + private RequestLocal m_response; + + private static org.apache.log4j.Logger s_log = + Logger.getLogger(SurveyProcessListener.class.getName()); + + public SurveyProcessListener(RequestLocal response) { + m_response = response; + } + public SurveyProcessListener() { + m_response = null; + } + + public void process(FormSectionEvent event) { + + FormData formData = event.getFormData(); + PageState ps = event.getPageState(); + + BigDecimal surveyID = (BigDecimal)formData.get(SURVEY_ID_NAME); + BigDecimal responseID = (BigDecimal)formData.get(RESPONSE_ID); + m_response.set(ps, responseID); + + Survey survey = (Survey) FormBuilderUtil.instantiateObjectOneArg(Survey.class.getName(), surveyID); + Response response = null; + try { + response = (Response) DomainObjectFactory.newInstance( new OID(Response.class.getName(), responseID)); + } catch (DataObjectNotFoundException ex) { + // s_log.warn("Can't create this object" + responseID); + } + + //Let's not save the data twice in the case of a double-click + if ( response.questionsAnswered() ) { + return; + } + + m_persistentForm.set(ps, survey.getForm()); + + // Get the responding user + User user = KernelHelper.getCurrentUser(ps.getRequest()); + + // Use the generic user "The Public" if the user is not registered + if ( user == null) { + try { + user = User.retrieve(THE_PUBLIC_USER); + } catch ( DataObjectNotFoundException e ) { + s_log.error("Public User does not exist."); + } + } + + // Iterate over the widget parameters and insert the answers to the survey response + Iterator parameterIter = formData.getParameters().iterator(); + while (parameterIter.hasNext()) { + s_log.warn("Found some formData"); + ParameterData parameterData = (ParameterData)parameterIter.next(); + + String parameterName = (String)parameterData.getName(); + + Object parameterValue = parameterData.getValue(); + if (parameterValue instanceof java.lang.String[]) { + // This is a multi-answer question - iterate over the + // answer values and add them one by one + String[] valueArray = (String[])parameterValue; + for (int i = 0; i < valueArray.length; ++i) { + addAnswer(response, ps, valueArray[i], parameterName); + + } + } else { + // Single answer question + + addAnswer(response, ps, parameterValue, parameterName); + } + } + // Save the survey response to the database + response.save(); + saveScore(survey, response); + } + + private void saveScore(Survey survey, Response response) { + + String query; + if ( survey.getQuizType().equals(KNOWLEDGE_TEST) ) { + query = "com.arsdigita.simplesurvey.saveScore"; + } else { + query = "com.arsdigita.simplesurvey.saveAssessmentScore"; + } + DataOperation dao = SessionManager.getSession().retrieveDataOperation(query); + dao.setParameter("responseID", response.getID()); + dao.execute(); + } + + private void addAnswer(Response surveyResponse, + PageState ps, + Object parameterValue, + String parameterName) { + + s_log.debug("formData name " + parameterName + " value " + parameterValue); + + Question question = getQuestion(ps, parameterName); + + if (question != null ) { + + PersistentLabel persistentLabel = question.getLabel(); + PersistentWidget persistentWidget = question.getWidget(); + + surveyResponse.addAnswer(persistentLabel, persistentWidget, getStringValue(parameterValue)); + } + } + + private String getStringValue(Object parameterValue) { + + return parameterValue == null ? "" : parameterValue.toString(); + } + + protected Question getQuestion(PageState ps, String parameterName) { + + if (m_nameQuestionMap.get(ps) == null) { + + // Populate the parameter name label id map + synchronized (this) { + + Map nameQuestionMap = new HashMap(); + + s_log.debug("initializing the parameter name persistent label map"); + + PersistentForm persistentForm = (PersistentForm)m_persistentForm.get(ps); + DataAssociationCursor componentCursor = persistentForm.getComponents(); + PersistentLabel lastPersistentLabel = null; + while (componentCursor.next()) { + + PersistentComponent factory = (PersistentComponent) DomainObjectFactory.newInstance(componentCursor.getDataObject()); + + s_log.debug("iterating, component " + factory.toString()); + + // If this is a PersistentLabel save its id + if (factory instanceof com.arsdigita.formbuilder.PersistentLabel) { + + lastPersistentLabel = (PersistentLabel)factory; + } + + // Add the previous label id if this is a PersistentWidget + if (factory instanceof com.arsdigita.formbuilder.PersistentWidget) { + + s_log.debug("adding to map " + ((PersistentWidget)factory).getParameterName() + + " mapped to " + lastPersistentLabel); + + Question question = new Question(lastPersistentLabel, + (PersistentWidget)factory); + + nameQuestionMap.put(((PersistentWidget)factory).getParameterName(), question); + } + } + + m_nameQuestionMap.set(ps, nameQuestionMap); + } + } + + s_log.debug("fetching label for parameter name " + parameterName); + + Question question = (Question)((Map)m_nameQuestionMap.get(ps)).get(parameterName); + + s_log.debug("returning " + question); + + return question; + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesForm.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesForm.java new file mode 100755 index 000000000..468665b65 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesForm.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui; + + +import com.arsdigita.cms.contenttypes.util.SurveyGlobalizationUtil ; + +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormInitListener; + +import com.arsdigita.bebop.parameters.NotWhiteSpaceValidationListener; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.BlockStylable; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.form.TextArea; +import com.arsdigita.bebop.form.Date; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.RadioGroup; +import com.arsdigita.bebop.form.Option; + +import com.arsdigita.formbuilder.PersistentForm; + +import com.arsdigita.cms.contenttypes.Survey; + +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.lang.Boolean; + +public class SurveyPropertiesForm extends Form { + + private SurveySelectionModel m_survey; + private Class m_type; + + + private TextField m_surveyName; + private TextArea m_description; + private Date m_startDate; + private Date m_endDate; + private RadioGroup m_responsesPublic; + private RadioGroup m_quizType; + + public PropertiesForm(SurveySelectionModel survey, + Class type) { + + super("properties" + type.getName()); + + m_survey = survey; + m_type = type; + + m_surveyName = new TextField("surveyName"); + m_surveyName.addValidationListener(new NotWhiteSpaceValidationListener()); + m_description = new TextArea("description"); + + + m_startDate = new Date("startDate"); + m_endDate = new Date("endDate"); + + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.name"))); + add(m_surveyName); + + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.description"))); + m_description.setRows(20); + m_description.setCols(60); + add(m_description); + + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.start_date"))); + add(m_startDate); + + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.end_date"))); + add(m_endDate); + + + + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.should_quiz_responses_be_public"))); + m_responsesPublic = new RadioGroup("responsesPublic"); + Option o1 = new Option("true", new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.Yes"))); + Option o2 = new Option("false", new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.No"))); + m_responsesPublic.addOption(o1); + m_responsesPublic.addOption(o2); + add(m_responsesPublic); + + // There can be 2 kinds of quizzes: the knowledge test kind of quiz and the personality assessment kind + add(new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.what_type_of_quiz_is_this"))); + m_quizType = new RadioGroup("quizType"); + Option o3 = new Option("knowledge_test", new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.knowledge_test_quiz"))); + Option o4 = new Option("personal_assessment", new Label(GlobalizationUtil.globalize("simplesurvey.ui.admin.personal_assessment_quiz"))); + m_quizType.addOption(o3); + m_quizType.addOption(o4); + add(m_quizType); + + add(new Submit("submit"), BlockStylable.CENTER); + addInitListener(new SurveyInitListener()); + addProcessListener(new PropertiesFormProcessListener()); + + } + + private class SurveyInitListener implements FormInitListener { + public void init(FormSectionEvent e) + throws FormProcessException { + PageState state = e.getPageState(); + + if (m_survey.isSelected(state)) { + Survey survey = m_survey.getSelectedSurvey(state); + PersistentForm form = survey.getForm(); + + m_surveyName.setValue(state, form.getAdminName()); + m_description.setValue(state, form.getDescription()); + m_startDate.setValue(state, survey.getStartDate()); + m_endDate.setValue(state, survey.getEndDate()); + m_quizType.setValue(state, survey.getQuizType()); + if ( survey.responsesArePublic() ) { + m_responsesPublic.setValue(state, "true"); + } else { + m_responsesPublic.setValue(state,"false"); + } + } else { + m_surveyName.setValue(state, ""); + m_description.setValue(state, ""); + + Calendar startCalendar = new GregorianCalendar(); + startCalendar.add(Calendar.DATE, 0); + java.util.Date startDate = startCalendar.getTime(); + Calendar endCalendar = new GregorianCalendar(); + endCalendar.add(Calendar.DATE, 15); + java.util.Date endDate = endCalendar.getTime(); + + m_startDate.setValue(state, startDate); + m_endDate.setValue(state, endDate); + m_responsesPublic.setValue(state, "true"); + m_quizType.setValue(state, "knowledge_test"); + } + } + } + + private class PropertiesFormProcessListener implements FormProcessListener { + public void process(FormSectionEvent e) + throws FormProcessException { + PageState state = e.getPageState(); + + Survey survey; + PersistentForm form; + + if (m_survey.isSelected(state)) { + survey = m_survey.getSelectedSurvey(state); + form = survey.getForm(); + } else { + survey = m_type.equals(Survey.class) ? new Survey() : new Poll(); + survey.setPackageInstance(SimpleSurveyUtil.getPackageInstance(state)); + form = new PersistentForm(); + survey.setForm(form); + } + + form.setAdminName((String)m_surveyName.getValue(state)); + form.setHTMLName(getHTMLName((String)m_surveyName.getValue(state))); + form.setDescription((String)m_description.getValue(state)); + form.save(); + + survey.setStartDate((java.util.Date)m_startDate.getValue(state)); + survey.setEndDate((java.util.Date)m_endDate.getValue(state)); + survey.setResponsesPublic(new Boolean((String) m_responsesPublic.getValue(state))); + survey.setQuizType((String) m_quizType.getValue(state)); + survey.save(); + } + + private String getHTMLName(String surveyName) { + + String htmlName = surveyName.trim().toLowerCase(); + + htmlName = htmlName.replace(' ', '_'); + + return htmlName; + } + + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesStep.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesStep.java new file mode 100644 index 000000000..057e97a17 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveyPropertiesStep.java @@ -0,0 +1,119 @@ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.cms.ContentPage; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; +import com.arsdigita.cms.ui.authoring.BasicPageForm; +import com.arsdigita.cms.ui.authoring.SimpleEditStep; +import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess; +import com.arsdigita.domain.DomainObject; +import com.arsdigita.toolbox.ui.DomainObjectPropertySheet; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.cms.contenttypes.Survey; +import com.arsdigita.cms.contenttypes.util.SurveyGlobalizationUtil; + +import java.text.DateFormat; +import org.apache.log4j.Logger; + +/** + * AuthoringStep for the basic properties of a basic contact + */ +public class SurveyPropertiesStep extends SimpleEditStep { + + private static final Logger logger = Logger.getLogger(SurveyPropertiesStep.class); + + /** + * Name of the this edit sheet (Don't know if this this really needed. + * It has the same value in almost all PropertiesStep classes) + */ + public static final String EDIT_BASIC_SHEET_NAME = "editBasic"; + + /** + * Constructor for the PropertiesStep. + * + * @param itemModel + * @param parent + */ + public SurveyPropertiesStep(ItemSelectionModel itemModel, AuthoringKitWizard parent) { + super(itemModel, parent); + + /* Use a Segmented Panel for the multiple parts of data */ + SegmentedPanel segmentedPanel = new SegmentedPanel(); + + setDefaultEditKey(EDIT_BASIC_SHEET_NAME); + + /* The different parts of information are displayed in seperated segments each containing a SimpleEditStep */ + /* Well, not so simple anymore... */ + + /* A new SimpleEditStep */ + SimpleEditStep basicProperties = new SimpleEditStep(itemModel, parent, EDIT_BASIC_SHEET_NAME); + + /* Create the edit component for this SimpleEditStep and the corresponding link */ + BasicPageForm editBasicSheet = new SurveyPropertyForm(itemModel, this); + basicProperties.add(EDIT_BASIC_SHEET_NAME, (String)SurveyGlobalizationUtil.globalize("cms.contenttypes.ui.survey.edit_basic_properties").localize(), new WorkflowLockedComponentAccess(editBasicSheet, itemModel), editBasicSheet.getSaveCancelSection().getCancelButton()); + + /* Set the displayComponent for this step */ + basicProperties.setDisplayComponent(getSurveyPropertySheet(itemModel)); + + /* Add the SimpleEditStep to the segmented panel */ + segmentedPanel.addSegment(new Label((String)SurveyGlobalizationUtil.globalize("cms.contenttypes.ui.survey.basic_properties").localize()), basicProperties); + + // If not disabled via registry, add the ui for attaching a person + if(!Survey.getConfig().getHidePerson()) { + SurveyPersonPropertiesStep personProperties = new SurveyPersonPropertiesStep(itemModel, parent); + segmentedPanel.addSegment(new Label((String)SurveyGlobalizationUtil.globalize("cms.contenttypes.ui.survey.person").localize()), personProperties); + } + + // If not disabled via registry, add the ui for attaching a baseAddress + if(!Survey.getConfig().getHideAddress()) { + SurveyAddressPropertiesStep addressProperties = new SurveyAddressPropertiesStep(itemModel, parent); + segmentedPanel.addSegment(new Label((String)SurveyGlobalizationUtil.globalize("cms.contenttypes.ui.survey.address").localize()), addressProperties); + } + + SurveyEntriesPropertiesStep surveyEntries = new SurveyEntriesPropertiesStep(itemModel, parent); + segmentedPanel.addSegment(new Label((String)SurveyGlobalizationUtil.globalize("cms.contenttypes.ui.survey.contactEntry").localize()), surveyEntries); + + /* Sets the composed segmentedPanel as display component */ + setDisplayComponent(segmentedPanel); + } + + /** + * Creates and returns the sheet for editing the basic properties + * of an organization. (@see SurveyPropertyForm). + * + * @param itemModel + * @return The sheet for editing the properties of the organization. + */ + public static Component getSurveyPropertySheet(ItemSelectionModel itemModel) { + + + /* The DisplayComponent for the Basic Properties */ + DomainObjectPropertySheet sheet = new DomainObjectPropertySheet(itemModel); + + sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.name"),"name"); + sheet.add(GlobalizationUtil.globalize("cms.contenttypes.ui.title"),"title"); + + if(!ContentSection.getConfig().getHideLaunchDate()) { + sheet.add(GlobalizationUtil.globalize("cms.ui.authoring.page_launch_date"), ContentPage.LAUNCH_DATE, new DomainObjectPropertySheet.AttributeFormatter() { + + public String format(DomainObject obj, String attribute, PageState state) { + ContentPage page = (ContentPage)obj; + if(page.getLaunchDate() != null) { + return DateFormat.getDateInstance(DateFormat.LONG).format(page.getLaunchDate()); + } + else { + return (String)GlobalizationUtil.globalize("cms.ui.unknown").localize(); + } + } + }); + } + + return sheet; + } + +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveySelectionModel.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveySelectionModel.java new file mode 100755 index 000000000..3aaa1eaec --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/ui/SurveySelectionModel.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.simplesurvey.ui; + + +import com.arsdigita.bebop.PageState; + +import com.arsdigita.bebop.parameters.BigDecimalParameter; + +import com.arsdigita.simplesurvey.Survey; + +import com.arsdigita.toolbox.ui.ACSObjectSelectionModel; + + +public class SurveySelectionModel extends ACSObjectSelectionModel { + + public SurveySelectionModel(BigDecimalParameter param) { + super(Survey.class.getName(), + Survey.BASE_DATA_OBJECT_TYPE, + param); + } + + public Survey getSelectedSurvey(PageState state) { + return (Survey)getSelectedObject(state); + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyGlobalizationUtil.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyGlobalizationUtil.java new file mode 100755 index 000000000..c45335040 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyGlobalizationUtil.java @@ -0,0 +1,33 @@ +package com.arsdigita.cms.contenttypes.util; + +import com.arsdigita.globalization.GlobalizedMessage; + +/** + *

+ * . + * Contains methods to simplify globalizing keys + *

+ * + * @author Sören Bernstein + */ +public class SurveyGlobalizationUtil { + + final public static String BUNDLE_NAME = + "com.arsdigita.cms.contenttypes.util.SurveyResourceBundle"; + + /** + * This returns a globalized message using the type specific bundle, + * BUNDLE_NAME + */ + public static GlobalizedMessage globalize(String key) { + return new GlobalizedMessage(key, BUNDLE_NAME); + } + + /** + * This returns a globalized message using the type specific bundle, + * BUNDLE_NAME + */ + public static GlobalizedMessage globalize(String key, Object[] args) { + return new GlobalizedMessage(key, BUNDLE_NAME, args); + } +} diff --git a/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyResourceBundle.java b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyResourceBundle.java new file mode 100755 index 000000000..afb0197f7 --- /dev/null +++ b/ccm-cms-types-survey/src/com/arsdigita/cms/contenttypes/util/SurveyResourceBundle.java @@ -0,0 +1,17 @@ +package com.arsdigita.cms.contenttypes.util; + +import java.util.PropertyResourceBundle; +import com.arsdigita.globalization.ChainedResourceBundle; +import com.arsdigita.cms.CMSGlobalized; + +public class SurveyResourceBundle extends ChainedResourceBundle implements CMSGlobalized { + + public final static String SURVEY_BUNDLE_NAME = + "com.arsdigita.cms.contenttypes.SurveyResources"; + + public SurveyResourceBundle() { + super(); + addBundle((PropertyResourceBundle) getBundle(SURVEY_BUNDLE_NAME)); + addBundle((PropertyResourceBundle) getBundle(BUNDLE_NAME)); + } +} diff --git a/ccm-cms-types-survey/web/static/content-types/com/arsdigita/cms/contenttypes/Survey.xsl b/ccm-cms-types-survey/web/static/content-types/com/arsdigita/cms/contenttypes/Survey.xsl new file mode 100644 index 000000000..a039f12d5 --- /dev/null +++ b/ccm-cms-types-survey/web/static/content-types/com/arsdigita/cms/contenttypes/Survey.xsl @@ -0,0 +1,41 @@ + +]> + + + + +
+ + + + + + +
+ +
+ + + + + + + +
Address:
+
+ + + +

+ + Address +
+
+
+ + \ No newline at end of file