Pollen-commits
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- 3196 discussions
r3836 - in trunk/pollen-ui-js/src/main: resources/nuiton-js webapp webapp/bundle webapp/js/controls webapp/js/models webapp/views
by kmorin@users.chorem.org 18 Jun '13
by kmorin@users.chorem.org 18 Jun '13
18 Jun '13
Author: kmorin
Date: 2013-06-18 18:48:04 +0200 (Tue, 18 Jun 2013)
New Revision: 3836
Url: http://chorem.org/projects/pollen/repository/revisions/3836
Log:
- add user form with validation
- improve vote live results and choices
Added:
trunk/pollen-ui-js/src/main/webapp/js/controls/user_form.js
trunk/pollen-ui-js/src/main/webapp/js/models/users.js
trunk/pollen-ui-js/src/main/webapp/views/user_form.ejs
Modified:
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
trunk/pollen-ui-js/src/main/webapp/index.html
trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js
trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
trunk/pollen-ui-js/src/main/webapp/js/models/polls.js
trunk/pollen-ui-js/src/main/webapp/js/models/votes.js
trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs
trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
Modified: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
===================================================================
--- trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml 2013-06-18 16:48:04 UTC (rev 3836)
@@ -8,6 +8,7 @@
<group-ref>can.fixture</group-ref>
<group-ref>can.observe.attributes</group-ref>
<group-ref>can.observe.delegate</group-ref>
+ <group-ref>can.observe.validations</group-ref>
<group-ref>jquery.i18n.properties</group-ref>
<group-ref>moment</group-ref>
Modified: trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-18 16:48:04 UTC (rev 3836)
@@ -1,3 +1,5 @@
+pollen.app.title=Pollen
+
#common
pollen.common.cancel=Annuler
pollen.common.validate=Valider
@@ -20,9 +22,22 @@
pollen.choice.name.label=Titre
pollen.choice.name.placeholder=Titre
+#user attributes
+pollen.user.email.label=Email
+pollen.user.email.placeholder=Email
+pollen.user.login.label=Login
+pollen.user.login.placeholder=Login
+pollen.user.name.label=Nom
+pollen.user.name.placeholder=Nom
+pollen.user.password.label=Mot de passe
+pollen.user.password.placeholder=Mot de passe
+pollen.user.repeatPassword.label=Répétez le mot de passe
+pollen.user.repeatPassword.placeholder=Répétez le mot de passe
+
#menu
pollen.menu.home=Accueil
pollen.menu.polls=Sondages
+pollen.menu.register=Créer un compte
#poll creation form
pollen.poll.form.create.button.save=Créer le sondage
@@ -58,4 +73,16 @@
pollen.vote.comments.list.title=Commentaires
pollen.vote.comments.list.button.addComment=Ajouter un commentaire
pollen.vote.comments.add.field.userName.placeholder=Votre nom
-pollen.vote.comments.add.field.message.placeholder=Votre commentaire
\ No newline at end of file
+pollen.vote.comments.add.field.message.placeholder=Votre commentaire
+
+#user form
+pollen.user.form.edit.title.creation=Enregistrement
+pollen.user.form.edit.title.update=Compte utilisateur
+pollen.user.form.edit.button.create=Créer le compte
+pollen.user.form.edit.button.update=Sauvegarder
+
+#validation
+pollen.validation.required=Le champ est obligatoire
+pollen.validation.email.format.error=L''email n''est pas valide
+pollen.validation.password.length.error=Le mot de passe doit faire au moins 6 caractères
+pollen.validation.passwords.different.error=Les deux mots de passes ne correspondent pas
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/index.html
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-18 16:48:04 UTC (rev 3836)
@@ -11,10 +11,7 @@
<div class="navbar navbar-inverse navbar-static-top">
<div class="navbar-inner">
- <div class='container'>
- <a class="brand" href="#">Pollen</a>
- <ul class="nav" id="menu">
- </ul>
+ <div class='container' id="menu">
</div>
</div>
</div>
@@ -25,6 +22,7 @@
<div id="pollForm"></div>
<div id="pollSummary"></div>
<div id="vote"></div>
+ <div id="userForm"></div>
</div>
@@ -34,11 +32,13 @@
<script src="js/models/polls.js"></script>
<script src="js/models/comments.js"></script>
<script src="js/models/votes.js"></script>
+ <script src="js/models/users.js"></script>
<script src="js/controls/menu.js"></script>
<script src="js/controls/poll_form.js"></script>
<script src="js/controls/poll_summary.js"></script>
<script src="js/controls/vote.js"></script>
+ <script src="js/controls/user_form.js"></script>
<script type="text/javascript">
@@ -55,6 +55,7 @@
var pf = new PollForm('#pollForm');
var summary = new PollSummary('#pollSummary');
var vote = new PollVote('#vote');
+ var userForm = new UserForm('#userForm');
can.route(':type/:action');
can.route(':type/:id/:action');
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -29,10 +29,6 @@
}
},
- '.save click': function() {
- this.updatePoll();
- },
-
'.create click': function() {
can.route.attr({ type: "poll", action: "edit" }, true);
},
@@ -41,24 +37,18 @@
can.route.attr({ type: "poll", action: "edit", id: el.data('id') });
},
- '{poll} created': function(data) {
- can.route.attr({ type: "poll", action: "summary", id: data.id });
- },
-
- '{poll} updated': function(data) {
- can.route.attr({ type: "poll", action: "summary", id: data.id });
- },
-
- updatePoll: function() {
- var form = this.element.find('form'),
- values = can.deparam(form.serialize()),
+ '#pollCreationForm submit': function(form) {
+ var values = can.deparam(form.serialize()),
self = this;
this.options.poll.attr(values).save(function(data) {
if (data.id) {
-// self.options.poll.id = data.id;
+ self.options.poll.id = data.id;
}
+ can.route.attr({ type: "poll", action: "summary", id: data.id });
});
+
+ return false;
},
editPoll: function(poll) {
Copied: trunk/pollen-ui-js/src/main/webapp/js/controls/user_form.js (from rev 3834, trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js)
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/user_form.js (rev 0)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/user_form.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -0,0 +1,89 @@
+var UserForm = can.Control({
+
+ defaults: {
+ user: new User()
+ }
+
+}, {
+ init: function() {
+
+ this.element.html(can.view('views/user_form.ejs', {
+ user: this.options.user
+ }));
+
+ },
+
+ ':type/:action route': function(data) {
+ if (data.type === "user" && data.action === "registration") {
+ this.editUser(new User());
+ }
+ },
+
+ ':type/:id/:action route': function(data) {
+ if (data.type === "user" && data.action === "edit") {
+ var self = this;
+ $.when(User.findOne({id: data.id})).then(
+ function(user) {
+ self.editUser(user);
+ });
+ }
+ },
+
+ ':input change': function(el) {
+ this.options.user.attr(el.attr('name'), el.val());
+ },
+
+ ':input keyup': function(el) {
+ this.options.user.attr(el.attr('name'), el.val());
+ },
+
+ '#userEditionForm submit': function(form) {
+ var self = this,
+ user = this.options.user,
+ errors = user.errors();
+
+ if (errors == null) {
+ user.repeatPassword = null;
+ //TODO 20130618 kmorin encrypt password
+ user.save(function(data) {
+ if (data.id) {
+ user.id = data.id;
+ }
+ });
+
+ } else {
+ for (var error in errors) {
+ this.hideOrShowError(error, errors);
+ }
+ }
+
+ return false;
+ },
+
+ '{user} change': function(user, ev, attr, type, newValue, oldValue) {
+ var errors = user.errors();
+ this.hideOrShowError(attr, errors, type == "remove");
+ },
+
+ hideOrShowError: function(attr, errors, forceHide) {
+ var error = errors && errors[attr];
+ var el = this.element.find(':input[name="' + attr + '"]');
+
+ if (error && !forceHide) {
+ el.parents('.control-group').addClass('error');
+ el.siblings('.help-inline').text($.i18n.prop(error, this.options.user[attr]));
+ el.siblings('.help-inline').show();
+
+ } else {
+ el.parents('.control-group').removeClass('error');
+ el.siblings('.help-inline').hide();
+ }
+ },
+
+ editUser: function(user) {
+ this.options.user.attr(user._data, true);
+ this.element.siblings().hide();
+ this.element.show();
+ }
+
+});
\ No newline at end of file
Property changes on: trunk/pollen-ui-js/src/main/webapp/js/controls/user_form.js
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -25,12 +25,12 @@
},
'#voteForm submit': function(form) {
- var voteToChoices = [];
+ var voteToChoices = {};
var choices = this.options.poll.choices;
for (var i = 0 ; i < choices.length ; i++) {
var choice = choices[i];
var voteValue = form.find("[name='" + i + "']").is(':checked');
- voteToChoices.push({ voteValue: voteValue, choice: choice.id });
+ voteToChoices[choice.id] = { voteValue: voteValue, choice: choice.id };
}
var voteAttributes = {
@@ -42,9 +42,15 @@
var vote = new Vote(voteAttributes);
var self = this;
- vote.save({ pollId: this.options.poll.id },
- function(saved) {
+ var poll = this.options.poll;
+ vote.save({ pollId: poll.id }, function(saved) {
self.options.votes.push(vote);
+ for (var choiceId in vote.voteToChoices) {
+ if (vote.voteToChoices[choiceId].voteValue) {
+ var result = poll.results[choiceId];
+ poll.results.attr(choiceId, result + 1);
+ }
+ }
});
form[0].reset();
@@ -56,7 +62,9 @@
var choices = this.options.poll.choices;
var name = form.find("[name='name']").val();
var desc = form.find("[name='description']").val();
- choices.push({ name: name, description: desc });
+ var choiceId = moment().valueOf();
+ choices.push({ id: choiceId, name: name, description: desc });
+ this.options.poll.results.attr(choiceId, 0);
form[0].reset();
@@ -99,6 +107,27 @@
// other functions
showPoll: function(poll, comments, votes) {
+ var results = new can.Observe.List();
+ // init results
+ for (var i = 0 ; i < poll.choices.length ; i++) {
+ results[poll.choices[i].id] = 0;
+ }
+ // fill the results
+ for (i = 0 ; i < votes.length ; i++) {
+ var vote = votes[i];
+ var voteToChoices = {};
+ // create a map of the choices by id
+ for (var j = 0 ; j < vote.voteToChoices.length ; j++) {
+ var voteChoice = vote.voteToChoices[j];
+ voteToChoices[voteChoice.choice] = voteChoice;
+ if (voteChoice.voteValue) {
+ results.attr(voteChoice.choice, results[voteChoice.choice] + 1);
+ }
+ }
+ vote.voteToChoices = voteToChoices;
+ }
+ poll.results = results;
+
this.options.poll = poll;
this.options.votes = votes;
this.options.comments = comments;
Modified: trunk/pollen-ui-js/src/main/webapp/js/models/polls.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -33,7 +33,7 @@
description: "description très longue, mais vraiment très longue pour qu'elle passe en dessous. Enfin j'espère que ce sera assez long",
creatorName: "moi",
choiceAddAllowed: true,
- beginChoiceDate: moment.valueOf(),
+ beginChoiceDate: moment().valueOf(),
endChoiceDate: moment().add('m', 1).valueOf(),
beginDate: moment().subtract('d', 5).valueOf(),
endDate: moment().add('d', 5).valueOf(),
Added: trunk/pollen-ui-js/src/main/webapp/js/models/users.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/models/users.js (rev 0)
+++ trunk/pollen-ui-js/src/main/webapp/js/models/users.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -0,0 +1,71 @@
+var User = can.Model({
+ findAll: 'GET /users',
+ findOne: "GET /users/{id}",
+ create : "POST /users",
+ update : "PUT /users/{id}",
+ destroy : "DELETE /users/{id}",
+
+ init: function() {
+ this.validatePresenceOf(["login", "name", "email", "password", "repeatPassword"],
+ {
+ message : "pollen.validation.required"
+ });
+
+ this.validateFormatOf(
+ ["email"],
+ /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
+ {
+ message : "pollen.validation.email.format.error"
+ });
+
+ this.validateLengthOf(["password"], 6, 1000, {
+ message : "pollen.validation.password.length.error"
+ });
+
+ this.validate(["repeatPassword"], function(val) {
+ if (val != this.password) {
+ return "pollen.validation.passwords.different.error";
+ }
+ });
+ }
+
+}, {});
+
+var USERS = [
+ {
+ id: 1,
+ login: 'kmorin',
+ name: "Kevin Morin",
+ email: "kmorin(a)codelutin.com"
+ },
+ {
+ id: 2,
+ login: 'tchemit',
+ name: "Tony Chemit",
+ email: "chemit(a)codelutin.com"
+ },
+];
+
+can.fixture('GET /users', function(){
+ return USERS;
+});
+
+can.fixture('GET /users/{id}', function(orig) {
+ return USERS[orig.data.id - 1];
+});
+
+var idToInc= 3;
+can.fixture("POST /users", function() {
+ console.log("create user " + idToInc);
+ return {id: (idToInc++)}
+});
+
+can.fixture("PUT /users/{id}", function(orig) {
+ console.log("update user " + orig.data.id);
+ return {};
+});
+
+can.fixture("DELETE /users/{id}", function(orig){
+ console.log("delete user " + orig.data.id);
+ return {};
+});
Modified: trunk/pollen-ui-js/src/main/webapp/js/models/votes.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/models/votes.js 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/js/models/votes.js 2013-06-18 16:48:04 UTC (rev 3836)
@@ -41,11 +41,11 @@
email: "william(a)dalt.on"
},
voteToChoices: [{
+ voteValue: 0,
+ choice: 2
+ }, {
voteValue: 1,
choice: 1
- },{
- voteValue: 0,
- choice: 2
}]
}, {
id: 4,
Modified: trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-18 16:48:04 UTC (rev 3836)
@@ -1,7 +1,13 @@
-<li><%== can.route.link(pollen.menu.home, {}) %></li>
-<li class="dropdown">
- <a href="#" role="button" class="dropdown-toggle" data-toggle="dropdown"><%= pollen.menu.polls %> <b class="caret"></b></a>
- <ul class="dropdown-menu" role="menu">
- <li role="presentation"><%== can.route.link(pollen.menu.polls, { type: 'poll', action: 'edit' }, { role: 'menuitem', tabIndex: "-1" }, false) %></li>
- </ul>
-</li>
\ No newline at end of file
+<a class="brand" href="#"><%= pollen.app.title %></a>
+<ul class="nav">
+ <li><%== can.route.link(pollen.menu.home, {}) %></li>
+ <li class="dropdown">
+ <a href="#" role="button" class="dropdown-toggle" data-toggle="dropdown"><%= pollen.menu.polls %> <b class="caret"></b></a>
+ <ul class="dropdown-menu" role="menu">
+ <li role="presentation"><%== can.route.link(pollen.menu.polls, { type: 'poll', action: 'edit' }, { role: 'menuitem', tabIndex: "-1" }, false) %></li>
+ </ul>
+ </li>
+</ul>
+<ul class="nav pull-right">
+<li><%== can.route.link(pollen.menu.register, { type: 'user', action: 'registration' }) %></li>
+</ul>
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-18 16:48:04 UTC (rev 3836)
@@ -21,7 +21,7 @@
</div>
<div class="form-actions">
- <a href="javascript://" class="btn btn-primary save"><%= pollen.poll.form.create.button.save %></a>
+ <button type='submit' class="btn btn-primary"><%= pollen.poll.form.create.button.save %></button>
<a href="javascript://" class="btn btn-primary create">New poll</a>
<a href="javascript://" data-id="1" class="btn btn">Edit poll 1</a>
<a href="javascript://" data-id="2" class="btn btn">Edit poll 2</a>
Added: trunk/pollen-ui-js/src/main/webapp/views/user_form.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/user_form.ejs (rev 0)
+++ trunk/pollen-ui-js/src/main/webapp/views/user_form.ejs 2013-06-18 16:48:04 UTC (rev 3836)
@@ -0,0 +1,75 @@
+<h1><%= user.attr('id') ? pollen.user.form.edit.title.update : pollen.user.form.edit.title.creation %></h1>
+
+<form id='userEditionForm' class="form-horizontal">
+
+ <div class="control-group">
+ <label class="control-label" for="userEditionFormLogin"><%= pollen.user.login.label %></label>
+ <div class="controls">
+ <input type='text' name='login'
+ id='userEditionFormLogin'
+ placeholder='<%= pollen.user.login.placeholder %>'
+ value='<%= user.attr("login")%>'
+ required/>
+ <span class="help-inline"></span>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditionFormPassword"><%= pollen.user.password.label %></label>
+ <div class="controls">
+ <input type='password'
+ name='password'
+ id='userEditionFormPassword'
+ placeholder='<%= pollen.user.password.placeholder %>'
+ value='<%= user.attr("password")%>'
+ required/>
+ <span class="help-inline"></span>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditionFormRepeatPassword"><%= pollen.user.repeatPassword.label %></label>
+ <div class="controls">
+ <input type='password'
+ name='repeatPassword'
+ id='userEditionFormRepeatPassword'
+ placeholder='<%= pollen.user.repeatPassword.placeholder %>'
+ value='<%= user.attr("repeatPassword")%>'
+ required/>
+ <span class="help-inline"></span>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditionFormName"><%= pollen.user.name.label %></label>
+ <div class="controls">
+ <input type='text'
+ name='name'
+ id='userEditionFormName'
+ placeholder='<%= pollen.user.name.placeholder %>'
+ value='<%= user.attr("name")%>'
+ required/>
+ <span class="help-inline"></span>
+ </div>
+ </div>
+
+ <div class="control-group">
+ <label class="control-label" for="userEditionFormEmail"><%= pollen.user.email.label %></label>
+ <div class="controls">
+ <input type='email'
+ name='email'
+ id='userEditionFormEmail'
+ placeholder='<%= pollen.user.email.placeholder %>'
+ value='<%= user.attr("email")%>'
+ required/>
+ <span class="help-inline"></span>
+ </div>
+ </div>
+
+ <div class="form-actions">
+ <button type='submit' class="btn btn-primary save">
+ <%= user.attr('id') ? pollen.user.form.edit.button.update : pollen.user.form.edit.button.create %>
+ </button>
+ </div>
+
+</form>
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-18 09:15:55 UTC (rev 3835)
+++ trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-18 16:48:04 UTC (rev 3836)
@@ -10,7 +10,7 @@
| <a id="commentSummary" class='link'><i class='icon-comment'></i> <%= comments.attr('length') %></a>
<!-- poll dates -->
<% if (poll.attr('beginDate') && poll.attr('endDate')) { %>
- | <i class='icon-time'></i> <%= pollen.common.date.fromTo(moment(poll.attr('beginDate')).format(pollen.common.format.date), moment(poll.attr('endDate')).format(pollen.common.format.date)) %>
+ | <i class='icon-time'></i> <%= pollen.common.date.fromTo(moment(poll.attr('beginDate')).format(pollen.common.format.date), moment(poll.attr('endDate')).toString(pollen.common.format.date)) %>
<% } else if (poll.attr('beginDate')) { %>
| <i class='icon-time'></i> <%= pollen.common.date.from(moment(poll.attr('beginDate')).format(pollen.common.format.date)) %>
<% } else if (poll.attr('endDate')) { %>
@@ -40,7 +40,7 @@
<li><strong><%= choice.attr('name') %></strong> : <%= choice.attr('description') %></li>
<% }); %>
</ol>
- <% var now = new Date().getTime();
+ <% var now = moment().valueOf();
if (poll.attr('choiceAddAllowed') && poll.attr('beginChoiceDate') <= now && poll.attr('endChoiceDate') > now) {%>
<!-- link to show/hide the new choice form -->
@@ -77,14 +77,12 @@
<h2><%= pollen.vote.votes.list.title %></h2>
<table id="voteTable" class="table table-bordered table-striped">
- <% var results = new can.Observe.List(new Array(poll.attr('choices.length'))); %>
<thead>
<tr>
<th><%= pollen.vote.votes.list.header.voter %></th>
<% poll.choices.each(function(choice, i) { %>
<th data-container='body' data-placement='top' title='<%= choice.attr("description") %>'>
<%= choice.attr('name') %>
- <% results[i] = 0 %>
</th>
<% }); %>
</tr>
@@ -94,31 +92,27 @@
<tr>
<td><%= vote.attr('voterListMember.name') %></td>
<%
- poll.choices.each(function(choice, i) {
- var voteChoice = vote.voteToChoices.attr(i);
- if (voteChoice == null) {
- %>
- <td class='choice voteBeforeChoice'></td>
- <% } else { %>
- <td class='choice <%= voteChoice.attr("voteValue") ? "selected" : "notSelected" %>'>
- <%= voteChoice.attr("voteValue") ? "OK" : "" %>
- </td>
- <%
- if (voteChoice.attr("voteValue")) {
- // todo 20130614 kmorin check why if we do a results.attr(i, results[i] +1) ==> too much recursion
- results[i] = results[i] + 1
- }
- }
- });
+ poll.choices.each(function(choice) {
+ var voteChoice = vote.voteToChoices[choice.id];
+ if (voteChoice == null) {
+ %>
+ <td class='choice voteBeforeChoice'></td>
+ <% } else { %>
+ <td class='choice <%= voteChoice.attr("voteValue") ? "selected" : "notSelected" %>'>
+ <%= voteChoice.attr("voteValue") ? "OK" : "" %>
+ </td>
+ <%
+ }
+ });
%>
</tr>
<% }); %>
<tr>
<td>Resultats</td>
- <% poll.choices.each(function(choice, i) { %>
+ <% poll.choices.each(function(choice) { %>
<td class='result'>
- <%= results.attr(i) %>
+ <%= poll.results.attr(choice.id) %>
</td>
<% }); %>
</tr>
@@ -178,7 +172,7 @@
<%= comment.attr('text') %>
</p>
<div class='footer'>
- <small><%= comment.attr('author') %> | <%= moment(comment.attr('postDate')).format(pollen.common.format.dateTime) %></small>
+ <small><%= comment.attr('author') %> | <%= new Date(comment.attr('postDate')).toString(pollen.common.format.dateTime) %></small>
</div>
</div>
1
0
r3835 - in trunk/pollen-ui-js: . src/main/resources/nuiton-js src/main/webapp src/main/webapp/bundle src/main/webapp/js/controls src/main/webapp/js/libs src/main/webapp/js/models src/main/webapp/views
by kmorin@users.chorem.org 18 Jun '13
by kmorin@users.chorem.org 18 Jun '13
18 Jun '13
Author: kmorin
Date: 2013-06-18 11:15:55 +0200 (Tue, 18 Jun 2013)
New Revision: 3835
Url: http://chorem.org/projects/pollen/repository/revisions/3835
Log:
use nuiton-js + use moment.js instead of the old date.js
Removed:
trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap.min.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.fixture.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.min.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.object.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.attributes.js
trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.delegate.js
trunk/pollen-ui-js/src/main/webapp/js/libs/date.js
trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
Modified:
trunk/pollen-ui-js/pom.xml
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
trunk/pollen-ui-js/src/main/webapp/
trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
trunk/pollen-ui-js/src/main/webapp/index.html
trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
trunk/pollen-ui-js/src/main/webapp/js/models/polls.js
trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
Modified: trunk/pollen-ui-js/pom.xml
===================================================================
--- trunk/pollen-ui-js/pom.xml 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/pom.xml 2013-06-18 09:15:55 UTC (rev 3835)
@@ -61,6 +61,18 @@
<version>1.1.6-1</version>
</dependency>
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-jquery-i18n-properties</artifactId>
+ <version>1.0.9-1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-moment</artifactId>
+ <version>2.0.0-1</version>
+ </dependency>
+
</dependencies>
<executions>
Modified: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
===================================================================
--- trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml 2013-06-18 09:15:55 UTC (rev 3835)
@@ -8,6 +8,8 @@
<group-ref>can.fixture</group-ref>
<group-ref>can.observe.attributes</group-ref>
<group-ref>can.observe.delegate</group-ref>
+ <group-ref>jquery.i18n.properties</group-ref>
+ <group-ref>moment</group-ref>
<!-- scpecifique nuiton profiling -->
<!--<css>/nuiton-profiling.css</css>-->
Property changes on: trunk/pollen-ui-js/src/main/webapp
___________________________________________________________________
Added: svn:ignore
+ pollen-ui-js.js
pollen-ui-js.css
Modified: trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,8 +1,8 @@
#common
pollen.common.cancel=Annuler
pollen.common.validate=Valider
-pollen.common.format.date=dd/MM/yyyy
-pollen.common.format.dateTime=dd/MM/yyyy HH:mm
+pollen.common.format.date=DD/MM/YYYY
+pollen.common.format.dateTime=DD/MM/YYYY HH:mm
pollen.common.format.time=HH:mm
pollen.common.date.from=à partir du {0}
pollen.common.date.fromTo=du {0} au {1}
Modified: trunk/pollen-ui-js/src/main/webapp/index.html
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="fr" xmlns="http://www.w3.org/1999/xhtml">
<head>
- <meta charset="utf-8">
+ <meta charset="utf-8"/>
<title>Pollen</title>
<link rel="stylesheet" href="pollen-ui-js.css"></link>
<link rel="stylesheet" href="css/style.css"></link>
@@ -30,8 +30,6 @@
<script src="pollen-ui-js.js"></script>
<script src="js/libs/jquery.scrollto.js"></script>
- <script src="js/libs/date.js"></script>
- <script src="js/libs/jquery.i18n.properties-min-1.0.9.js"></script>
<script src="js/models/polls.js"></script>
<script src="js/models/comments.js"></script>
@@ -45,8 +43,6 @@
<script type="text/javascript">
// This will initialize the plugin
- // and show two dialog boxes: one with the text "Olá World"
- // and other with the text "Good morning John!"
$.i18n.properties({
name:'Messages',
path:'bundle/',
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -17,7 +17,7 @@
// click events
'#voteSummary click': function() {
- this.scrollToComponent($("#voteTable"));
+ this.scrollToComponent($("#voteForm"));
},
'#commentSummary click': function() {
@@ -113,8 +113,7 @@
},
scrollToComponent: function(component) {
- var position = component.position();
- $('html, body').scrollTo(position.left, position.top);
+ $('html, body').scrollTo(null, component);
}
});
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap.min.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap.min.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/bootstrap.min.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,7 +0,0 @@
-/**
-* Bootstrap.js by @fat & @mdo
-* plugins: bootstrap-transition.js, bootstrap-modal.js, bootstrap-dropdown.js, bootstrap-scrollspy.js, bootstrap-tab.js, bootstrap-tooltip.js, bootstrap-popover.js, bootstrap-affix.js, bootstrap-alert.js, bootstrap-button.js, bootstrap-collapse.js, bootstrap-carousel.js, bootstrap-typeahead.js
-* Copyright 2012 Twitter, Inc.
-* http://www.apache.org/licenses/LICENSE-2.0.txt
-*/
-!function(a){a(function(){a.support.transition=function(){var a=function(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},c;for(c in b)if(a.style[c]!==undefined)return b[c]}();return a&&{end:a}}()})}(window.jQuery),!function(a){var b=function(b,c){this.options=c,this.$element=a(b).delegate('[data-dismiss="modal"]',"click.dismiss.modal",a.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};b.prototype={constructor:b,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var b=this,c=a.Event("show");this.$element.trigger(c);if(this.isShown||c.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var c=a.support.transition&&b.$element.hasClass("fade");b.$element.parent().length||b.$element.appendTo(document.body),b.$element.show(),c&&b.$element[0].offsetWidth,b.$element.addClass("in").attr("aria-hidden",!1),b.enforceFocus(),c?b.$element.one(a.support.transition.end,function(){b.$element.focus().trigger("shown")}):b.$element.focus().trigger("shown")})},hide:function(b){b&&b.preventDefault();var c=this;b=a.Event("hide"),this.$element.trigger(b);if(!this.isShown||b.isDefaultPrevented())return;this.isShown=!1,this.escape(),a(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),a.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var b=this;a(document).on("focusin.modal",function(a){b.$element[0]!==a.target&&!b.$element.has(a.target).length&&b.$element.focus()})},escape:function(){var a=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(b){b.which==27&&a.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var b=this,c=setTimeout(function(){b.$element.off(a.support.transition.end),b.hideModal()},500);this.$element.one(a.support.transition.end,function(){clearTimeout(c),b.hideModal()})},hideModal:function(){var a=this;this.$element.hide(),this.backdrop(function(){a.removeBackdrop(),a.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(b){var c=this,d=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var e=a.support.transition&&d;this.$backdrop=a('<div class="modal-backdrop '+d+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?a.proxy(this.$element[0].focus,this.$element[0]):a.proxy(this.hide,this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!b)return;e?this.$backdrop.one(a.support.transition.end,b):b()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(a.support.transition.end,b):b()):b&&b()}};var c=a.fn.modal;a.fn.modal=function(c){return this.each(function(){var d=a(this),e=d.data("modal"),f=a.extend({},a.fn.modal.defaults,d.data(),typeof c=="object"&&c);e||d.data("modal",e=new b(this,f)),typeof c=="string"?e[c]():f.show&&e.show()})},a.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},a.fn.modal.Constructor=b,a.fn.modal.noConflict=function(){return a.fn.modal=c,this},a(document).on("click.modal.data-api",'[data-toggle="modal"]',function(b){var c=a(this),d=c.attr("href"),e=a(c.attr("data-target")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=e.data("modal")?"toggle":a.extend({remote:!/#/.test(d)&&d},e.data(),c.data());b.preventDefault(),e.modal(f).one("hide",function(){c.focus()})})}(window.jQuery),!function(a){function d(){a(".dropdown-backdrop").remove(),a(b).each(function(){e(a(this)).removeClass("open")})}function e(b){var c=b.attr("data-target"),d;c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,"")),d=c&&a(c);if(!d||!d.length)d=b.parent();return d}var b="[data-toggle=dropdown]",c=function(b){var c=a(b).on("click.dropdown.data-api",this.toggle);a("html").on("click.dropdown.data-api",function(){c.parent().removeClass("open")})};c.prototype={constructor:c,toggle:function(b){var c=a(this),f,g;if(c.is(".disabled, :disabled"))return;return f=e(c),g=f.hasClass("open"),d(),g||("ontouchstart"in document.documentElement&&a('<div class="dropdown-backdrop"/>').insertBefore(a(this)).on("click",d),f.toggleClass("open")),c.focus(),!1},keydown:function(c){var d,f,g,h,i,j;if(!/(38|40|27)/.test(c.keyCode))return;d=a(this),c.preventDefault(),c.stopPropagation();if(d.is(".disabled, :disabled"))return;h=e(d),i=h.hasClass("open");if(!i||i&&c.keyCode==27)return c.which==27&&h.find(b).focus(),d.click();f=a("[role=menu] li:not(.divider):visible a",h);if(!f.length)return;j=f.index(f.filter(":focus")),c.keyCode==38&&j>0&&j--,c.keyCode==40&&j<f.length-1&&j++,~j||(j=0),f.eq(j).focus()}};var f=a.fn.dropdown;a.fn.dropdown=function(b){return this.each(function(){var d=a(this),e=d.data("dropdown");e||d.data("dropdown",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.dropdown.Constructor=c,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=f,this},a(document).on("click.dropdown.data-api",d).on("click.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.dropdown.data-api",b,c.prototype.toggle).on("keydown.dropdown.data-api",b+", [role=menu]",c.prototype.keydown)}(window.jQuery),!function(a){function b(b,c){var d=a.proxy(this.process,this),e=a(b).is("body")?a(window):a(b),f;this.options=a.extend({},a.fn.scrollspy.defaults,c),this.$scrollElement=e.on("scroll.scroll-spy.data-api",d),this.selector=(this.options.target||(f=a(b).attr("href"))&&f.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=a("body"),this.refresh(),this.process()}b.prototype={constructor:b,refresh:function(){var b=this,c;this.offsets=a([]),this.targets=a([]),c=this.$body.find(this.selector).map(function(){var c=a(this),d=c.data("target")||c.attr("href"),e=/^#\w/.test(d)&&a(d);return e&&e.length&&[[e.position().top+(!a.isWindow(b.$scrollElement.get(0))&&b.$scrollElement.scrollTop()),d]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){b.offsets.push(this[0]),b.targets.push(this[1])})},process:function(){var a=this.$scrollElement.scrollTop()+this.options.offset,b=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,c=b-this.$scrollElement.height(),d=this.offsets,e=this.targets,f=this.activeTarget,g;if(a>=c)return f!=(g=e.last()[0])&&this.activate(g);for(g=d.length;g--;)f!=e[g]&&a>=d[g]&&(!d[g+1]||a<=d[g+1])&&this.activate(e[g])},activate:function(b){var c,d;this.activeTarget=b,a(this.selector).parent(".active").removeClass("active"),d=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',c=a(d).parent("li").addClass("active"),c.parent(".dropdown-menu").length&&(c=c.closest("li.dropdown").addClass("active")),c.trigger("activate")}};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("scrollspy"),f=typeof c=="object"&&c;e||d.data("scrollspy",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.defaults={offset:10},a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),!function(a){var b=function(b){this.element=a(b)};b.prototype={constructor:b,show:function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target"),e,f,g;d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,""));if(b.parent("li").hasClass("active"))return;e=c.find(".active:last a")[0],g=a.Event("show",{relatedTarget:e}),b.trigger(g);if(g.isDefaultPrevented())return;f=a(d),this.activate(b.parent("li"),c),this.activate(f,f.parent(),function(){b.trigger({type:"shown",relatedTarget:e})})},activate:function(b,c,d){function g(){e.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),f?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var e=c.find("> .active"),f=d&&a.support.transition&&e.hasClass("fade");f?e.one(a.support.transition.end,g):g(),e.removeClass("in")}};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("tab");e||d.data("tab",e=new b(this)),typeof c=="string"&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),!function(a){var b=function(a,b){this.init("tooltip",a,b)};b.prototype={constructor:b,init:function(b,c,d){var e,f,g,h,i;this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.enabled=!0,g=this.options.trigger.split(" ");for(i=g.length;i--;)h=g[i],h=="click"?this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this)):h!="manual"&&(e=h=="hover"?"mouseenter":"focus",f=h=="hover"?"mouseleave":"blur",this.$element.on(e+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(f+"."+this.type,this.options.selector,a.proxy(this.leave,this)));this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(b){return b=a.extend({},a.fn[this.type].defaults,this.$element.data(),b),b.delay&&typeof b.delay=="number"&&(b.delay={show:b.delay,hide:b.delay}),b},enter:function(b){var c=a.fn[this.type].defaults,d={},e;this._options&&a.each(this._options,function(a,b){c[a]!=b&&(d[a]=b)},this),e=a(b.currentTarget)[this.type](d).data(this.type);if(!e.options.delay||!e.options.delay.show)return e.show();clearTimeout(this.timeout),e.hoverState="in",this.timeout=setTimeout(function(){e.hoverState=="in"&&e.show()},e.options.delay.show)},leave:function(b){var c=a(b.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!c.options.delay||!c.options.delay.hide)return c.hide();c.hoverState="out",this.timeout=setTimeout(function(){c.hoverState=="out"&&c.hide()},c.options.delay.hide)},show:function(){var b,c,d,e,f,g,h=a.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(h);if(h.isDefaultPrevented())return;b=this.tip(),this.setContent(),this.options.animation&&b.addClass("fade"),f=typeof this.options.placement=="function"?this.options.placement.call(this,b[0],this.$element[0]):this.options.placement,b.detach().css({top:0,left:0,display:"block"}),this.options.container?b.appendTo(this.options.container):b.insertAfter(this.$element),c=this.getPosition(),d=b[0].offsetWidth,e=b[0].offsetHeight;switch(f){case"bottom":g={top:c.top+c.height,left:c.left+c.width/2-d/2};break;case"top":g={top:c.top-e,left:c.left+c.width/2-d/2};break;case"left":g={top:c.top+c.height/2-e/2,left:c.left-d};break;case"right":g={top:c.top+c.height/2-e/2,left:c.left+c.width}}this.applyPlacement(g,f),this.$element.trigger("shown")}},applyPlacement:function(a,b){var c=this.tip(),d=c[0].offsetWidth,e=c[0].offsetHeight,f,g,h,i;c.offset(a).addClass(b).addClass("in"),f=c[0].offsetWidth,g=c[0].offsetHeight,b=="top"&&g!=e&&(a.top=a.top+e-g,i=!0),b=="bottom"||b=="top"?(h=0,a.left<0&&(h=a.left*-2,a.left=0,c.offset(a),f=c[0].offsetWidth,g=c[0].offsetHeight),this.replaceArrow(h-d+f,f,"left")):this.replaceArrow(g-e,g,"top"),i&&c.offset(a)},replaceArrow:function(a,b,c){this.arrow().css(c,a?50*(1-a/b)+"%":"")},setContent:function(){var a=this.tip(),b=this.getTitle();a.find(".tooltip-inner")[this.options.html?"html":"text"](b),a.removeClass("fade in top bottom left right")},hide:function(){function e(){var b=setTimeout(function(){c.off(a.support.transition.end).detach()},500);c.one(a.support.transition.end,function(){clearTimeout(b),c.detach()})}var b=this,c=this.tip(),d=a.Event("hide");this.$element.trigger(d);if(d.isDefaultPrevented())return;return c.removeClass("in"),a.support.transition&&this.$tip.hasClass("fade")?e():c.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var a=this.$element;(a.attr("title")||typeof a.attr("data-original-title")!="string")&&a.attr("data-original-title",a.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var b=this.$element[0];return a.extend({},typeof b.getBoundingClientRect=="function"?b.getBoundingClientRect():{width:b.offsetWidth,height:b.offsetHeight},this.$element.offset())},getTitle:function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||(typeof c.title=="function"?c.title.call(b[0]):c.title),a},tip:function(){return this.$tip=this.$tip||a(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(b){var c=b?a(b.currentTarget)[this.type](this._options).data(this.type):this;c.tip().hasClass("in")?c.hide():c.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var c=a.fn.tooltip;a.fn.tooltip=function(c){return this.each(function(){var d=a(this),e=d.data("tooltip"),f=typeof c=="object"&&c;e||d.data("tooltip",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.tooltip.Constructor=b,a.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},a.fn.tooltip.noConflict=function(){return a.fn.tooltip=c,this}}(window.jQuery),!function(a){var b=function(a,b){this.init("popover",a,b)};b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype,{constructor:b,setContent:function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var a,b=this.$element,c=this.options;return a=(typeof c.content=="function"?c.content.call(b[0]):c.content)||b.attr("data-content"),a},tip:function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("popover"),f=typeof c=="object"&&c;e||d.data("popover",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.defaults=a.extend({},a.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),!function(a){var b=function(b,c){this.options=a.extend({},a.fn.affix.defaults,c),this.$window=a(window).on("scroll.affix.data-api",a.proxy(this.checkPosition,this)).on("click.affix.data-api",a.proxy(function(){setTimeout(a.proxy(this.checkPosition,this),1)},this)),this.$element=a(b),this.checkPosition()};b.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var b=a(document).height(),c=this.$window.scrollTop(),d=this.$element.offset(),e=this.options.offset,f=e.bottom,g=e.top,h="affix affix-top affix-bottom",i;typeof e!="object"&&(f=g=e),typeof g=="function"&&(g=e.top()),typeof f=="function"&&(f=e.bottom()),i=this.unpin!=null&&c+this.unpin<=d.top?!1:f!=null&&d.top+this.$element.height()>=b-f?"bottom":g!=null&&c<=g?"top":!1;if(this.affixed===i)return;this.affixed=i,this.unpin=i=="bottom"?d.top-c:null,this.$element.removeClass(h).addClass("affix"+(i?"-"+i:""))};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("affix"),f=typeof c=="object"&&c;e||d.data("affix",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.defaults={offset:0},a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery),!function(a){var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function f(){e.trigger("closed").remove()}var c=a(this),d=c.attr("data-target"),e;d||(d=c.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),e=a(d),b&&b.preventDefault(),e.length||(e=c.hasClass("alert")?c:c.parent()),e.trigger(b=a.Event("close"));if(b.isDefaultPrevented())return;e.removeClass("in"),a.support.transition&&e.hasClass("fade")?e.on(a.support.transition.end,f):f()};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("alert");e||d.data("alert",e=new c(this)),typeof b=="string"&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.alert.data-api",b,c.prototype.close)}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.button.defaults,c)};b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.data(),e=c.is("input")?"val":"html";a+="Text",d.resetText||c.data("resetText",c[e]()),c[e](d[a]||this.options[a]),setTimeout(function(){a=="loadingText"?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons-radio"]');a&&a.find(".active").removeClass("active"),this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("button"),f=typeof c=="object"&&c;e||d.data("button",e=new b(this,f)),c=="toggle"?e.toggle():c&&e.setState(c)})},a.fn.button.defaults={loadingText:"loading..."},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle")})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.collapse.defaults,c),this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.prototype={constructor:b,dimension:function(){var a=this.$element.hasClass("width");return a?"width":"height"},show:function(){var b,c,d,e;if(this.transitioning||this.$element.hasClass("in"))return;b=this.dimension(),c=a.camelCase(["scroll",b].join("-")),d=this.$parent&&this.$parent.find("> .accordion-group > .in");if(d&&d.length){e=d.data("collapse");if(e&&e.transitioning)return;d.collapse("hide"),e||d.data("collapse",null)}this.$element[b](0),this.transition("addClass",a.Event("show"),"shown"),a.support.transition&&this.$element[b](this.$element[0][c])},hide:function(){var b;if(this.transitioning||!this.$element.hasClass("in"))return;b=this.dimension(),this.reset(this.$element[b]()),this.transition("removeClass",a.Event("hide"),"hidden"),this.$element[b](0)},reset:function(a){var b=this.dimension();return this.$element.removeClass("collapse")[b](a||"auto")[0].offsetWidth,this.$element[a!==null?"addClass":"removeClass"]("collapse"),this},transition:function(b,c,d){var e=this,f=function(){c.type=="show"&&e.reset(),e.transitioning=0,e.$element.trigger(d)};this.$element.trigger(c);if(c.isDefaultPrevented())return;this.transitioning=1,this.$element[b]("in"),a.support.transition&&this.$element.hasClass("collapse")?this.$element.one(a.support.transition.end,f):f()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("collapse"),f=a.extend({},a.fn.collapse.defaults,d.data(),typeof c=="object"&&c);e||d.data("collapse",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.collapse.defaults={toggle:!0},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.collapse.data-api","[data-toggle=collapse]",function(b){var c=a(this),d,e=c.attr("data-target")||b.preventDefault()||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),f=a(e).data("collapse")?"toggle":c.data();c[a(e).hasClass("in")?"addClass":"removeClass"]("collapsed"),a(e).collapse(f)})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.options.pause=="hover"&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.prototype={cycle:function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(b){var c=this.getActiveIndex(),d=this;if(b>this.$items.length-1||b<0)return;return this.sliding?this.$element.one("slid",function(){d.to(b)}):c==b?this.pause().cycle():this.slide(b>c?"next":"prev",a(this.$items[b]))},pause:function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g=b=="next"?"left":"right",h=b=="next"?"first":"last",i=this,j;this.sliding=!0,f&&this.pause(),e=e.length?e:this.$element.find(".item")[h](),j=a.Event("slide",{relatedTarget:e[0],direction:g});if(e.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")}));if(a.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(j);if(j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),this.$element.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)})}else{this.$element.trigger(j);if(j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("carousel"),f=a.extend({},a.fn.carousel.defaults,typeof c=="object"&&c),g=typeof c=="string"?c:f.slide;e||d.data("carousel",e=new b(this,f)),typeof c=="number"?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.defaults={interval:5e3,pause:"hover"},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c=a(this),d,e=a(c.attr("data-target")||(d=c.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),c.data()),g;e.carousel(f),(g=c.attr("data-slide-to"))&&e.data("carousel").pause().to(g).cycle(),b.preventDefault()})}(window.jQuery),!function(a){var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.typeahead.defaults,c),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=a(this.options.menu),this.shown=!1,this.listen()};b.prototype={constructor:b,select:function(){var a=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(a)).change(),this.hide()},updater:function(a){return a},show:function(){var b=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:b.top+b.height,left:b.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){var c;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(c=a.isFunction(this.source)?this.source(this.query,a.proxy(this.process,this)):this.source,c?this.process(c):this)},process:function(b){var c=this;return b=a.grep(b,function(a){return c.matcher(a)}),b=this.sorter(b),b.length?this.render(b.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(a){return~a.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){var b=[],c=[],d=[],e;while(e=a.shift())e.toLowerCase().indexOf(this.query.toLowerCase())?~e.indexOf(this.query)?c.push(e):d.push(e):b.push(e);return b.concat(c,d)},highlighter:function(a){var b=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return a.replace(new RegExp("("+b+")","ig"),function(a,b){return"<strong>"+b+"</strong>"})},render:function(b){var c=this;return b=a(b).map(function(b,d){return b=a(c.options.item).attr("data-value",d),b.find("a").html(c.highlighter(d)),b[0]}),b.first().addClass("active"),this.$menu.html(b),this},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active")},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active")},listen:function(){this.$element.on("focus",a.proxy(this.focus,this)).on("blur",a.proxy(this.blur,this)).on("keypress",a.proxy(this.keypress,this)).on("keyup",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",a.proxy(this.keydown,this)),this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this))},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b=typeof this.$element[a]=="function"),b},move:function(a){if(!this.shown)return;switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:a.preventDefault(),this.prev();break;case 40:a.preventDefault(),this.next()}a.stopPropagation()},keydown:function(b){this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.move(b)},keypress:function(a){if(this.suppressKeyPressRepeat)return;this.move(a)},keyup:function(a){switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}a.stopPropagation(),a.preventDefault()},focus:function(a){this.focused=!0},blur:function(a){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(a){a.stopPropagation(),a.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){return this.each(function(){var d=a(this),e=d.data("typeahead"),f=typeof c=="object"&&c;e||d.data("typeahead",e=new b(this,f)),typeof c=="string"&&e[c]()})},a.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);if(c.data("typeahead"))return;c.typeahead(c.data())})}(window.jQuery)
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.fixture.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.fixture.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.fixture.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,614 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:29 GMT
- * Licensed MIT
- * Includes: can/util/fixture
- * Download from: http://canjs.com
- */
-(function(can) {
-
- // Get the URL from old Steal root, new Steal config or can.fixture.rootUrl
- var getUrl = function(url) {
- if (typeof steal !== 'undefined') {
- if (can.isFunction(steal.config)) {
- return steal.config().root.mapJoin(url).toString();
- }
- return steal.root.join(url).toString();
- }
- return (can.fixture.rootUrl || '') + url;
- }
-
- var updateSettings = function(settings, originalOptions) {
- if (!can.fixture.on) {
- return;
- }
-
- //simple wrapper for logging
- var _logger = function(type, arr) {
- if (console.log.apply) {
- Function.prototype.call.apply(console[type], [console].concat(arr));
- // console[type].apply(console, arr)
- } else {
- console[type](arr)
- }
- },
- log = function() {
- if (typeof steal !== 'undefined' && steal.dev) {
- steal.dev.log('fixture INFO: ' + Array.prototype.slice.call(arguments).join(' '));
- }
- }
-
- // We always need the type which can also be called method, default to GET
- settings.type = settings.type || settings.method || 'GET';
-
- // add the fixture option if programmed in
- var data = overwrite(settings);
-
- // if we don't have a fixture, do nothing
- if (!settings.fixture) {
- if (window.location.protocol === "file:") {
- log("ajax request to " + settings.url + ", no fixture found");
- }
- return;
- }
-
- //if referencing something else, update the fixture option
- if (typeof settings.fixture === "string" && can.fixture[settings.fixture]) {
- settings.fixture = can.fixture[settings.fixture];
- }
-
- // if a string, we just point to the right url
- if (typeof settings.fixture == "string") {
- var url = settings.fixture;
-
- if (/^\/\//.test(url)) {
- // this lets us use rootUrl w/o having steal...
- url = getUrl(settings.fixture.substr(2));
- }
-
- if (data) {
- // Template static fixture URLs
- url = can.sub(url, data);
- }
-
- delete settings.fixture;
-
-
-
- settings.url = url;
- settings.data = null;
- settings.type = "GET";
- if (!settings.error) {
- settings.error = function(xhr, error, message) {
- throw "fixtures.js Error " + error + " " + message;
- };
- }
- } else {
-
-
- //it's a function ... add the fixture datatype so our fixture transport handles it
- // TODO: make everything go here for timing and other fun stuff
- // add to settings data from fixture ...
- settings.dataTypes && settings.dataTypes.splice(0, 0, "fixture");
-
- if (data && originalOptions) {
- can.extend(originalOptions.data, data)
- }
- }
- },
- // A helper function that takes what's called with response
- // and moves some common args around to make it easier to call
- extractResponse = function(status, statusText, responses, headers) {
- // if we get response(RESPONSES, HEADERS)
- if (typeof status != "number") {
- headers = statusText;
- responses = status;
- statusText = "success"
- status = 200;
- }
- // if we get response(200, RESPONSES, HEADERS)
- if (typeof statusText != "string") {
- headers = responses;
- responses = statusText;
- statusText = "success";
- }
- if (status >= 400 && status <= 599) {
- this.dataType = "text"
- }
- return [status, statusText, extractResponses(this, responses), headers];
- },
- // If we get data instead of responses,
- // make sure we provide a response type that matches the first datatype (typically json)
- extractResponses = function(settings, responses) {
- var next = settings.dataTypes ? settings.dataTypes[0] : (settings.dataType || 'json');
- if (!responses || !responses[next]) {
- var tmp = {}
- tmp[next] = responses;
- responses = tmp;
- }
- return responses;
- };
-
- //used to check urls
- // check if jQuery
- if (can.ajaxPrefilter && can.ajaxTransport) {
-
- // the pre-filter needs to re-route the url
- can.ajaxPrefilter(updateSettings);
-
- can.ajaxTransport("fixture", function(s, original) {
- // remove the fixture from the datatype
- s.dataTypes.shift();
-
- //we'll return the result of the next data type
- var timeout, stopped = false;
-
- return {
- send: function(headers, callback) {
- // we'll immediately wait the delay time for all fixtures
- timeout = setTimeout(function() {
- // if the user wants to call success on their own, we allow it ...
- var success = function() {
- if (stopped === false) {
- callback.apply(null, extractResponse.apply(s, arguments));
- }
- },
- // get the result form the fixture
- result = s.fixture(original, success, headers, s);
- if (result !== undefined) {
- // make sure the result has the right dataType
- callback(200, "success", extractResponses(s, result), {});
- }
- }, can.fixture.delay);
- },
- abort: function() {
- stopped = true;
- clearTimeout(timeout)
- }
- };
- });
- } else {
- var AJAX = can.ajax;
- can.ajax = function(settings) {
- updateSettings(settings, settings);
- if (settings.fixture) {
- var timeout, d = new can.Deferred(),
- stopped = false;
-
- //TODO this should work with response
- d.getResponseHeader = function() {}
-
- // call success and fail
- d.then(settings.success, settings.fail);
-
- // abort should stop the timeout and calling success
- d.abort = function() {
- clearTimeout(timeout);
- stopped = true;
- d.reject(d)
- }
- // set a timeout that simulates making a request ....
- timeout = setTimeout(function() {
- // if the user wants to call success on their own, we allow it ...
- var success = function() {
- var response = extractResponse.apply(settings, arguments),
- status = response[0];
-
- if ((status >= 200 && status < 300 || status === 304) && stopped === false) {
- d.resolve(response[2][settings.dataType])
- } else {
- // TODO probably resolve better
- d.reject(d, 'error', response[1]);
- }
- },
- // get the result form the fixture
- result = settings.fixture(settings, success, settings.headers, settings);
- if (result !== undefined) {
- d.resolve(result)
- }
- }, can.fixture.delay);
-
- return d;
- } else {
- return AJAX(settings);
- }
- }
- }
-
- var typeTest = /^(script|json|text|jsonp)$/,
- // a list of 'overwrite' settings object
- overwrites = [],
- // returns the index of an overwrite function
- find = function(settings, exact) {
- for (var i = 0; i < overwrites.length; i++) {
- if ($fixture._similar(settings, overwrites[i], exact)) {
- return i;
- }
- }
- return -1;
- },
- // overwrites the settings fixture if an overwrite matches
- overwrite = function(settings) {
- var index = find(settings);
- if (index > -1) {
- settings.fixture = overwrites[index].fixture;
- return $fixture._getData(overwrites[index].url, settings.url)
- }
-
- },
- // Makes an attempt to guess where the id is at in the url and returns it.
- getId = function(settings) {
- var id = settings.data.id;
-
- if (id === undefined && typeof settings.data === "number") {
- id = settings.data;
- }
-
-
-
- if (id === undefined) {
- settings.url.replace(/\/(\d+)(\/|$|\.)/g, function(all, num) {
- id = num;
- });
- }
-
- if (id === undefined) {
- id = settings.url.replace(/\/(\w+)(\/|$|\.)/g, function(all, num) {
- if (num != 'update') {
- id = num;
- }
- })
- }
-
- if (id === undefined) { // if still not set, guess a random number
- id = Math.round(Math.random() * 1000)
- }
-
- return id;
- };
-
- var $fixture = can.fixture = function(settings, fixture) {
- // if we provide a fixture ...
- if (fixture !== undefined) {
- if (typeof settings == 'string') {
- // handle url strings
- var matches = settings.match(/(GET|POST|PUT|DELETE) (.+)/i);
- if (!matches) {
- settings = {
- url: settings
- };
- } else {
- settings = {
- url: matches[2],
- type: matches[1]
- };
- }
-
- }
-
- //handle removing. An exact match if fixture was provided, otherwise, anything similar
- var index = find(settings, !! fixture);
- if (index > -1) {
- overwrites.splice(index, 1)
- }
- if (fixture == null) {
- return
- }
- settings.fixture = fixture;
- overwrites.push(settings)
- } else {
- can.each(settings, function(fixture, url) {
- $fixture(url, fixture);
- })
- }
- };
- var replacer = can.replacer;
-
- can.extend(can.fixture, {
- // given ajax settings, find an overwrite
- _similar: function(settings, overwrite, exact) {
- if (exact) {
- return can.Object.same(settings, overwrite, {
- fixture: null
- })
- } else {
- return can.Object.subset(settings, overwrite, can.fixture._compare)
- }
- },
- _compare: {
- url: function(a, b) {
- return !!$fixture._getData(b, a)
- },
- fixture: null,
- type: "i"
- },
- // gets data from a url like "/todo/{id}" given "todo/5"
- _getData: function(fixtureUrl, url) {
- var order = [],
- fixtureUrlAdjusted = fixtureUrl.replace('.', '\\.').replace('?', '\\?'),
- res = new RegExp(fixtureUrlAdjusted.replace(replacer, function(whole, part) {
- order.push(part)
- return "([^\/]+)"
- }) + "$").exec(url),
- data = {};
-
- if (!res) {
- return null;
- }
- res.shift();
- can.each(order, function(name) {
- data[name] = res.shift()
- })
- return data;
- },
-
- store: function(types, count, make, filter) {
-
- var items = [], // TODO: change this to a hash
- currentId = 0,
- findOne = function(id) {
- for (var i = 0; i < items.length; i++) {
- if (id == items[i].id) {
- return items[i];
- }
- }
- },
- methods = {};
-
- if (typeof types === "string") {
- types = [types + "s", types]
- } else if (!can.isArray(types)) {
- filter = make;
- make = count;
- count = types;
- }
-
- // make all items
- can.extend(methods, {
-
- findAll: function(request) {
- request = request || {}
- //copy array of items
- var retArr = items.slice(0);
- request.data = request.data || {};
- //sort using order
- //order looks like ["age ASC","gender DESC"]
- can.each((request.data.order || []).slice(0).reverse(), function(name) {
- var split = name.split(" ");
- retArr = retArr.sort(function(a, b) {
- if (split[1].toUpperCase() !== "ASC") {
- if (a[split[0]] < b[split[0]]) {
- return 1;
- } else if (a[split[0]] == b[split[0]]) {
- return 0
- } else {
- return -1;
- }
- } else {
- if (a[split[0]] < b[split[0]]) {
- return -1;
- } else if (a[split[0]] == b[split[0]]) {
- return 0
- } else {
- return 1;
- }
- }
- });
- });
-
- //group is just like a sort
- can.each((request.data.group || []).slice(0).reverse(), function(name) {
- var split = name.split(" ");
- retArr = retArr.sort(function(a, b) {
- return a[split[0]] > b[split[0]];
- });
- });
-
- var offset = parseInt(request.data.offset, 10) || 0,
- limit = parseInt(request.data.limit, 10) || (items.length - offset),
- i = 0;
-
- //filter results if someone added an attr like parentId
- for (var param in request.data) {
- i = 0;
- if (request.data[param] !== undefined && // don't do this if the value of the param is null (ignore it)
- (param.indexOf("Id") != -1 || param.indexOf("_id") != -1)) {
- while (i < retArr.length) {
- if (request.data[param] != retArr[i][param]) {
- retArr.splice(i, 1);
- } else {
- i++;
- }
- }
- }
- }
-
- if (filter) {
- i = 0;
- while (i < retArr.length) {
- if (!filter(retArr[i], request)) {
- retArr.splice(i, 1);
- } else {
- i++;
- }
- }
- }
-
- //return data spliced with limit and offset
- return {
- "count": retArr.length,
- "limit": request.data.limit,
- "offset": request.data.offset,
- "data": retArr.slice(offset, offset + limit)
- };
- },
-
- findOne: function(request, response) {
- var item = findOne(getId(request));
- response(item ? item : undefined);
- },
-
- update: function(request, response) {
- var id = getId(request);
-
- // TODO: make it work with non-linear ids ..
- can.extend(findOne(id), request.data);
- response({
- id: getId(request)
- }, {
- location: request.url || "/" + getId(request)
- });
- },
-
- destroy: function(request) {
- var id = getId(request);
- for (var i = 0; i < items.length; i++) {
- if (items[i].id == id) {
- items.splice(i, 1);
- break;
- }
- }
-
- // TODO: make it work with non-linear ids ..
- can.extend(findOne(id) || {}, request.data);
- return {};
- },
-
- create: function(settings, response) {
- var item = make(items.length, items);
-
- can.extend(item, settings.data);
-
- if (!item.id) {
- item.id = currentId++;
- }
-
- items.push(item);
- response({
- id: item.id
- }, {
- location: settings.url + "/" + item.id
- })
- }
- });
-
- var reset = function() {
- items = [];
- for (var i = 0; i < (count); i++) {
- //call back provided make
- var item = make(i, items);
-
- if (!item.id) {
- item.id = i;
- }
- currentId = Math.max(item.id + 1, currentId + 1) || items.length;
- items.push(item);
- }
- if (can.isArray(types)) {
- can.fixture["~" + types[0]] = items;
- can.fixture["-" + types[0]] = methods.findAll;
- can.fixture["-" + types[1]] = methods.findOne;
- can.fixture["-" + types[1] + "Update"] = methods.update;
- can.fixture["-" + types[1] + "Destroy"] = methods.destroy;
- can.fixture["-" + types[1] + "Create"] = methods.create;
- }
-
- }
- reset()
- // if we have types given add them to can.fixture
-
-
- return can.extend({
- getId: getId,
-
- find: function(settings) {
- return findOne(getId(settings));
- },
-
- reset: reset
- }, methods);
- },
-
- rand: function(arr, min, max) {
- if (typeof arr == 'number') {
- if (typeof min == 'number') {
- return arr + Math.floor(Math.random() * (min - arr));
- } else {
- return Math.floor(Math.random() * arr);
- }
-
- }
- var rand = arguments.callee;
- // get a random set
- if (min === undefined) {
- return rand(arr, rand(arr.length + 1))
- }
- // get a random selection of arr
- var res = [];
- arr = arr.slice(0);
- // set max
- if (!max) {
- max = min;
- }
- //random max
- max = min + Math.round(rand(max - min))
- for (var i = 0; i < max; i++) {
- res.push(arr.splice(rand(arr.length), 1)[0])
- }
- return res;
- },
-
- xhr: function(xhr) {
- return can.extend({}, {
- abort: can.noop,
- getAllResponseHeaders: function() {
- return "";
- },
- getResponseHeader: function() {
- return "";
- },
- open: can.noop,
- overrideMimeType: can.noop,
- readyState: 4,
- responseText: "",
- responseXML: null,
- send: can.noop,
- setRequestHeader: can.noop,
- status: 200,
- statusText: "OK"
- }, xhr);
- },
-
- on: true
- });
-
- can.fixture.delay = 200;
-
-
- can.fixture.rootUrl = getUrl('');
-
- can.fixture["-handleFunction"] = function(settings) {
- if (typeof settings.fixture === "string" && can.fixture[settings.fixture]) {
- settings.fixture = can.fixture[settings.fixture];
- }
- if (typeof settings.fixture == "function") {
- setTimeout(function() {
- if (settings.success) {
- settings.success.apply(null, settings.fixture(settings, "success"));
- }
- if (settings.complete) {
- settings.complete.apply(null, settings.fixture(settings, "complete"));
- }
- }, can.fixture.delay);
- return true;
- }
- return false;
- };
-
- //Expose this for fixture debugging
- can.fixture.overwrites = overwrites;
- can.fixture.make = can.fixture.store;
- return can.fixture;
- })(can);
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,4367 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:27 GMT
- * Licensed MIT
- * Includes: can/construct,can/observe,can/observe/compute,can/model,can/view,can/view/ejs,can/control,can/route,can/control/route
- * Download from: http://canjs.com
- */
-(function(undefined) {
-
- // ## util/can.js
- var __m5 = (function() {
- var can = window.can || {};
- if (typeof GLOBALCAN === 'undefined' || GLOBALCAN !== false) {
- window.can = can;
- }
-
- can.isDeferred = function(obj) {
- var isFunction = this.isFunction;
- // Returns `true` if something looks like a deferred.
- return obj && isFunction(obj.then) && isFunction(obj.pipe);
- };
-
- var cid = 0;
- can.cid = function(object, name) {
- if (object._cid) {
- return object._cid
- } else {
- return object._cid = (name || "") + (++cid)
- }
- }
- can.VERSION = '@EDGE';
- return can;
- })();
-
- // ## util/array/each.js
- var __m6 = (function(can) {
- can.each = function(elements, callback, context) {
- var i = 0,
- key;
- if (elements) {
- if (typeof elements.length === 'number' && elements.pop) {
- if (elements.attr) {
- elements.attr('length');
- }
- for (key = elements.length; i < key; i++) {
- if (callback.call(context || elements[i], elements[i], i, elements) === false) {
- break;
- }
- }
- } else if (elements.hasOwnProperty) {
- for (key in elements) {
- if (elements.hasOwnProperty(key)) {
- if (callback.call(context || elements[key], elements[key], key, elements) === false) {
- break;
- }
- }
- }
- }
- }
- return elements;
- };
-
- return can;
- })(__m5);
-
- // ## util/jquery/jquery.js
- var __m3 = (function($, can) {
- // _jQuery node list._
- $.extend(can, $, {
- trigger: function(obj, event, args) {
- if (obj.trigger) {
- obj.trigger(event, args);
- } else {
- $.event.trigger(event, args, obj, true);
- }
- },
- addEvent: function(ev, cb) {
- $([this]).bind(ev, cb);
- return this;
- },
- removeEvent: function(ev, cb) {
- $([this]).unbind(ev, cb);
- return this;
- },
- // jquery caches fragments, we always needs a new one
- buildFragment: function(elems, context) {
- var oldFragment = $.buildFragment,
- ret;
-
- elems = [elems];
- // Set context per 1.8 logic
- context = context || document;
- context = !context.nodeType && context[0] || context;
- context = context.ownerDocument || context;
-
- ret = oldFragment.call(jQuery, elems, context);
-
- return ret.cacheable ? $.clone(ret.fragment) : ret.fragment || ret;
- },
- $: $,
- each: can.each
- });
-
- // Wrap binding functions.
- $.each(['bind', 'unbind', 'undelegate', 'delegate'], function(i, func) {
- can[func] = function() {
- var t = this[func] ? this : $([this]);
- t[func].apply(t, arguments);
- return this;
- };
- });
-
- // Wrap modifier functions.
- $.each(["append", "filter", "addClass", "remove", "data", "get"], function(i, name) {
- can[name] = function(wrapped) {
- return wrapped[name].apply(wrapped, can.makeArray(arguments).slice(1));
- };
- });
-
- // Memory safe destruction.
- var oldClean = $.cleanData;
-
- $.cleanData = function(elems) {
- $.each(elems, function(i, elem) {
- if (elem) {
- can.trigger(elem, "destroyed", [], false);
- }
- });
- oldClean(elems);
- };
-
- return can;
- })(jQuery, __m5, __m6);
-
- // ## util/string/string.js
- var __m2 = (function(can) {
- // ##string.js
- // _Miscellaneous string utility functions._
-
- // Several of the methods in this plugin use code adapated from Prototype
- // Prototype JavaScript framework, version 1.6.0.1.
- // © 2005-2007 Sam Stephenson
- var strUndHash = /_|-/,
- strColons = /\=\=/,
- strWords = /([A-Z]+)([A-Z][a-z])/g,
- strLowUp = /([a-z\d])([A-Z])/g,
- strDash = /([a-z\d])([A-Z])/g,
- strReplacer = /\{([^\}]+)\}/g,
- strQuote = /"/g,
- strSingleQuote = /'/g,
-
- // Returns the `prop` property from `obj`.
- // If `add` is true and `prop` doesn't exist in `obj`, create it as an
- // empty object.
- getNext = function(obj, prop, add) {
- var result = obj[prop];
-
- if (result === undefined && add === true) {
- result = obj[prop] = {}
- }
- return result
- },
-
- // Returns `true` if the object can have properties (no `null`s).
- isContainer = function(current) {
- return (/^f|^o/).test(typeof current);
- };
-
- can.extend(can, {
- // Escapes strings for HTML.
-
- esc: function(content) {
- // Convert bad values into empty strings
- var isInvalid = content === null || content === undefined || (isNaN(content) && ("" + content === 'NaN'));
- return ("" + (isInvalid ? '' : content))
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(strQuote, '"')
- .replace(strSingleQuote, "'");
- },
-
-
- getObject: function(name, roots, add) {
-
- // The parts of the name we are looking up
- // `['App','Models','Recipe']`
- var parts = name ? name.split('.') : [],
- length = parts.length,
- current,
- r = 0,
- i, container, rootsLength;
-
- // Make sure roots is an `array`.
- roots = can.isArray(roots) ? roots : [roots || window];
-
- rootsLength = roots.length
-
- if (!length) {
- return roots[0];
- }
-
- // For each root, mark it as current.
- for (r; r < rootsLength; r++) {
- current = roots[r];
- container = undefined;
-
- // Walk current to the 2nd to last object or until there
- // is not a container.
- for (i = 0; i < length && isContainer(current); i++) {
- container = current;
- current = getNext(container, parts[i]);
- }
-
- // If we found property break cycle
- if (container !== undefined && current !== undefined) {
- break
- }
- }
-
- // Remove property from found container
- if (add === false && current !== undefined) {
- delete container[parts[i - 1]]
- }
-
- // When adding property add it to the first root
- if (add === true && current === undefined) {
- current = roots[0]
-
- for (i = 0; i < length && isContainer(current); i++) {
- current = getNext(current, parts[i], true);
- }
- }
-
- return current;
- },
- // Capitalizes a string.
-
- capitalize: function(s, cache) {
- // Used to make newId.
- return s.charAt(0).toUpperCase() + s.slice(1);
- },
-
- // Underscores a string.
-
- underscore: function(s) {
- return s
- .replace(strColons, '/')
- .replace(strWords, '$1_$2')
- .replace(strLowUp, '$1_$2')
- .replace(strDash, '_')
- .toLowerCase();
- },
- // Micro-templating.
-
- sub: function(str, data, remove) {
- var obs = [];
-
- str = str || '';
-
- obs.push(str.replace(strReplacer, function(whole, inside) {
-
- // Convert inside to type.
- var ob = can.getObject(inside, data, remove === true ? false : undefined);
-
- if (ob === undefined) {
- obs = null;
- return "";
- }
-
- // If a container, push into objs (which will return objects found).
- if (isContainer(ob) && obs) {
- obs.push(ob);
- return "";
- }
-
- return "" + ob;
- }));
-
- return obs === null ? obs : (obs.length <= 1 ? obs[0] : obs);
- },
-
- // These regex's are used throughout the rest of can, so let's make
- // them available.
- replacer: strReplacer,
- undHash: strUndHash
- });
- return can;
- })(__m3);
-
- // ## construct/construct.js
- var __m1 = (function(can) {
-
- // ## construct.js
- // `can.Construct`
- // _This is a modified version of
- // [John Resig's class](http://ejohn.org/blog/simple-javascript-inheritance/).
- // It provides class level inheritance and callbacks._
-
- // A private flag used to initialize a new class instance without
- // initializing it's bindings.
- var initializing = 0;
-
-
- can.Construct = function() {
- if (arguments.length) {
- return can.Construct.extend.apply(can.Construct, arguments);
- }
- };
-
-
- can.extend(can.Construct, {
-
- newInstance: function() {
- // Get a raw instance object (`init` is not called).
- var inst = this.instance(),
- arg = arguments,
- args;
-
- // Call `setup` if there is a `setup`
- if (inst.setup) {
- args = inst.setup.apply(inst, arguments);
- }
-
- // Call `init` if there is an `init`
- // If `setup` returned `args`, use those as the arguments
- if (inst.init) {
- inst.init.apply(inst, args || arguments);
- }
-
- return inst;
- },
- // Overwrites an object with methods. Used in the `super` plugin.
- // `newProps` - New properties to add.
- // `oldProps` - Where the old properties might be (used with `super`).
- // `addTo` - What we are adding to.
- _inherit: function(newProps, oldProps, addTo) {
- can.extend(addTo || newProps, newProps || {})
- },
- // used for overwriting a single property.
- // this should be used for patching other objects
- // the super plugin overwrites this
- _overwrite: function(what, oldProps, propName, val) {
- what[propName] = val;
- },
- // Set `defaults` as the merger of the parent `defaults` and this
- // object's `defaults`. If you overwrite this method, make sure to
- // include option merging logic.
-
- setup: function(base, fullName) {
- this.defaults = can.extend(true, {}, base.defaults, this.defaults);
- },
- // Create's a new `class` instance without initializing by setting the
- // `initializing` flag.
- instance: function() {
-
- // Prevents running `init`.
- initializing = 1;
-
- var inst = new this();
-
- // Allow running `init`.
- initializing = 0;
-
- return inst;
- },
- // Extends classes.
-
- extend: function(fullName, klass, proto) {
- // Figure out what was passed and normalize it.
- if (typeof fullName != 'string') {
- proto = klass;
- klass = fullName;
- fullName = null;
- }
-
- if (!proto) {
- proto = klass;
- klass = null;
- }
- proto = proto || {};
-
- var _super_class = this,
- _super = this.prototype,
- name, shortName, namespace, prototype;
-
- // Instantiate a base class (but only create the instance,
- // don't run the init constructor).
- prototype = this.instance();
-
- // Copy the properties over onto the new prototype.
- can.Construct._inherit(proto, _super, prototype);
-
- // The dummy class constructor.
-
- function Constructor() {
- // All construction is actually done in the init method.
- if (!initializing) {
- return this.constructor !== Constructor && arguments.length ?
- // We are being called without `new` or we are extending.
- arguments.callee.extend.apply(arguments.callee, arguments) :
- // We are being called with `new`.
- this.constructor.newInstance.apply(this.constructor, arguments);
- }
- }
-
- // Copy old stuff onto class (can probably be merged w/ inherit)
- for (name in _super_class) {
- if (_super_class.hasOwnProperty(name)) {
- Constructor[name] = _super_class[name];
- }
- }
-
- // Copy new static properties on class.
- can.Construct._inherit(klass, _super_class, Constructor);
-
- // Setup namespaces.
- if (fullName) {
-
- var parts = fullName.split('.'),
- shortName = parts.pop(),
- current = can.getObject(parts.join('.'), window, true),
- namespace = current,
- _fullName = can.underscore(fullName.replace(/\./g, "_")),
- _shortName = can.underscore(shortName);
-
-
-
- current[shortName] = Constructor;
- }
-
- // Set things that shouldn't be overwritten.
- can.extend(Constructor, {
- constructor: Constructor,
- prototype: prototype,
-
- namespace: namespace,
-
- _shortName: _shortName,
-
- fullName: fullName,
- _fullName: _fullName
- });
-
- // Dojo and YUI extend undefined
- if (shortName !== undefined) {
- Constructor.shortName = shortName;
- }
-
- // Make sure our prototype looks nice.
- Constructor.prototype.constructor = Constructor;
-
-
- // Call the class `setup` and `init`
- var t = [_super_class].concat(can.makeArray(arguments)),
- args = Constructor.setup.apply(Constructor, t);
-
- if (Constructor.init) {
- Constructor.init.apply(Constructor, args || t);
- }
-
-
- return Constructor;
-
- }
-
- });
- return can.Construct;
- })(__m2);
-
- // ## util/bind/bind.js
- var __m8 = (function(can) {
-
-
- // ## Bind helpers
- can.bindAndSetup = function() {
- // Add the event to this object
- can.addEvent.apply(this, arguments);
- // If not initializing, and the first binding
- // call bindsetup if the function exists.
- if (!this._init) {
- if (!this._bindings) {
- this._bindings = 1;
- // setup live-binding
- this._bindsetup && this._bindsetup();
-
- } else {
- this._bindings++;
- }
-
- }
-
- return this;
- };
-
- can.unbindAndTeardown = function(ev, handler) {
- // Remove the event handler
- can.removeEvent.apply(this, arguments);
-
- this._bindings--;
- // If there are no longer any bindings and
- // there is a bindteardown method, call it.
- if (!this._bindings) {
- this._bindteardown && this._bindteardown();
- }
- return this;
- }
-
- return can;
-
- })(__m3);
-
- // ## observe/observe.js
- var __m7 = (function(can, bind) {
- // ## observe.js
- // `can.Observe`
- // _Provides the observable pattern for JavaScript Objects._
- // Returns `true` if something is an object with properties of its own.
- var canMakeObserve = function(obj) {
- return obj && !can.isDeferred(obj) && (can.isArray(obj) || can.isPlainObject(obj) || (obj instanceof can.Observe));
- },
-
- // Removes all listeners.
- unhookup = function(items, namespace) {
- return can.each(items, function(item) {
- if (item && item.unbind) {
- item.unbind("change" + namespace);
- }
- });
- },
- // Listens to changes on `child` and "bubbles" the event up.
- // `child` - The object to listen for changes on.
- // `prop` - The property name is at on.
- // `parent` - The parent object of prop.
- // `ob` - (optional) The Observe object constructor
- // `list` - (optional) The observable list constructor
- hookupBubble = function(child, prop, parent, Ob, List) {
- Ob = Ob || Observe;
- List = List || Observe.List;
-
- // If it's an `array` make a list, otherwise a child.
- if (child instanceof Observe) {
- // We have an `observe` already...
- // Make sure it is not listening to this already
- // It's only listening if it has bindings already.
- parent._bindings && unhookup([child], parent._cid);
- } else if (can.isArray(child)) {
- child = new List(child);
- } else {
- child = new Ob(child);
- }
- // only listen if something is listening to you
- if (parent._bindings) {
- // Listen to all changes and `batchTrigger` upwards.
- bindToChildAndBubbleToParent(child, prop, parent)
- }
-
-
- return child;
- },
- bindToChildAndBubbleToParent = function(child, prop, parent) {
- child.bind("change" + parent._cid, function() {
- // `batchTrigger` the type on this...
- var args = can.makeArray(arguments),
- ev = args.shift();
- args[0] = (prop === "*" ? [parent.indexOf(child), args[0]] : [prop, args[0]]).join(".");
-
- // track objects dispatched on this observe
- ev.triggeredNS = ev.triggeredNS || {};
-
- // if it has already been dispatched exit
- if (ev.triggeredNS[parent._cid]) {
- return;
- }
-
- ev.triggeredNS[parent._cid] = true;
- // send change event with modified attr to parent
- can.trigger(parent, ev, args);
- // send modified attr event to parent
- //can.trigger(parent, args[0], args);
- });
- }
- // An `id` to track events for a given observe.
- observeId = 0,
- // A helper used to serialize an `Observe` or `Observe.List`.
- // `observe` - The observable.
- // `how` - To serialize with `attr` or `serialize`.
- // `where` - To put properties, in an `{}` or `[]`.
- serialize = function(observe, how, where) {
- // Go through each property.
- observe.each(function(val, name) {
- // If the value is an `object`, and has an `attrs` or `serialize` function.
- where[name] = canMakeObserve(val) && can.isFunction(val[how]) ?
- // Call `attrs` or `serialize` to get the original data back.
- val[how]() :
- // Otherwise return the value.
- val;
- });
- return where;
- },
- attrParts = function(attr, keepKey) {
- if (keepKey) {
- return [attr];
- }
- return can.isArray(attr) ? attr : ("" + attr).split(".");
- },
- // Which batch of events this is for -- might not want to send multiple
- // messages on the same batch. This is mostly for event delegation.
- batchNum = 1,
- // how many times has start been called without a stop
- transactions = 0,
- // an array of events within a transaction
- batchEvents = [],
- stopCallbacks = [],
- makeBindSetup = function(wildcard) {
- return function() {
- var parent = this;
- this._each(function(child, prop) {
- if (child && child.bind) {
- bindToChildAndBubbleToParent(child, wildcard || prop, parent)
- }
- })
- };
- };
-
-
- var Observe = can.Map = can.Observe = can.Construct({
-
- // keep so it can be overwritten
- bind: can.bindAndSetup,
- unbind: can.unbindAndTeardown,
- id: "id",
- canMakeObserve: canMakeObserve,
- // starts collecting events
- // takes a callback for after they are updated
- // how could you hook into after ejs
-
- startBatch: function(batchStopHandler) {
- transactions++;
- batchStopHandler && stopCallbacks.push(batchStopHandler);
- },
-
- stopBatch: function(force, callStart) {
- if (force) {
- transactions = 0;
- } else {
- transactions--;
- }
-
- if (transactions == 0) {
- var items = batchEvents.slice(0),
- callbacks = stopCallbacks.slice(0);
- batchEvents = [];
- stopCallbacks = [];
- batchNum++;
- callStart && this.startBatch();
- can.each(items, function(args) {
- can.trigger.apply(can, args);
- });
- can.each(callbacks, function(cb) {
- cb();
- });
- }
- },
-
- triggerBatch: function(item, event, args) {
- // Don't send events if initalizing.
- if (!item._init) {
- if (transactions == 0) {
- return can.trigger(item, event, args);
- } else {
- event = typeof event === "string" ? {
- type: event
- } :
- event;
- event.batchNum = batchNum;
- batchEvents.push([
- item,
- event,
- args
- ]);
- }
- }
- },
-
- keys: function(observe) {
- var keys = [];
- Observe.__reading && Observe.__reading(observe, '__keys');
- for (var keyName in observe._data) {
- keys.push(keyName);
- }
- return keys;
- }
- },
-
- {
- setup: function(obj) {
- // `_data` is where we keep the properties.
- this._data = {};
-
- // The namespace this `object` uses to listen to events.
- can.cid(this, ".observe");
- // Sets all `attrs`.
- this._init = 1;
- this.attr(obj);
- this.bind('change' + this._cid, can.proxy(this._changes, this));
- delete this._init;
- },
- _bindsetup: makeBindSetup(),
- _bindteardown: function() {
- var cid = this._cid;
- this._each(function(child) {
- unhookup([child], cid)
- })
- },
- _changes: function(ev, attr, how, newVal, oldVal) {
- Observe.triggerBatch(this, {
- type: attr,
- batchNum: ev.batchNum
- }, [newVal, oldVal]);
- },
- _triggerChange: function(attr, how, newVal, oldVal) {
- Observe.triggerBatch(this, "change", can.makeArray(arguments))
- },
- // no live binding iterator
- _each: function(callback) {
- var data = this.__get();
- for (var prop in data) {
- if (data.hasOwnProperty(prop)) {
- callback(data[prop], prop)
- }
- }
- },
-
- attr: function(attr, val) {
- // This is super obfuscated for space -- basically, we're checking
- // if the type of the attribute is not a `number` or a `string`.
- var type = typeof attr;
- if (type !== "string" && type !== "number") {
- return this._attrs(attr, val)
- } else if (val === undefined) { // If we are getting a value.
- // Let people know we are reading.
- Observe.__reading && Observe.__reading(this, attr)
- return this._get(attr)
- } else {
- // Otherwise we are setting.
- this._set(attr, val);
- return this;
- }
- },
-
- each: function() {
- Observe.__reading && Observe.__reading(this, '__keys');
- return can.each.apply(undefined, [this.__get()].concat(can.makeArray(arguments)))
- },
-
- removeAttr: function(attr) {
- // Info if this is List or not
- var isList = this instanceof can.Observe.List,
- // Convert the `attr` into parts (if nested).
- parts = attrParts(attr),
- // The actual property to remove.
- prop = parts.shift(),
- // The current value.
- current = isList ? this[prop] : this._data[prop];
-
- // If we have more parts, call `removeAttr` on that part.
- if (parts.length) {
- return current.removeAttr(parts)
- } else {
- if (isList) {
- this.splice(prop, 1)
- } else if (prop in this._data) {
- // Otherwise, `delete`.
- delete this._data[prop];
- // Create the event.
- if (!(prop in this.constructor.prototype)) {
- delete this[prop]
- }
- // Let others know the number of keys have changed
- Observe.triggerBatch(this, "__keys");
- this._triggerChange(prop, "remove", undefined, current);
-
- }
- return current;
- }
- },
- // Reads a property from the `object`.
- _get: function(attr) {
- var value = typeof attr === 'string' && !! ~attr.indexOf('.') && this.__get(attr);
- if (value) {
- return value;
- }
-
- // break up the attr (`"foo.bar"`) into `["foo","bar"]`
- var parts = attrParts(attr),
- // get the value of the first attr name (`"foo"`)
- current = this.__get(parts.shift());
- // if there are other attributes to read
- return parts.length ?
- // and current has a value
- current ?
- // lookup the remaining attrs on current
- current._get(parts) :
- // or if there's no current, return undefined
- undefined :
- // if there are no more parts, return current
- current;
- },
- // Reads a property directly if an `attr` is provided, otherwise
- // returns the "real" data object itself.
- __get: function(attr) {
- return attr ? this._data[attr] : this._data;
- },
- // Sets `attr` prop as value on this object where.
- // `attr` - Is a string of properties or an array of property values.
- // `value` - The raw value to set.
- _set: function(attr, value, keepKey) {
- // Convert `attr` to attr parts (if it isn't already).
- var parts = attrParts(attr, keepKey),
- // The immediate prop we are setting.
- prop = parts.shift(),
- // The current value.
- current = this.__get(prop);
-
- // If we have an `object` and remaining parts.
- if (canMakeObserve(current) && parts.length) {
- // That `object` should set it (this might need to call attr).
- current._set(parts, value)
- } else if (!parts.length) {
- // We're in "real" set territory.
- if (this.__convert) {
- value = this.__convert(prop, value)
- }
- this.__set(prop, value, current)
- } else {
- throw "can.Observe: Object does not exist"
- }
- },
- __set: function(prop, value, current) {
-
- // Otherwise, we are setting it on this `object`.
- // TODO: Check if value is object and transform
- // are we changing the value.
- if (value !== current) {
- // Check if we are adding this for the first time --
- // if we are, we need to create an `add` event.
- var changeType = this.__get().hasOwnProperty(prop) ? "set" : "add";
-
- // Set the value on data.
- this.___set(prop,
-
- // If we are getting an object.
- canMakeObserve(value) ?
-
- // Hook it up to send event.
- hookupBubble(value, prop, this) :
- // Value is normal.
- value);
-
- if (changeType == "add") {
- // If there is no current value, let others know that
- // the the number of keys have changed
-
- Observe.triggerBatch(this, "__keys", undefined);
-
- }
- // `batchTrigger` the change event.
- this._triggerChange(prop, changeType, value, current);
-
- //Observe.triggerBatch(this, prop, [value, current]);
- // If we can stop listening to our old value, do it.
- current && unhookup([current], this._cid);
- }
-
- },
- // Directly sets a property on this `object`.
- ___set: function(prop, val) {
- this._data[prop] = val;
- // Add property directly for easy writing.
- // Check if its on the `prototype` so we don't overwrite methods like `attrs`.
- if (!(prop in this.constructor.prototype)) {
- this[prop] = val
- }
- },
-
-
- bind: can.bindAndSetup,
-
- unbind: can.unbindAndTeardown,
-
- serialize: function() {
- return serialize(this, 'serialize', {});
- },
-
- _attrs: function(props, remove) {
-
- if (props === undefined) {
- return serialize(this, 'attr', {})
- }
-
- props = can.extend({}, props);
- var prop,
- self = this,
- newVal;
- Observe.startBatch();
- this.each(function(curVal, prop) {
- newVal = props[prop];
-
- // If we are merging...
- if (newVal === undefined) {
- remove && self.removeAttr(prop);
- return;
- }
-
- if (self.__convert) {
- newVal = self.__convert(prop, newVal)
- }
-
- // if we're dealing with models, want to call _set to let converter run
- if (newVal instanceof can.Observe) {
- self.__set(prop, newVal, curVal)
- // if its an object, let attr merge
- } else if (canMakeObserve(curVal) && canMakeObserve(newVal) && curVal.attr) {
- curVal.attr(newVal, remove)
- // otherwise just set
- } else if (curVal != newVal) {
- self.__set(prop, newVal, curVal)
- }
-
- delete props[prop];
- })
- // Add remaining props.
- for (var prop in props) {
- newVal = props[prop];
- this._set(prop, newVal, true)
- }
- Observe.stopBatch()
- return this;
- },
-
-
- compute: function(prop) {
- return can.compute(this, prop);
- }
- });
- // Helpers for `observable` lists.
- var splice = [].splice,
-
- list = Observe(
-
- {
- setup: function(instances, options) {
- this.length = 0;
- can.cid(this, ".observe")
- this._init = 1;
- if (can.isDeferred(instances)) {
- this.replace(instances)
- } else {
- this.push.apply(this, can.makeArray(instances || []));
- }
- // this change needs to be ignored
- this.bind('change' + this._cid, can.proxy(this._changes, this));
- can.extend(this, options);
- delete this._init;
- },
- _triggerChange: function(attr, how, newVal, oldVal) {
-
- Observe.prototype._triggerChange.apply(this, arguments)
- // `batchTrigger` direct add and remove events...
- if (!~attr.indexOf('.')) {
-
- if (how === 'add') {
- Observe.triggerBatch(this, how, [newVal, +attr]);
- Observe.triggerBatch(this, 'length', [this.length]);
- } else if (how === 'remove') {
- Observe.triggerBatch(this, how, [oldVal, +attr]);
- Observe.triggerBatch(this, 'length', [this.length]);
- } else {
- Observe.triggerBatch(this, how, [newVal, +attr])
- }
-
- }
-
- },
- __get: function(attr) {
- return attr ? this[attr] : this;
- },
- ___set: function(attr, val) {
- this[attr] = val;
- if (+attr >= this.length) {
- this.length = (+attr + 1)
- }
- },
- _each: function(callback) {
- var data = this.__get();
- for (var i = 0; i < data.length; i++) {
- callback(data[i], i)
- }
- },
- _bindsetup: makeBindSetup("*"),
- // Returns the serialized form of this list.
-
- serialize: function() {
- return serialize(this, 'serialize', []);
- },
-
- splice: function(index, howMany) {
- var args = can.makeArray(arguments),
- i;
-
- for (i = 2; i < args.length; i++) {
- var val = args[i];
- if (canMakeObserve(val)) {
- args[i] = hookupBubble(val, "*", this, this.constructor.Observe, this.constructor)
- }
- }
- if (howMany === undefined) {
- howMany = args[1] = this.length - index;
- }
- var removed = splice.apply(this, args);
- can.Observe.startBatch();
- if (howMany > 0) {
- this._triggerChange("" + index, "remove", undefined, removed);
- unhookup(removed, this._cid);
- }
- if (args.length > 2) {
- this._triggerChange("" + index, "add", args.slice(2), removed);
- }
- can.Observe.stopBatch();
- return removed;
- },
-
- _attrs: function(items, remove) {
- if (items === undefined) {
- return serialize(this, 'attr', []);
- }
-
- // Create a copy.
- items = can.makeArray(items);
-
- Observe.startBatch();
- this._updateAttrs(items, remove);
- Observe.stopBatch()
- },
-
- _updateAttrs: function(items, remove) {
- var len = Math.min(items.length, this.length);
-
- for (var prop = 0; prop < len; prop++) {
- var curVal = this[prop],
- newVal = items[prop];
-
- if (canMakeObserve(curVal) && canMakeObserve(newVal)) {
- curVal.attr(newVal, remove)
- } else if (curVal != newVal) {
- this._set(prop, newVal)
- } else {
-
- }
- }
- if (items.length > this.length) {
- // Add in the remaining props.
- this.push.apply(this, items.slice(this.length));
- } else if (items.length < this.length && remove) {
- this.splice(items.length)
- }
- }
- }),
-
- // Converts to an `array` of arguments.
- getArgs = function(args) {
- return args[0] && can.isArray(args[0]) ?
- args[0] :
- can.makeArray(args);
- };
- // Create `push`, `pop`, `shift`, and `unshift`
- can.each({
-
- push: "length",
-
- unshift: 0
- },
- // Adds a method
- // `name` - The method name.
- // `where` - Where items in the `array` should be added.
-
- function(where, name) {
- var orig = [][name]
- list.prototype[name] = function() {
- // Get the items being added.
- var args = [],
- // Where we are going to add items.
- len = where ? this.length : 0,
- i = arguments.length,
- res,
- val,
- constructor = this.constructor;
-
- // Go through and convert anything to an `observe` that needs to be converted.
- while (i--) {
- val = arguments[i];
- args[i] = canMakeObserve(val) ?
- hookupBubble(val, "*", this, this.constructor.Observe, this.constructor) :
- val;
- }
-
- // Call the original method.
- res = orig.apply(this, args);
-
- if (!this.comparator || args.length) {
-
- this._triggerChange("" + len, "add", args, undefined);
- }
-
- return res;
- }
- });
-
- can.each({
-
- pop: "length",
-
- shift: 0
- },
- // Creates a `remove` type method
-
- function(where, name) {
- list.prototype[name] = function() {
-
- var args = getArgs(arguments),
- len = where && this.length ? this.length - 1 : 0;
-
- var res = [][name].apply(this, args)
-
- // Create a change where the args are
- // `len` - Where these items were removed.
- // `remove` - Items removed.
- // `undefined` - The new values (there are none).
- // `res` - The old, removed values (should these be unbound).
- this._triggerChange("" + len, "remove", undefined, [res])
-
- if (res && res.unbind) {
- res.unbind("change" + this._cid)
- }
- return res;
- }
- });
-
- can.extend(list.prototype, {
-
- indexOf: function(item) {
- this.attr('length')
- return can.inArray(item, this)
- },
-
-
- join: [].join,
-
-
- reverse: [].reverse,
-
-
- slice: function() {
- var temp = Array.prototype.slice.apply(this, arguments);
- return new this.constructor(temp);
- },
-
-
- concat: function() {
- var args = [];
- can.each(can.makeArray(arguments), function(arg, i) {
- args[i] = arg instanceof can.Observe.List ? arg.serialize() : arg;
- });
- return new this.constructor(Array.prototype.concat.apply(this.serialize(), args));
- },
-
-
- forEach: function(cb, thisarg) {
- can.each(this, cb, thisarg || this);
- },
-
-
- replace: function(newList) {
- if (can.isDeferred(newList)) {
- newList.then(can.proxy(this.replace, this));
- } else {
- this.splice.apply(this, [0, this.length].concat(can.makeArray(newList || [])));
- }
-
- return this;
- }
- });
-
- can.List = Observe.List = list;
- Observe.setup = function() {
- can.Construct.setup.apply(this, arguments);
- // I would prefer not to do it this way. It should
- // be using the attributes plugin to do this type of conversion.
- this.List = Observe.List({
- Observe: this
- }, {});
- }
- return Observe;
- })(__m3, __m8, __m1);
-
- // ## observe/compute/compute.js
- var __m9 = (function(can, bind) {
-
- // returns the
- // - observes and attr methods are called by func
- // - the value returned by func
- // ex: `{value: 100, observed: [{obs: o, attr: "completed"}]}`
- var getValueAndObserved = function(func, self) {
-
- var oldReading;
- if (can.Observe) {
- // Set a callback on can.Observe to know
- // when an attr is read.
- // Keep a reference to the old reader
- // if there is one. This is used
- // for nested live binding.
- oldReading = can.Observe.__reading;
- can.Observe.__reading = function(obj, attr) {
- // Add the observe and attr that was read
- // to `observed`
- observed.push({
- obj: obj,
- attr: attr + ""
- });
- };
- }
-
- var observed = [],
- // Call the "wrapping" function to get the value. `observed`
- // will have the observe/attribute pairs that were read.
- value = func.call(self);
-
- // Set back so we are no longer reading.
- if (can.Observe) {
- can.Observe.__reading = oldReading;
- }
- return {
- value: value,
- observed: observed
- };
- },
- // Calls `callback(newVal, oldVal)` everytime an observed property
- // called within `getterSetter` is changed and creates a new result of `getterSetter`.
- // Also returns an object that can teardown all event handlers.
- computeBinder = function(getterSetter, context, callback, computeState) {
- // track what we are observing
- var observing = {},
- // a flag indicating if this observe/attr pair is already bound
- matched = true,
- // the data to return
- data = {
- // we will maintain the value while live-binding is taking place
- value: undefined,
- // a teardown method that stops listening
- teardown: function() {
- for (var name in observing) {
- var ob = observing[name];
- ob.observe.obj.unbind(ob.observe.attr, onchanged);
- delete observing[name];
- }
- }
- },
- batchNum;
-
- // when a property value is changed
- var onchanged = function(ev) {
- // If the compute is no longer bound (because the same change event led to an unbind)
- // then do not call getValueAndBind, or we will leak bindings.
- if (computeState && !computeState.bound) {
- return;
- }
- if (ev.batchNum === undefined || ev.batchNum !== batchNum) {
- // store the old value
- var oldValue = data.value,
- // get the new value
- newvalue = getValueAndBind();
-
- // update the value reference (in case someone reads)
- data.value = newvalue;
- // if a change happened
- if (newvalue !== oldValue) {
- callback(newvalue, oldValue);
- }
- batchNum = batchNum = ev.batchNum;
- }
-
-
- };
-
- // gets the value returned by `getterSetter` and also binds to any attributes
- // read by the call
- var getValueAndBind = function() {
- var info = getValueAndObserved(getterSetter, context),
- newObserveSet = info.observed;
-
- var value = info.value;
- matched = !matched;
-
- // go through every attribute read by this observe
- can.each(newObserveSet, function(ob) {
- // if the observe/attribute pair is being observed
- if (observing[ob.obj._cid + "|" + ob.attr]) {
- // mark at as observed
- observing[ob.obj._cid + "|" + ob.attr].matched = matched;
- } else {
- // otherwise, set the observe/attribute on oldObserved, marking it as being observed
- observing[ob.obj._cid + "|" + ob.attr] = {
- matched: matched,
- observe: ob
- };
- ob.obj.bind(ob.attr, onchanged);
- }
- });
-
- // Iterate through oldObserved, looking for observe/attributes
- // that are no longer being bound and unbind them
- for (var name in observing) {
- var ob = observing[name];
- if (ob.matched !== matched) {
- ob.observe.obj.unbind(ob.observe.attr, onchanged);
- delete observing[name];
- }
- }
- return value;
- };
- // set the initial value
- data.value = getValueAndBind();
-
- data.isListening = !can.isEmptyObject(observing);
- return data;
- }
-
- // if no one is listening ... we can not calculate every time
-
- can.compute = function(getterSetter, context, eventName) {
- if (getterSetter && getterSetter.isComputed) {
- return getterSetter;
- }
- // stores the result of computeBinder
- var computedData,
- // how many listeners to this this compute
- bindings = 0,
- // the computed object
- computed,
- // an object that keeps track if the computed is bound
- // onchanged needs to know this. It's possible a change happens and results in
- // something that unbinds the compute, it needs to not to try to recalculate who it
- // is listening to
- computeState = {
- bound: false,
- // true if this compute is calculated from other computes and observes
- hasDependencies: false
- },
- // The following functions are overwritten depending on how compute() is called
- // a method to setup listening
- on = function() {},
- // a method to teardown listening
- off = function() {},
- // the current cached value (only valid if bound = true)
- value,
- // how to read the value
- get = function() {
- return value
- },
- // sets the value
- set = function(newVal) {
- value = newVal;
- },
- // this compute can be a dependency of other computes
- canReadForChangeEvent = true;
-
- computed = function(newVal) {
- // setting ...
- if (arguments.length) {
- // save a reference to the old value
- var old = value;
-
- // setter may return a value if
- // setter is for a value maintained exclusively by this compute
- var setVal = set.call(context, newVal, old);
-
- // if this has dependencies return the current value
- if (computed.hasDependencies) {
- return get.call(context);
- }
-
- if (setVal === undefined) {
- // it's possible, like with the DOM, setting does not
- // fire a change event, so we must read
- value = get.call(context);
- } else {
- value = setVal;
- }
- // fire the change
- if (old !== value) {
- can.Observe.triggerBatch(computed, "change", [value, old]);
- }
- return value;
- } else {
- // Let others know to listen to changes in this compute
- if (can.Observe.__reading && canReadForChangeEvent) {
- can.Observe.__reading(computed, 'change');
- }
- // if we are bound, use the cached value
- if (computeState.bound) {
- return value;
- } else {
- return get.call(context);
- }
- }
- }
- if (typeof getterSetter === "function") {
- set = getterSetter;
- get = getterSetter;
- canReadForChangeEvent = eventName === false ? false : true;
- computed.hasDependencies = false;
- on = function(update) {
- computedData = computeBinder(getterSetter, context || this, update, computeState);
- computed.hasDependencies = computedData.isListening
- value = computedData.value;
- }
- off = function() {
- computedData.teardown();
- }
- } else if (context) {
-
- if (typeof context == "string") {
- // `can.compute(obj, "propertyName", [eventName])`
-
- var propertyName = context,
- isObserve = getterSetter instanceof can.Observe;
- if (isObserve) {
- computed.hasDependencies = true;
- }
- get = function() {
- if (isObserve) {
- return getterSetter.attr(propertyName);
- } else {
- return getterSetter[propertyName];
- }
- }
- set = function(newValue) {
- if (isObserve) {
- getterSetter.attr(propertyName, newValue)
- } else {
- getterSetter[propertyName] = newValue;
- }
- }
- var handler;
- on = function(update) {
- handler = function() {
- update(get(), value)
- };
- can.bind.call(getterSetter, eventName || propertyName, handler)
-
- // use getValueAndObserved because
- // we should not be indicating that some parent
- // reads this property if it happens to be binding on it
- value = getValueAndObserved(get).value
- }
- off = function() {
- can.unbind.call(getterSetter, eventName || propertyName, handler)
- }
-
- } else {
- // `can.compute(initialValue, setter)`
- if (typeof context === "function") {
- value = getterSetter;
- set = context;
- } else {
- // `can.compute(initialValue,{get:, set:, on:, off:})`
- value = getterSetter;
- var options = context;
- get = options.get || get;
- set = options.set || set;
- on = options.on || on;
- off = options.off || off;
- }
-
- }
-
-
-
- } else {
- // `can.compute(5)`
- value = getterSetter;
- }
-
- computed.isComputed = true;
-
- can.cid(computed, "compute")
-
- var updater = function(newValue, oldValue) {
- value = newValue;
- // might need a way to look up new and oldVal
- can.Observe.triggerBatch(computed, "change", [newValue, oldValue])
- }
-
- return can.extend(computed, {
- _bindsetup: function() {
- computeState.bound = true;
- // setup live-binding
- on.call(this, updater)
- },
- _bindteardown: function() {
- off.call(this, updater)
- computeState.bound = false;
- },
-
- bind: can.bindAndSetup,
-
- unbind: can.unbindAndTeardown
- });
- };
- can.compute.binder = computeBinder;
- return can.compute;
- })(__m3, __m8);
-
- // ## model/model.js
- var __m10 = (function(can) {
-
- // ## model.js
- // `can.Model`
- // _A `can.Observe` that connects to a RESTful interface._
- // Generic deferred piping function
-
- var pipe = function(def, model, func) {
- var d = new can.Deferred();
- def.then(function() {
- var args = can.makeArray(arguments);
- args[0] = model[func](args[0]);
- d.resolveWith(d, args);
- }, function() {
- d.rejectWith(this, arguments);
- });
-
- if (typeof def.abort === 'function') {
- d.abort = function() {
- return def.abort();
- }
- }
-
- return d;
- },
- modelNum = 0,
- ignoreHookup = /change.observe\d+/,
- getId = function(inst) {
- // Instead of using attr, use __get for performance.
- // Need to set reading
- can.Observe.__reading && can.Observe.__reading(inst, inst.constructor.id)
- return inst.__get(inst.constructor.id);
- },
- // Ajax `options` generator function
- ajax = function(ajaxOb, data, type, dataType, success, error) {
-
- var params = {};
-
- // If we get a string, handle it.
- if (typeof ajaxOb == "string") {
- // If there's a space, it's probably the type.
- var parts = ajaxOb.split(/\s+/);
- params.url = parts.pop();
- if (parts.length) {
- params.type = parts.pop();
- }
- } else {
- can.extend(params, ajaxOb);
- }
-
- // If we are a non-array object, copy to a new attrs.
- params.data = typeof data == "object" && !can.isArray(data) ?
- can.extend(params.data || {}, data) : data;
-
- // Get the url with any templated values filled out.
- params.url = can.sub(params.url, params.data, true);
-
- return can.ajax(can.extend({
- type: type || "post",
- dataType: dataType || "json",
- success: success,
- error: error
- }, params));
- },
- makeRequest = function(self, type, success, error, method) {
- var args;
- // if we pass an array as `self` it it means we are coming from
- // the queued request, and we're passing already serialized data
- // self's signature will be: [self, serializedData]
- if (can.isArray(self)) {
- args = self[1];
- self = self[0];
- } else {
- args = self.serialize();
- }
- args = [args];
- var deferred,
- // The model.
- model = self.constructor,
- jqXHR;
-
- // `destroy` does not need data.
- if (type == 'destroy') {
- args.shift();
- }
- // `update` and `destroy` need the `id`.
- if (type !== 'create') {
- args.unshift(getId(self));
- }
-
-
- jqXHR = model[type].apply(model, args);
-
- deferred = jqXHR.pipe(function(data) {
- self[method || type + "d"](data, jqXHR);
- return self;
- });
-
- // Hook up `abort`
- if (jqXHR.abort) {
- deferred.abort = function() {
- jqXHR.abort();
- };
- }
-
- deferred.then(success, error);
- return deferred;
- },
-
- // This object describes how to make an ajax request for each ajax method.
- // The available properties are:
- // `url` - The default url to use as indicated as a property on the model.
- // `type` - The default http request type
- // `data` - A method that takes the `arguments` and returns `data` used for ajax.
-
- ajaxMethods = {
-
- create: {
- url: "_shortName",
- type: "post"
- },
-
- update: {
- data: function(id, attrs) {
- attrs = attrs || {};
- var identity = this.id;
- if (attrs[identity] && attrs[identity] !== id) {
- attrs["new" + can.capitalize(id)] = attrs[identity];
- delete attrs[identity];
- }
- attrs[identity] = id;
- return attrs;
- },
- type: "put"
- },
-
- destroy: {
- type: "delete",
- data: function(id) {
- var args = {};
- args.id = args[this.id] = id;
- return args;
- }
- },
-
- findAll: {
- url: "_shortName"
- },
-
- findOne: {}
- },
- // Makes an ajax request `function` from a string.
- // `ajaxMethod` - The `ajaxMethod` object defined above.
- // `str` - The string the user provided. Ex: `findAll: "/recipes.json"`.
- ajaxMaker = function(ajaxMethod, str) {
- // Return a `function` that serves as the ajax method.
- return function(data) {
- // If the ajax method has it's own way of getting `data`, use that.
- data = ajaxMethod.data ?
- ajaxMethod.data.apply(this, arguments) :
- // Otherwise use the data passed in.
- data;
- // Return the ajax method with `data` and the `type` provided.
- return ajax(str || this[ajaxMethod.url || "_url"], data, ajaxMethod.type || "get")
- }
- }
-
-
-
- can.Model = can.Observe({
- fullName: "can.Model",
- _reqs: 0,
- setup: function(base) {
- // create store here if someone wants to use model without inheriting from it
- this.store = {};
- can.Observe.setup.apply(this, arguments);
- // Set default list as model list
- if (!can.Model) {
- return;
- }
- this.List = ML({
- Observe: this
- }, {});
- var self = this,
- clean = can.proxy(this._clean, self);
-
-
- // go through ajax methods and set them up
- can.each(ajaxMethods, function(method, name) {
- // if an ajax method is not a function, it's either
- // a string url like findAll: "/recipes" or an
- // ajax options object like {url: "/recipes"}
- if (!can.isFunction(self[name])) {
- // use ajaxMaker to convert that into a function
- // that returns a deferred with the data
- self[name] = ajaxMaker(method, self[name]);
- }
- // check if there's a make function like makeFindAll
- // these take deferred function and can do special
- // behavior with it (like look up data in a store)
- if (self["make" + can.capitalize(name)]) {
- // pass the deferred method to the make method to get back
- // the "findAll" method.
- var newMethod = self["make" + can.capitalize(name)](self[name]);
- can.Construct._overwrite(self, base, name, function() {
- // increment the numer of requests
- can.Model._reqs++;
- var def = newMethod.apply(this, arguments);
- var then = def.then(clean, clean);
- then.abort = def.abort;
-
- // attach abort to our then and return it
- return then;
- })
- }
- });
-
- if (self.fullName == "can.Model" || !self.fullName) {
- self.fullName = "Model" + (++modelNum);
- }
- // Add ajax converters.
- can.Model._reqs = 0;
- this._url = this._shortName + "/{" + this.id + "}"
- },
- _ajax: ajaxMaker,
- _makeRequest: makeRequest,
- _clean: function() {
- can.Model._reqs--;
- if (!can.Model._reqs) {
- for (var id in this.store) {
- if (!this.store[id]._bindings) {
- delete this.store[id];
- }
- }
- }
- return arguments[0];
- },
-
- models: function(instancesRawData, oldList) {
- // until "end of turn", increment reqs counter so instances will be added to the store
- can.Model._reqs++;
- if (!instancesRawData) {
- return;
- }
-
- if (instancesRawData instanceof this.List) {
- return instancesRawData;
- }
-
- // Get the list type.
- var self = this,
- tmp = [],
- res = oldList instanceof can.Observe.List ? oldList : new(self.List || ML),
- // Did we get an `array`?
- arr = can.isArray(instancesRawData),
-
- // Did we get a model list?
- ml = (instancesRawData instanceof ML),
-
- // Get the raw `array` of objects.
- raw = arr ?
-
- // If an `array`, return the `array`.
- instancesRawData :
-
- // Otherwise if a model list.
- (ml ?
-
- // Get the raw objects from the list.
- instancesRawData.serialize() :
-
- // Get the object's data.
- instancesRawData.data),
- i = 0;
-
-
-
- if (res.length) {
- res.splice(0);
- }
-
- can.each(raw, function(rawPart) {
- tmp.push(self.model(rawPart));
- });
-
- // We only want one change event so push everything at once
- res.push.apply(res, tmp);
-
- if (!arr) { // Push other stuff onto `array`.
- can.each(instancesRawData, function(val, prop) {
- if (prop !== 'data') {
- res.attr(prop, val);
- }
- })
- }
- // at "end of turn", clean up the store
- setTimeout(can.proxy(this._clean, this), 1);
- return res;
- },
-
- model: function(attributes) {
- if (!attributes) {
- return;
- }
- if (attributes instanceof this) {
- attributes = attributes.serialize();
- }
- var id = attributes[this.id],
- model = (id || id === 0) && this.store[id] ?
- this.store[id].attr(attributes, this.removeAttr || false) : new this(attributes);
- if (can.Model._reqs) {
- this.store[attributes[this.id]] = model;
- }
- return model;
- }
- },
-
-
- {
-
- isNew: function() {
- var id = getId(this);
- return !(id || id === 0); // If `null` or `undefined`
- },
-
- save: function(success, error) {
- return makeRequest(this, this.isNew() ? 'create' : 'update', success, error);
- },
-
- destroy: function(success, error) {
- if (this.isNew()) {
- var self = this;
- var def = can.Deferred();
- def.then(success, error);
- return def.done(function(data) {
- self.destroyed(data)
- }).resolve(self);
- }
- return makeRequest(this, 'destroy', success, error, 'destroyed');
- },
-
- _bindsetup: function() {
- this.constructor.store[this.__get(this.constructor.id)] = this;
- return can.Observe.prototype._bindsetup.apply(this, arguments);
- },
-
- _bindteardown: function() {
- delete this.constructor.store[getId(this)];
- return can.Observe.prototype._bindteardown.apply(this, arguments)
- },
- // Change `id`.
- ___set: function(prop, val) {
- can.Observe.prototype.___set.call(this, prop, val)
- // If we add an `id`, move it to the store.
- if (prop === this.constructor.id && this._bindings) {
- this.constructor.store[getId(this)] = this;
- }
- }
- });
-
- can.each({
- makeFindAll: "models",
- makeFindOne: "model",
- makeCreate: "model",
- makeUpdate: "model"
- }, function(method, name) {
- can.Model[name] = function(oldMethod) {
- return function() {
- var args = can.makeArray(arguments),
- oldArgs = can.isFunction(args[1]) ? args.splice(0, 1) : args.splice(0, 2),
- def = pipe(oldMethod.apply(this, oldArgs), this, method);
- def.then(args[0], args[1]);
- // return the original promise
- return def;
- };
- };
- });
-
- can.each([
-
- "created",
-
- "updated",
-
- "destroyed"
- ], function(funcName) {
- can.Model.prototype[funcName] = function(attrs) {
- var stub,
- constructor = this.constructor;
-
- // Update attributes if attributes have been passed
- stub = attrs && typeof attrs == 'object' && this.attr(attrs.attr ? attrs.attr() : attrs);
-
- // triggers change event that bubble's like
- // handler( 'change','1.destroyed' ). This is used
- // to remove items on destroyed from Model Lists.
- // but there should be a better way.
- can.trigger(this, "change", funcName)
-
-
- // Call event on the instance's Class
- can.trigger(constructor, funcName, this);
- };
- });
-
- // Model lists are just like `Observe.List` except that when their items are
- // destroyed, it automatically gets removed from the list.
-
- var ML = can.Model.List = can.Observe.List({
- setup: function(params) {
- if (can.isPlainObject(params) && !can.isArray(params)) {
- can.Observe.List.prototype.setup.apply(this);
- this.replace(this.constructor.Observe.findAll(params))
- } else {
- can.Observe.List.prototype.setup.apply(this, arguments);
- }
- },
- _changes: function(ev, attr) {
- can.Observe.List.prototype._changes.apply(this, arguments);
- if (/\w+\.destroyed/.test(attr)) {
- var index = this.indexOf(ev.target);
- if (index != -1) {
- this.splice(index, 1);
- }
- }
- }
- })
-
- return can.Model;
- })(__m3, __m7);
-
- // ## view/view.js
- var __m11 = (function(can) {
- // ## view.js
- // `can.view`
- // _Templating abstraction._
-
- var isFunction = can.isFunction,
- makeArray = can.makeArray,
- // Used for hookup `id`s.
- hookupId = 1,
-
- $view = can.view = can.template = function(view, data, helpers, callback) {
- // If helpers is a `function`, it is actually a callback.
- if (isFunction(helpers)) {
- callback = helpers;
- helpers = undefined;
- }
-
- var pipe = function(result) {
- return $view.frag(result);
- },
- // In case we got a callback, we need to convert the can.view.render
- // result to a document fragment
- wrapCallback = isFunction(callback) ? function(frag) {
- callback(pipe(frag));
- } : null,
- // Get the result.
- result = $view.render(view, data, helpers, wrapCallback),
- deferred = can.Deferred();
-
- if (isFunction(result)) {
- return result;
- }
-
- if (can.isDeferred(result)) {
- result.then(function(result, data) {
- deferred.resolve.call(deferred, pipe(result), data);
- }, function() {
- deferred.fail.apply(deferred, arguments);
- });
- return deferred;
- }
-
- // Convert it into a dom frag.
- return pipe(result);
- };
-
- can.extend($view, {
- // creates a frag and hooks it up all at once
- frag: function(result, parentNode) {
- return $view.hookup($view.fragment(result), parentNode);
- },
-
- // simply creates a frag
- // this is used internally to create a frag
- // insert it
- // then hook it up
- fragment: function(result) {
- var frag = can.buildFragment(result, document.body);
- // If we have an empty frag...
- if (!frag.childNodes.length) {
- frag.appendChild(document.createTextNode(''));
- }
- return frag;
- },
-
- // Convert a path like string into something that's ok for an `element` ID.
- toId: function(src) {
- return can.map(src.toString().split(/\/|\./g), function(part) {
- // Dont include empty strings in toId functions
- if (part) {
- return part;
- }
- }).join("_");
- },
-
- hookup: function(fragment, parentNode) {
- var hookupEls = [],
- id,
- func;
-
- // Get all `childNodes`.
- can.each(fragment.childNodes ? can.makeArray(fragment.childNodes) : fragment, function(node) {
- if (node.nodeType === 1) {
- hookupEls.push(node);
- hookupEls.push.apply(hookupEls, can.makeArray(node.getElementsByTagName('*')));
- }
- });
-
- // Filter by `data-view-id` attribute.
- can.each(hookupEls, function(el) {
- if (el.getAttribute && (id = el.getAttribute('data-view-id')) && (func = $view.hookups[id])) {
- func(el, parentNode, id);
- delete $view.hookups[id];
- el.removeAttribute('data-view-id');
- }
- });
-
- return fragment;
- },
-
-
- hookups: {},
-
-
- hook: function(cb) {
- $view.hookups[++hookupId] = cb;
- return " data-view-id='" + hookupId + "'";
- },
-
-
- cached: {},
-
- cachedRenderers: {},
-
-
- cache: true,
-
-
- register: function(info) {
- this.types["." + info.suffix] = info;
- },
-
- types: {},
-
-
- ext: ".ejs",
-
-
- registerScript: function() {},
-
-
- preload: function() {},
-
-
- render: function(view, data, helpers, callback) {
- // If helpers is a `function`, it is actually a callback.
- if (isFunction(helpers)) {
- callback = helpers;
- helpers = undefined;
- }
-
- // See if we got passed any deferreds.
- var deferreds = getDeferreds(data);
-
- if (deferreds.length) { // Does data contain any deferreds?
- // The deferred that resolves into the rendered content...
- var deferred = new can.Deferred(),
- dataCopy = can.extend({}, data);
-
- // Add the view request to the list of deferreds.
- deferreds.push(get(view, true))
-
- // Wait for the view and all deferreds to finish...
- can.when.apply(can, deferreds).then(function(resolved) {
- // Get all the resolved deferreds.
- var objs = makeArray(arguments),
- // Renderer is the last index of the data.
- renderer = objs.pop(),
- // The result of the template rendering with data.
- result;
-
- // Make data look like the resolved deferreds.
- if (can.isDeferred(data)) {
- dataCopy = usefulPart(resolved);
- } else {
- // Go through each prop in data again and
- // replace the defferreds with what they resolved to.
- for (var prop in data) {
- if (can.isDeferred(data[prop])) {
- dataCopy[prop] = usefulPart(objs.shift());
- }
- }
- }
-
- // Get the rendered result.
- result = renderer(dataCopy, helpers);
-
- // Resolve with the rendered view.
- deferred.resolve(result, dataCopy);
-
- // If there's a `callback`, call it back with the result.
- callback && callback(result, dataCopy);
- }, function() {
- deferred.reject.apply(deferred, arguments)
- });
- // Return the deferred...
- return deferred;
- } else {
- // No deferreds! Render this bad boy.
- var response,
- // If there's a `callback` function
- async = isFunction(callback),
- // Get the `view` type
- deferred = get(view, async);
-
- // If we are `async`...
- if (async) {
- // Return the deferred
- response = deferred;
- // And fire callback with the rendered result.
- deferred.then(function(renderer) {
- callback(data ? renderer(data, helpers) : renderer);
- })
- } else {
- // if the deferred is resolved, call the cached renderer instead
- // this is because it's possible, with recursive deferreds to
- // need to render a view while its deferred is _resolving_. A _resolving_ deferred
- // is a deferred that was just resolved and is calling back it's success callbacks.
- // If a new success handler is called while resoliving, it does not get fired by
- // jQuery's deferred system. So instead of adding a new callback
- // we use the cached renderer.
- // We also add __view_id on the deferred so we can look up it's cached renderer.
- // In the future, we might simply store either a deferred or the cached result.
- if (deferred.state() === "resolved" && deferred.__view_id) {
- var currentRenderer = $view.cachedRenderers[deferred.__view_id];
- return data ? currentRenderer(data, helpers) : currentRenderer;
- } else {
- // Otherwise, the deferred is complete, so
- // set response to the result of the rendering.
- deferred.then(function(renderer) {
- response = data ? renderer(data, helpers) : renderer;
- });
- }
- }
-
- return response;
- }
- },
-
-
- registerView: function(id, text, type, def) {
- // Get the renderer function.
- var func = (type || $view.types[$view.ext]).renderer(id, text);
- def = def || new can.Deferred();
-
- // Cache if we are caching.
- if ($view.cache) {
- $view.cached[id] = def;
- def.__view_id = id;
- $view.cachedRenderers[id] = func;
- }
-
- // Return the objects for the response's `dataTypes`
- // (in this case view).
- return def.resolve(func);
- }
- });
-
- // Makes sure there's a template, if not, have `steal` provide a warning.
- var checkText = function(text, url) {
- if (!text.length) {
-
- throw "can.view: No template or empty template:" + url;
- }
- },
- // `Returns a `view` renderer deferred.
- // `url` - The url to the template.
- // `async` - If the ajax request should be asynchronous.
- // Returns a deferred.
- get = function(url, async) {
- var suffix = url.match(/\.[\w\d]+$/),
- type,
- // If we are reading a script element for the content of the template,
- // `el` will be set to that script element.
- el,
- // A unique identifier for the view (used for caching).
- // This is typically derived from the element id or
- // the url for the template.
- id,
- // The ajax request used to retrieve the template content.
- jqXHR;
-
- //If the url has a #, we assume we want to use an inline template
- //from a script element and not current page's HTML
- if (url.match(/^#/)) {
- url = url.substr(1);
- }
- // If we have an inline template, derive the suffix from the `text/???` part.
- // This only supports `<script>` tags.
- if (el = document.getElementById(url)) {
- suffix = "." + el.type.match(/\/(x\-)?(.+)/)[2];
- }
-
- // If there is no suffix, add one.
- if (!suffix && !$view.cached[url]) {
- url += (suffix = $view.ext);
- }
-
- if (can.isArray(suffix)) {
- suffix = suffix[0]
- }
-
- // Convert to a unique and valid id.
- id = $view.toId(url);
-
- // If an absolute path, use `steal` to get it.
- // You should only be using `//` if you are using `steal`.
- if (url.match(/^\/\//)) {
- var sub = url.substr(2);
- url = !window.steal ?
- sub :
- steal.config().root.mapJoin("" + steal.id(sub));
- }
-
- // Set the template engine type.
- type = $view.types[suffix];
-
- // If it is cached,
- if ($view.cached[id]) {
- // Return the cached deferred renderer.
- return $view.cached[id];
-
- // Otherwise if we are getting this from a `<script>` element.
- } else if (el) {
- // Resolve immediately with the element's `innerHTML`.
- return $view.registerView(id, el.innerHTML, type);
- } else {
- // Make an ajax request for text.
- var d = new can.Deferred();
- can.ajax({
- async: async,
- url: url,
- dataType: "text",
- error: function(jqXHR) {
- checkText("", url);
- d.reject(jqXHR);
- },
- success: function(text) {
- // Make sure we got some text back.
- checkText(text, url);
- $view.registerView(id, text, type, d)
- }
- });
- return d;
- }
- },
- // Gets an `array` of deferreds from an `object`.
- // This only goes one level deep.
- getDeferreds = function(data) {
- var deferreds = [];
-
- // pull out deferreds
- if (can.isDeferred(data)) {
- return [data]
- } else {
- for (var prop in data) {
- if (can.isDeferred(data[prop])) {
- deferreds.push(data[prop]);
- }
- }
- }
- return deferreds;
- },
- // Gets the useful part of a resolved deferred.
- // This is for `model`s and `can.ajax` that resolve to an `array`.
- usefulPart = function(resolved) {
- return can.isArray(resolved) && resolved[1] === 'success' ? resolved[0] : resolved
- };
-
- //!steal-pluginify-remove-start
- if (window.steal) {
- steal.type("view js", function(options, success, error) {
- var type = $view.types["." + options.type],
- id = $view.toId(options.id);
-
- options.text = "steal('" + (type.plugin || "can/view/" + options.type) + "',function(can){return " + "can.view.preload('" + id + "'," + options.text + ");\n})";
- success();
- })
- }
- //!steal-pluginify-remove-end
-
- can.extend($view, {
- register: function(info) {
- this.types["." + info.suffix] = info;
-
- //!steal-pluginify-remove-start
- if (window.steal) {
- steal.type(info.suffix + " view js", function(options, success, error) {
- var type = $view.types["." + options.type],
- id = $view.toId(options.id + '');
-
- options.text = type.script(id, options.text)
- success();
- })
- };
- //!steal-pluginify-remove-end
-
- $view[info.suffix] = function(id, text) {
- if (!text) {
- // Return a nameless renderer
- var renderer = function() {
- return $view.frag(renderer.render.apply(this, arguments));
- }
- renderer.render = function() {
- var renderer = info.renderer(null, id);
- return renderer.apply(renderer, arguments);
- }
- return renderer;
- }
-
- $view.preload(id, info.renderer(id, text));
- return can.view(id);
- }
- },
- registerScript: function(type, id, src) {
- return "can.view.preload('" + id + "'," + $view.types["." + type].script(id, src) + ");";
- },
- preload: function(id, renderer) {
- $view.cached[id] = new can.Deferred().resolve(function(data, helpers) {
- return renderer.call(data, data, helpers);
- });
-
- function frag() {
- return $view.frag(renderer.apply(this, arguments));
- }
- // expose the renderer for mustache
- frag.render = renderer;
- return frag;
- }
-
- });
-
- return can;
- })(__m3);
-
- // ## view/elements.js
- var __m14 = (function() {
-
- var elements = {
- tagToContentPropMap: {
- option: "textContent" in document.createElement("option") ? "textContent" : "innerText",
- textarea: "value"
- },
-
- attrMap: {
- "class": "className",
- "value": "value",
- "innerText": "innerText",
- "textContent": "textContent",
- "checked": true,
- "disabled": true,
- "readonly": true,
- "required": true
- },
- // elements whos default value we should set
- defaultValue: ["input", "textarea"],
- // a map of parent element to child elements
- tagMap: {
- "": "span",
- table: "tbody",
- tr: "td",
- ol: "li",
- ul: "li",
- tbody: "tr",
- thead: "tr",
- tfoot: "tr",
- select: "option",
- optgroup: "option"
- },
- // a tag's parent element
- reverseTagMap: {
- tr: "tbody",
- option: "select",
- td: "tr",
- th: "tr",
- li: "ul"
- },
-
- getParentNode: function(el, defaultParentNode) {
- return defaultParentNode && el.parentNode.nodeType === 11 ? defaultParentNode : el.parentNode;
- },
- // set an attribute on an element
- setAttr: function(el, attrName, val) {
- var tagName = el.nodeName.toString().toLowerCase(),
- prop = elements.attrMap[attrName];
- // if this is a special property
- if (prop === true) {
- el[attrName] = true;
- } else if (prop) {
- // set the value as true / false
- el[prop] = val;
- if (prop === "value" && can.inArray(tagName, elements.defaultValue) >= 0) {
- el.defaultValue = val;
- }
- } else {
- el.setAttribute(attrName, val);
- }
- },
- // gets the value of an attribute
- getAttr: function(el, attrName) {
- // Default to a blank string for IE7/8
- return (elements.attrMap[attrName] && el[elements.attrMap[attrName]] ?
- el[elements.attrMap[attrName]] :
- el.getAttribute(attrName)) || '';
- },
- // removes the attribute
- removeAttr: function(el, attrName) {
- if (elements.attrMap[attrName] === true) {
- el[attrName] = false;
- } else {
- el.removeAttribute(attrName);
- }
- },
- contentText: function(text) {
- if (typeof text == 'string') {
- return text;
- }
- // If has no value, return an empty string.
- if (!text && text !== 0) {
- return '';
- }
- return "" + text;
- }
- };
-
- return elements;
- })();
-
- // ## view/scanner.js
- var __m13 = (function(can, elements) {
-
- var newLine = /(\r|\n)+/g,
- // Escapes characters starting with `\`.
- clean = function(content) {
- return content
- .split('\\').join("\\\\")
- .split("\n").join("\\n")
- .split('"').join('\\"')
- .split("\t").join("\\t");
- },
- // Returns a tagName to use as a temporary placeholder for live content
- // looks forward ... could be slow, but we only do it when necessary
- getTag = function(tagName, tokens, i) {
- // if a tagName is provided, use that
- if (tagName) {
- return tagName;
- } else {
- // otherwise go searching for the next two tokens like "<",TAG
- while (i < tokens.length) {
- if (tokens[i] == "<" && elements.reverseTagMap[tokens[i + 1]]) {
- return elements.reverseTagMap[tokens[i + 1]];
- }
- i++;
- }
- }
- return '';
- },
- bracketNum = function(content) {
- return (--content.split("{").length) - (--content.split("}").length);
- },
- myEval = function(script) {
- try {
- eval(script);
- } catch(e) {
- console.log(script)
- }
- },
- attrReg = /([^\s]+)[\s]*=[\s]*$/,
- // Commands for caching.
- startTxt = 'var ___v1ew = [];',
- finishTxt = "return ___v1ew.join('')",
- put_cmd = "___v1ew.push(",
- insert_cmd = put_cmd,
- // Global controls (used by other functions to know where we are).
- // Are we inside a tag?
- htmlTag = null,
- // Are we within a quote within a tag?
- quote = null,
- // What was the text before the current quote? (used to get the `attr` name)
- beforeQuote = null,
- // Whether a rescan is in progress
- rescan = null,
- // Used to mark where the element is.
- status = function() {
- // `t` - `1`.
- // `h` - `0`.
- // `q` - String `beforeQuote`.
- return quote ? "'" + beforeQuote.match(attrReg)[1] + "'" : (htmlTag ? 1 : 0);
- };
-
- can.view.Scanner = Scanner = function(options) {
- // Set options on self
- can.extend(this, {
- text: {},
- tokens: []
- }, options);
-
- // Cache a token lookup
- this.tokenReg = [];
- this.tokenSimple = {
- "<": "<",
- ">": ">",
- '"': '"',
- "'": "'"
- };
- this.tokenComplex = [];
- this.tokenMap = {};
- for (var i = 0, token; token = this.tokens[i]; i++) {
-
-
- // Save complex mappings (custom regexp)
- if (token[2]) {
- this.tokenReg.push(token[2]);
- this.tokenComplex.push({
- abbr: token[1],
- re: new RegExp(token[2]),
- rescan: token[3]
- });
- }
- // Save simple mappings (string only, no regexp)
- else {
- this.tokenReg.push(token[1]);
- this.tokenSimple[token[1]] = token[0];
- }
- this.tokenMap[token[0]] = token[1];
- }
-
- // Cache the token registry.
- this.tokenReg = new RegExp("(" + this.tokenReg.slice(0).concat(["<", ">", '"', "'"]).join("|") + ")", "g");
- };
-
- Scanner.prototype = {
-
- helpers: [
-
- {
- name: /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
- fn: function(content) {
- var quickFunc = /\s*\(([\$\w]+)\)\s*->([^\n]*)/,
- parts = content.match(quickFunc);
-
- return "can.proxy(function(__){var " + parts[1] + "=can.$(__);" + parts[2] + "}, this);";
- }
- }
- ],
-
- scan: function(source, name) {
- var tokens = [],
- last = 0,
- simple = this.tokenSimple,
- complex = this.tokenComplex;
-
- source = source.replace(newLine, "\n");
- if (this.transform) {
- source = this.transform(source);
- }
- source.replace(this.tokenReg, function(whole, part) {
- // offset is the second to last argument
- var offset = arguments[arguments.length - 2];
-
- // if the next token starts after the last token ends
- // push what's in between
- if (offset > last) {
- tokens.push(source.substring(last, offset));
- }
-
- // push the simple token (if there is one)
- if (simple[whole]) {
- tokens.push(whole);
- }
- // otherwise lookup complex tokens
- else {
- for (var i = 0, token; token = complex[i]; i++) {
- if (token.re.test(whole)) {
- tokens.push(token.abbr);
- // Push a rescan function if one exists
- if (token.rescan) {
- tokens.push(token.rescan(part));
- }
- break;
- }
- }
- }
-
- // update the position of the last part of the last token
- last = offset + part.length;
- });
-
- // if there's something at the end, add it
- if (last < source.length) {
- tokens.push(source.substr(last));
- }
-
- var content = '',
- buff = [startTxt + (this.text.start || '')],
- // Helper `function` for putting stuff in the view concat.
- put = function(content, bonus) {
- buff.push(put_cmd, '"', clean(content), '"' + (bonus || '') + ');');
- },
- // A stack used to keep track of how we should end a bracket
- // `}`.
- // Once we have a `<%= %>` with a `leftBracket`,
- // we store how the file should end here (either `))` or `;`).
- endStack = [],
- // The last token, used to remember which tag we are in.
- lastToken,
- // The corresponding magic tag.
- startTag = null,
- // Was there a magic tag inside an html tag?
- magicInTag = false,
- // The current tag name.
- tagName = '',
- // stack of tagNames
- tagNames = [],
- // Pop from tagNames?
- popTagName = false,
- // Declared here.
- bracketCount,
- i = 0,
- token,
- tmap = this.tokenMap;
-
- // Reinitialize the tag state goodness.
- htmlTag = quote = beforeQuote = null;
-
- for (;
- (token = tokens[i++]) !== undefined;) {
- if (startTag === null) {
- switch (token) {
- case tmap.left:
- case tmap.escapeLeft:
- case tmap.returnLeft:
- magicInTag = htmlTag && 1;
- case tmap.commentLeft:
- // A new line -- just add whatever content within a clean.
- // Reset everything.
- startTag = token;
- if (content.length) {
- put(content);
- }
- content = '';
- break;
- case tmap.escapeFull:
- // This is a full line escape (a line that contains only whitespace and escaped logic)
- // Break it up into escape left and right
- magicInTag = htmlTag && 1;
- rescan = 1;
- startTag = tmap.escapeLeft;
- if (content.length) {
- put(content);
- }
- rescan = tokens[i++];
- content = rescan.content || rescan;
- if (rescan.before) {
- put(rescan.before);
- }
- tokens.splice(i, 0, tmap.right);
- break;
- case tmap.commentFull:
- // Ignore full line comments.
- break;
- case tmap.templateLeft:
- content += tmap.left;
- break;
- case '<':
- // Make sure we are not in a comment.
- if (tokens[i].indexOf("!--") !== 0) {
- htmlTag = 1;
- magicInTag = 0;
- }
- content += token;
- break;
- case '>':
- htmlTag = 0;
- // content.substr(-1) doesn't work in IE7/8
- var emptyElement = content.substr(content.length - 1) == "/" || content.substr(content.length - 2) == "--";
- // if there was a magic tag
- // or it's an element that has text content between its tags,
- // but content is not other tags add a hookup
- // TODO: we should only add `can.EJS.pending()` if there's a magic tag
- // within the html tags.
- if (magicInTag || !popTagName && elements.tagToContentPropMap[tagNames[tagNames.length - 1]]) {
- // make sure / of /> is on the left of pending
- if (emptyElement) {
- put(content.substr(0, content.length - 1), ",can.view.pending(),\"/>\"");
- } else {
- put(content, ",can.view.pending(),\">\"");
- }
- content = '';
- magicInTag = 0;
- } else {
- content += token;
- }
- // if it's a tag like <input/>
- if (emptyElement || popTagName) {
- // remove the current tag in the stack
- tagNames.pop();
- // set the current tag to the previous parent
- tagName = tagNames[tagNames.length - 1];
- // Don't pop next time
- popTagName = false;
- }
- break;
- case "'":
- case '"':
- // If we are in an html tag, finding matching quotes.
- if (htmlTag) {
- // We have a quote and it matches.
- if (quote && quote === token) {
- // We are exiting the quote.
- quote = null;
- // Otherwise we are creating a quote.
- // TODO: does this handle `\`?
- } else if (quote === null) {
- quote = token;
- beforeQuote = lastToken;
- }
- }
- default:
- // Track the current tag
- if (lastToken === '<') {
- tagName = token.split(/\s/)[0];
- if (tagName.indexOf("/") === 0 && tagNames[tagNames.length - 1] === tagName.substr(1)) {
- // set tagName to the last tagName
- // if there are no more tagNames, we'll rely on getTag.
- tagName = tagNames[tagNames.length - 1];
- popTagName = true;
- } else {
- tagNames.push(tagName);
- }
- }
- content += token;
- break;
- }
- } else {
- // We have a start tag.
- switch (token) {
- case tmap.right:
- case tmap.returnRight:
- switch (startTag) {
- case tmap.left:
- // Get the number of `{ minus }`
- bracketCount = bracketNum(content);
-
- // We are ending a block.
- if (bracketCount == 1) {
-
- // We are starting on.
- buff.push(insert_cmd, "can.view.txt(0,'" + getTag(tagName, tokens, i) + "'," + status() + ",this,function(){", startTxt, content);
-
- endStack.push({
- before: "",
- after: finishTxt + "}));\n"
- });
- } else {
-
- // How are we ending this statement?
- last = // If the stack has value and we are ending a block...
- endStack.length && bracketCount == -1 ? // Use the last item in the block stack.
- endStack.pop() : // Or use the default ending.
- {
- after: ";"
- };
-
- // If we are ending a returning block,
- // add the finish text which returns the result of the
- // block.
- if (last.before) {
- buff.push(last.before);
- }
- // Add the remaining content.
- buff.push(content, ";", last.after);
- }
- break;
- case tmap.escapeLeft:
- case tmap.returnLeft:
- // We have an extra `{` -> `block`.
- // Get the number of `{ minus }`.
- bracketCount = bracketNum(content);
- // If we have more `{`, it means there is a block.
- if (bracketCount) {
- // When we return to the same # of `{` vs `}` end with a `doubleParent`.
- endStack.push({
- before: finishTxt,
- after: "}));"
- });
- }
-
- var escaped = startTag === tmap.escapeLeft ? 1 : 0,
- commands = {
- insert: insert_cmd,
- tagName: getTag(tagName, tokens, i),
- status: status()
- };
-
- for (var ii = 0; ii < this.helpers.length; ii++) {
- // Match the helper based on helper
- // regex name value
- var helper = this.helpers[ii];
- if (helper.name.test(content)) {
- content = helper.fn(content, commands);
-
- // dont escape partials
- if (helper.name.source == /^>[\s]*\w*/.source) {
- escaped = 0;
- }
- break;
- }
- }
-
- // Handle special cases
- if (typeof content == 'object') {
- if (content.raw) {
- buff.push(content.raw);
- }
- } else {
- // If we have `<%== a(function(){ %>` then we want
- // `can.EJS.text(0,this, function(){ return a(function(){ var _v1ew = [];`.
- buff.push(insert_cmd, "can.view.txt(" + escaped + ",'" + tagName + "'," + status() + ",this,function(){ " + (this.text.escape || '') + "return ", content,
- // If we have a block.
- bracketCount ?
- // Start with startTxt `"var _v1ew = [];"`.
- startTxt :
- // If not, add `doubleParent` to close push and text.
- "}));");
- }
-
- if (rescan && rescan.after && rescan.after.length) {
- put(rescan.after.length);
- rescan = null;
- }
- break;
- }
- startTag = null;
- content = '';
- break;
- case tmap.templateLeft:
- content += tmap.left;
- break;
- default:
- content += token;
- break;
- }
- }
- lastToken = token;
- }
-
- // Put it together...
- if (content.length) {
- // Should be `content.dump` in Ruby.
- put(content);
- }
- buff.push(";");
-
- var template = buff.join(''),
- out = {
- out: 'with(_VIEW) { with (_CONTEXT) {' + template + " " + finishTxt + "}}"
- };
- // Use `eval` instead of creating a function, because it is easier to debug.
- myEval.call(out, 'this.fn = (function(_CONTEXT,_VIEW){' + out.out + '});\r\n//@ sourceURL=' + name + ".js");
-
- return out;
- }
- };
-
- return Scanner;
- })(__m11, __m14);
-
- // ## view/node_lists.js
- var __m17 = (function(can) {
-
- // text node expando test
- var canExpando = true;
- try {
- document.createTextNode('')._ = 0;
- } catch (ex) {
- canExpando = false;
- }
-
- // a mapping of element ids to nodeList ids
- var nodeMap = {},
- // a mapping of ids to text nodes
- textNodeMap = {},
- // a mapping of nodeList ids to nodeList
- nodeListMap = {},
- expando = "ejs_" + Math.random(),
- _id = 0,
- id = function(node) {
- if (canExpando || node.nodeType !== 3) {
- if (node[expando]) {
- return node[expando];
- } else {
- return node[expando] = (node.nodeName ? "element_" : "obj_") + (++_id);
- }
- } else {
- for (var textNodeID in textNodeMap) {
- if (textNodeMap[textNodeID] === node) {
- return textNodeID;
- }
- }
-
- textNodeMap["text_" + (++_id)] = node;
- return "text_" + _id;
- }
- },
- // removes a nodeListId from a node's nodeListIds
- removeNodeListId = function(node, nodeListId) {
- var nodeListIds = nodeMap[id(node)];
- if (nodeListIds) {
- var index = can.inArray(nodeListId, nodeListIds);
-
- if (index >= 0) {
- nodeListIds.splice(index, 1);
- }
- if (!nodeListIds.length) {
- delete nodeMap[id(node)];
- }
- }
- },
- addNodeListId = function(node, nodeListId) {
- var nodeListIds = nodeMap[id(node)];
- if (!nodeListIds) {
- nodeListIds = nodeMap[id(node)] = [];
- }
- nodeListIds.push(nodeListId);
- };
-
- var nodeLists = {
- id: id,
- // replaces the contents of one node list with the nodes in another list
- replace: function(oldNodeList, newNodes) {
- // for each node in the node list
- oldNodeList = can.makeArray(oldNodeList);
-
- // try every set
- //can.each( oldNodeList, function(node){
- var node = oldNodeList[0]
- // for each nodeList the node is in
- can.each(can.makeArray(nodeMap[id(node)]), function(nodeListId) {
-
- // if startNode to endNode is
- // within list, replace that list
- // I think the problem is not the WHOLE part is being
- // matched
- var nodeList = nodeListMap[nodeListId],
- startIndex = can.inArray(node, nodeList),
- endIndex = can.inArray(oldNodeList[oldNodeList.length - 1], nodeList);
-
-
- // remove this nodeListId from each node
- if (startIndex >= 0 && endIndex >= 0) {
- for (var i = startIndex; i <= endIndex; i++) {
- var n = nodeList[i];
- removeNodeListId(n, nodeListId);
- }
- // swap in new nodes into the nodeLIst
- nodeList.splice.apply(nodeList, [startIndex, endIndex - startIndex + 1].concat(newNodes));
-
- // tell these new nodes they belong to the nodeList
- can.each(newNodes, function(node) {
- addNodeListId(node, nodeListId);
- });
- } else {
- nodeLists.unregister(nodeList);
- }
- });
- //});
- },
- // registers a list of nodes
- register: function(nodeList) {
- var nLId = id(nodeList);
- nodeListMap[nLId] = nodeList;
-
- can.each(nodeList, function(node) {
- addNodeListId(node, nLId);
- });
-
- },
- // removes mappings
- unregister: function(nodeList) {
- var nLId = id(nodeList);
- can.each(nodeList, function(node) {
- removeNodeListId(node, nLId);
- });
- delete nodeListMap[nLId];
- },
- nodeMap: nodeMap,
- nodeListMap: nodeListMap
- }
- var ids = function(nodeList) {
- return nodeList.map(function(n) {
- return id(n) + ":" + (n.innerHTML || n.nodeValue)
- })
- }
- return nodeLists;
-
- })(__m3);
-
- // ## view/live.js
- var __m16 = (function(can, elements, view, nodeLists) {
- // ## live.js
- // The live module provides live binding for computes
- // and can.Observe.List.
- // Currently, it's API is designed for `can/view/render`, but
- // it could easily be used for other purposes.
-
- // ### Helper methods
- // #### setup
- // `setup(HTMLElement, bind(data), unbind(data)) -> data`
- // Calls bind right away, but will call unbind
- // if the element is "destroyed" (removed from the DOM).
- var setup = function(el, bind, unbind) {
- var teardown = function() {
- unbind(data)
- can.unbind.call(el, 'destroyed', teardown);
- },
- data = {
- teardownCheck: function(parent) {
- if (!parent) {
- teardown();
- }
- }
- }
-
- can.bind.call(el, 'destroyed', teardown);
- bind(data)
- return data;
- },
- // #### listen
- // Calls setup, but presets bind and unbind to
- // operate on a compute
- listen = function(el, compute, change) {
- return setup(el, function() {
- compute.bind("change", change);
- }, function(data) {
- compute.unbind("change", change);
- if (data.nodeList) {
- nodeLists.unregister(data.nodeList);
- }
- });
- },
- // #### getAttributeParts
- // Breaks up a string like foo='bar' into ["foo","'bar'""]
- getAttributeParts = function(newVal) {
- return (newVal || "").replace(/['"]/g, '').split('=')
- }
- // #### insertElementsAfter
- // Appends elements after the last item in oldElements.
- insertElementsAfter = function(oldElements, newFrag) {
- var last = oldElements[oldElements.length - 1];
-
- // Insert it in the `document` or `documentFragment`
- if (last.nextSibling) {
- last.parentNode.insertBefore(newFrag, last.nextSibling);
- } else {
- last.parentNode.appendChild(newFrag);
- }
- };
-
- var live = {
- nodeLists: nodeLists,
- list: function(el, list, func, context, parentNode) {
- // A mapping of the index to an array
- // of elements that represent the item.
- // Each array is registered so child or parent
- // live structures can update the elements
- var nodesMap = [],
-
- add = function(ev, items, index) {
-
- // Collect new html and mappings
- var frag = document.createDocumentFragment(),
- newMappings = [];
- can.each(items, function(item) {
- var itemHTML = func.call(context, item),
- itemFrag = can.view.frag(itemHTML, parentNode);
-
- newMappings.push(can.makeArray(itemFrag.childNodes));
- frag.appendChild(itemFrag);
- })
-
- // Inserting at the end of the list
- if (!nodesMap[index]) {
- insertElementsAfter(
- index == 0 ? [text] :
- nodesMap[index - 1], frag)
- } else {
- var el = nodesMap[index][0];
- el.parentNode.insertBefore(frag, el)
- }
- // register each item
- can.each(newMappings, function(nodeList) {
- nodeLists.register(nodeList)
- });
- [].splice.apply(nodesMap, [index, 0].concat(newMappings));
- },
- remove = function(ev, items, index) {
- var removedMappings = nodesMap.splice(index, items.length),
- itemsToRemove = [];
-
- can.each(removedMappings, function(nodeList) {
- // add items that we will remove all at once
- [].push.apply(itemsToRemove, nodeList)
- // Update any parent lists to remove these items
- nodeLists.replace(nodeList, []);
- // unregister the list
- nodeLists.unregister(nodeList);
-
- });
- can.remove(can.$(itemsToRemove));
- },
- parentNode = elements.getParentNode(el, parentNode),
- text = document.createTextNode("");
-
- // Setup binding and teardown to add and remove events
- setup(parentNode, function() {
- list.bind("add", add).bind("remove", remove)
- }, function() {
- list.unbind("add", add).unbind("remove", remove);
- can.each(nodesMap, function(nodeList) {
- nodeLists.unregister(nodeList);
- })
- })
-
- insertElementsAfter([el], text);
- can.remove(can.$(el));
- add({}, list, 0);
-
- },
- html: function(el, compute, parentNode) {
- var parentNode = elements.getParentNode(el, parentNode),
-
- data = listen(parentNode, compute, function(ev, newVal, oldVal) {
- var attached = nodes[0].parentNode;
- // update the nodes in the DOM with the new rendered value
- if (attached) {
- makeAndPut(newVal);
- }
- data.teardownCheck(nodes[0].parentNode);
- });
-
- var nodes,
- makeAndPut = function(val) {
- // create the fragment, but don't hook it up
- // we need to insert it into the document first
- var frag = can.view.frag(val, parentNode),
- // keep a reference to each node
- newNodes = can.makeArray(frag.childNodes);
- // Insert it in the `document` or `documentFragment`
- insertElementsAfter(nodes || [el], frag)
- // nodes hasn't been set yet
- if (!nodes) {
- can.remove(can.$(el));
- nodes = newNodes;
- // set the teardown nodeList
- data.nodeList = nodes;
- nodeLists.register(nodes);
- } else {
- // Update node Array's to point to new nodes
- // and then remove the old nodes.
- // It has to be in this order for Mootools
- // and IE because somehow, after an element
- // is removed from the DOM, it loses its
- // expando values.
- var nodesToRemove = can.makeArray(nodes);
- nodeLists.replace(nodes, newNodes);
- can.remove(can.$(nodesToRemove));
- }
- };
- makeAndPut(compute(), [el]);
-
- },
- text: function(el, compute, parentNode) {
- var parent = elements.getParentNode(el, parentNode);
-
- // setup listening right away so we don't have to re-calculate value
- var data = listen(el.parentNode !== parent ? el.parentNode : parent, compute, function(ev, newVal, oldVal) {
- // Sometimes this is 'unknown' in IE and will throw an exception if it is
- if (typeof node.nodeValue != 'unknown') {
- node.nodeValue = "" + newVal;
- }
- data.teardownCheck(node.parentNode);
- });
-
- var node = document.createTextNode(compute());
-
- if (el.parentNode !== parent) {
- parent = el.parentNode;
- parent.insertBefore(node, el);
- parent.removeChild(el);
- } else {
- parent.insertBefore(node, el);
- parent.removeChild(el);
- }
- },
- attributes: function(el, compute, currentValue) {
- var setAttrs = function(newVal) {
- var parts = getAttributeParts(newVal),
- newAttrName = parts.shift();
-
- // Remove if we have a change and used to have an `attrName`.
- if ((newAttrName != attrName) && attrName) {
- elements.removeAttr(el, attrName);
- }
- // Set if we have a new `attrName`.
- if (newAttrName) {
- elements.setAttr(el, newAttrName, parts.join('='));
- attrName = newAttrName;
- }
- }
-
- listen(el, compute, function(ev, newVal) {
- setAttrs(newVal)
- })
- // current value has been set
- if (arguments.length >= 3) {
- var attrName = getAttributeParts(currentValue)[0]
- } else {
- setAttrs(compute())
- }
- },
- attributePlaceholder: '__!!__',
- attributeReplace: /__!!__/g,
- attribute: function(el, attributeName, compute) {
- listen(el, compute, function(ev, newVal) {
- elements.setAttr(el, attributeName, hook.render());
- })
-
- var wrapped = can.$(el),
- hooks;
-
- // Get the list of hookups or create one for this element.
- // Hooks is a map of attribute names to hookup `data`s.
- // Each hookup data has:
- // `render` - A `function` to render the value of the attribute.
- // `funcs` - A list of hookup `function`s on that attribute.
- // `batchNum` - The last event `batchNum`, used for performance.
- hooks = can.data(wrapped, 'hooks');
- if (!hooks) {
- can.data(wrapped, 'hooks', hooks = {});
- }
-
- // Get the attribute value.
- var attr = elements.getAttr(el, attributeName),
- // Split the attribute value by the template.
- // Only split out the first __!!__ so if we have multiple hookups in the same attribute,
- // they will be put in the right spot on first render
- parts = attr.split(live.attributePlaceholder),
- goodParts = [],
- hook;
- goodParts.push(parts.shift(),
- parts.join(live.attributePlaceholder));
-
- // If we already had a hookup for this attribute...
- if (hooks[attributeName]) {
- // Just add to that attribute's list of `function`s.
- hooks[attributeName].computes.push(compute);
- } else {
- // Create the hookup data.
- hooks[attributeName] = {
- render: function() {
- var i = 0,
- // attr doesn't have a value in IE
- newAttr = attr ? attr.replace(live.attributeReplace, function() {
- return elements.contentText(hook.computes[i++]());
- }) : elements.contentText(hook.computes[i++]());
- return newAttr;
- },
- computes: [compute],
- batchNum: undefined
- };
- }
-
- // Save the hook for slightly faster performance.
- hook = hooks[attributeName];
-
- // Insert the value in parts.
- goodParts.splice(1, 0, compute());
-
- // Set the attribute.
- elements.setAttr(el, attributeName, goodParts.join(""));
-
- }
- }
- return live;
-
- })(__m3, __m14, __m11, __m17);
-
- // ## view/render.js
- var __m15 = (function(can, elements, live) {
-
- var pendingHookups = [],
- tagChildren = function(tagName) {
- var newTag = elements.tagMap[tagName] || "span";
- if (newTag === "span") {
- //innerHTML in IE doesn't honor leading whitespace after empty elements
- return "@@!!@@";
- }
- return "<" + newTag + ">" + tagChildren(newTag) + "</" + newTag + ">";
- },
- contentText = function(input, tag) {
-
- // If it's a string, return.
- if (typeof input == 'string') {
- return input;
- }
- // If has no value, return an empty string.
- if (!input && input !== 0) {
- return '';
- }
-
- // If it's an object, and it has a hookup method.
- var hook = (input.hookup &&
-
- // Make a function call the hookup method.
-
- function(el, id) {
- input.hookup.call(input, el, id);
- }) ||
-
- // Or if it's a `function`, just use the input.
- (typeof input == 'function' && input);
-
- // Finally, if there is a `function` to hookup on some dom,
- // add it to pending hookups.
- if (hook) {
- if (tag) {
- return "<" + tag + " " + can.view.hook(hook) + "></" + tag + ">"
- } else {
- pendingHookups.push(hook);
- }
-
- return '';
- }
-
- // Finally, if all else is `false`, `toString()` it.
- return "" + input;
- },
- // Returns escaped/sanatized content for anything other than a live-binding
- contentEscape = function(txt) {
- return (typeof txt == 'string' || typeof txt == 'number') ?
- can.esc(txt) :
- contentText(txt);
- };
-
- var current;
-
- can.extend(can.view, {
- live: live,
- setupLists: function() {
-
- var old = can.view.lists,
- data;
-
- can.view.lists = function(list, renderer) {
- data = {
- list: list,
- renderer: renderer
- }
- }
- return function() {
- can.view.lists = old;
- return data;
- }
- },
- pending: function() {
- // TODO, make this only run for the right tagName
- var hooks = pendingHookups.slice(0);
- lastHookups = hooks;
- pendingHookups = [];
- return can.view.hook(function(el) {
- can.each(hooks, function(fn) {
- fn(el);
- });
- });
- },
-
-
- txt: function(escape, tagName, status, self, func) {
- var listTeardown = can.view.setupLists(),
- emptyHandler = function() {},
- unbind = function() {
- compute.unbind("change", emptyHandler)
- };
-
- var compute = can.compute(func, self, false);
- // bind to get and temporarily cache the value
- compute.bind("change", emptyHandler);
- // call the "wrapping" function and get the binding information
- var tag = (elements.tagMap[tagName] || "span"),
- listData = listTeardown(),
- value = compute();
-
-
- if (listData) {
- return "<" + tag + can.view.hook(function(el, parentNode) {
- live.list(el, listData.list, listData.renderer, self, parentNode);
- }) + "></" + tag + ">";
- }
-
- // If we had no observes just return the value returned by func.
- if (!compute.hasDependencies) {
- unbind();
- return (escape || status !== 0 ? contentEscape : contentText)(value, status === 0 && tag);
- }
-
- // the property (instead of innerHTML elements) to adjust. For
- // example options should use textContent
- var contentProp = elements.tagToContentPropMap[tagName];
-
-
- // The magic tag is outside or between tags.
- if (status === 0 && !contentProp) {
- // Return an element tag with a hookup in place of the content
- return "<" + tag + can.view.hook(
- escape ?
- // If we are escaping, replace the parentNode with
- // a text node who's value is `func`'s return value.
-
- function(el, parentNode) {
- live.text(el, compute, parentNode);
- unbind();
- } :
- // If we are not escaping, replace the parentNode with a
- // documentFragment created as with `func`'s return value.
-
- function(el, parentNode) {
- live.html(el, compute, parentNode);
- unbind();
- //children have to be properly nested HTML for buildFragment to work properly
- }) + ">" + tagChildren(tag) + "</" + tag + ">";
- // In a tag, but not in an attribute
- } else if (status === 1) {
- // remember the old attr name
- pendingHookups.push(function(el) {
- live.attributes(el, compute, compute());
- unbind();
- });
- return compute();
- } else { // In an attribute...
- var attributeName = status === 0 ? contentProp : status;
- // if the magic tag is inside the element, like `<option><% TAG %></option>`,
- // we add this hookup to the last element (ex: `option`'s) hookups.
- // Otherwise, the magic tag is in an attribute, just add to the current element's
- // hookups.
- (status === 0 ? lastHookups : pendingHookups).push(function(el) {
- live.attribute(el, attributeName, compute);
- unbind();
- });
- return live.attributePlaceholder;
- }
- }
- });
-
- return can;
- })(__m11, __m14, __m16, __m2);
-
- // ## view/ejs/ejs.js
- var __m12 = (function(can) {
- // ## ejs.js
- // `can.EJS`
- // _Embedded JavaScript Templates._
-
- // Helper methods.
- var extend = can.extend,
- EJS = function(options) {
- // Supports calling EJS without the constructor
- // This returns a function that renders the template.
- if (this.constructor != EJS) {
- var ejs = new EJS(options);
- return function(data, helpers) {
- return ejs.render(data, helpers);
- };
- }
- // If we get a `function` directly, it probably is coming from
- // a `steal`-packaged view.
- if (typeof options == "function") {
- this.template = {
- fn: options
- };
- return;
- }
- // Set options on self.
- extend(this, options);
- this.template = this.scanner.scan(this.text, this.name);
- };
-
- can.EJS = EJS;
-
-
- EJS.prototype.
-
- render = function(object, extraHelpers) {
- object = object || {};
- return this.template.fn.call(object, object, new EJS.Helpers(object, extraHelpers || {}));
- };
-
- extend(EJS.prototype, {
-
- scanner: new can.view.Scanner({
-
- tokens: [
- ["templateLeft", "<%%"], // Template
- ["templateRight", "%>"], // Right Template
- ["returnLeft", "<%=="], // Return Unescaped
- ["escapeLeft", "<%="], // Return Escaped
- ["commentLeft", "<%#"], // Comment
- ["left", "<%"], // Run --- this is hack for now
- ["right", "%>"], // Right -> All have same FOR Mustache ...
- ["returnRight", "%>"]
- ],
-
-
- transform: function(source) {
- return source.replace(/<%([\s\S]+?)%>/gm, function(whole, part) {
- var brackets = [],
- foundBracketPair,
- i;
-
- // Look for brackets (for removing self-contained blocks)
- part.replace(/[{}]/gm, function(bracket, offset) {
- brackets.push([bracket, offset]);
- });
-
- // Remove bracket pairs from the list of replacements
- do {
- foundBracketPair = false;
- for (i = brackets.length - 2; i >= 0; i--) {
- if (brackets[i][0] == '{' && brackets[i + 1][0] == '}') {
- brackets.splice(i, 2);
- foundBracketPair = true;
- break;
- }
- }
- } while (foundBracketPair);
-
- // Unmatched brackets found, inject EJS tags
- if (brackets.length >= 2) {
- var result = ['<%'],
- bracket,
- last = 0;
- for (i = 0; bracket = brackets[i]; i++) {
- result.push(part.substring(last, last = bracket[1]));
- if ((bracket[0] == '{' && i < brackets.length - 1) || (bracket[0] == '}' && i > 0)) {
- result.push(bracket[0] == '{' ? '{ %><% ' : ' %><% }');
- } else {
- result.push(bracket[0]);
- }
- ++last;
- }
- result.push(part.substring(last), '%>');
- return result.join('');
- }
- // Otherwise return the original
- else {
- return '<%' + part + '%>';
- }
- });
- }
- })
- });
-
- EJS.Helpers = function(data, extras) {
- this._data = data;
- this._extras = extras;
- extend(this, extras);
- };
-
-
- EJS.Helpers.prototype = {
- // TODO Deprecated!!
- list: function(list, cb) {
-
- can.each(list, function(item, i) {
- cb(item, i, list)
- })
- },
- each: function(list, cb) {
- // Normal arrays don't get live updated
- if (can.isArray(list)) {
- this.list(list, cb);
- } else {
- can.view.lists(list, cb);
- }
- }
- };
-
- // Options for `steal`'s build.
- can.view.register({
- suffix: "ejs",
- // returns a `function` that renders the view.
- script: function(id, src) {
- return "can.EJS(function(_CONTEXT,_VIEW) { " + new EJS({
- text: src,
- name: id
- }).template.out + " })";
- },
- renderer: function(id, text) {
- return EJS({
- text: text,
- name: id
- });
- }
- });
-
- return can;
- })(__m3, __m11, __m2, __m9, __m13, __m15);
-
- // ## control/control.js
- var __m18 = (function(can) {
- // ## control.js
- // `can.Control`
- // _Controller_
-
- // Binds an element, returns a function that unbinds.
- var bind = function(el, ev, callback) {
-
- can.bind.call(el, ev, callback);
-
- return function() {
- can.unbind.call(el, ev, callback);
- };
- },
- isFunction = can.isFunction,
- extend = can.extend,
- each = can.each,
- slice = [].slice,
- paramReplacer = /\{([^\}]+)\}/g,
- special = can.getObject("$.event.special", [can]) || {},
-
- // Binds an element, returns a function that unbinds.
- delegate = function(el, selector, ev, callback) {
- can.delegate.call(el, selector, ev, callback);
- return function() {
- can.undelegate.call(el, selector, ev, callback);
- };
- },
-
- // Calls bind or unbind depending if there is a selector.
- binder = function(el, ev, callback, selector) {
- return selector ?
- delegate(el, can.trim(selector), ev, callback) :
- bind(el, ev, callback);
- },
-
- basicProcessor;
-
- var Control = can.Control = can.Construct(
-
- {
- // Setup pre-processes which methods are event listeners.
-
- setup: function() {
-
- // Allow contollers to inherit "defaults" from super-classes as it
- // done in `can.Construct`
- can.Construct.setup.apply(this, arguments);
-
- // If you didn't provide a name, or are `control`, don't do anything.
- if (can.Control) {
-
- // Cache the underscored names.
- var control = this,
- funcName;
-
- // Calculate and cache actions.
- control.actions = {};
- for (funcName in control.prototype) {
- if (control._isAction(funcName)) {
- control.actions[funcName] = control._action(funcName);
- }
- }
- }
- },
-
- // Moves `this` to the first argument, wraps it with `jQuery` if it's an element
- _shifter: function(context, name) {
-
- var method = typeof name == "string" ? context[name] : name;
-
- if (!isFunction(method)) {
- method = context[method];
- }
-
- return function() {
- context.called = name;
- return method.apply(context, [this.nodeName ? can.$(this) : this].concat(slice.call(arguments, 0)));
- };
- },
-
- // Return `true` if is an action.
-
- _isAction: function(methodName) {
-
- var val = this.prototype[methodName],
- type = typeof val;
- // if not the constructor
- return (methodName !== 'constructor') &&
- // and is a function or links to a function
- (type == "function" || (type == "string" && isFunction(this.prototype[val]))) &&
- // and is in special, a processor, or has a funny character
- !! (special[methodName] || processors[methodName] || /[^\w]/.test(methodName));
- },
- // Takes a method name and the options passed to a control
- // and tries to return the data necessary to pass to a processor
- // (something that binds things).
-
- _action: function(methodName, options) {
-
- // If we don't have options (a `control` instance), we'll run this
- // later.
- paramReplacer.lastIndex = 0;
- if (options || !paramReplacer.test(methodName)) {
- // If we have options, run sub to replace templates `{}` with a
- // value from the options or the window
- var convertedName = options ? can.sub(methodName, [options, window]) : methodName;
- if (!convertedName) {
- return null;
- }
- // If a `{}` template resolves to an object, `convertedName` will be
- // an array
- var arr = can.isArray(convertedName),
-
- // Get the name
- name = arr ? convertedName[1] : convertedName,
-
- // Grab the event off the end
- parts = name.split(/\s+/g),
- event = parts.pop();
-
- return {
- processor: processors[event] || basicProcessor,
- parts: [name, parts.join(" "), event],
- delegate: arr ? convertedName[0] : undefined
- };
- }
- },
- // An object of `{eventName : function}` pairs that Control uses to
- // hook up events auto-magically.
-
- processors: {},
- // A object of name-value pairs that act as default values for a
- // control instance
- defaults: {}
-
- }, {
-
- // Sets `this.element`, saves the control in `data, binds event
- // handlers.
-
- setup: function(element, options) {
-
- var cls = this.constructor,
- pluginname = cls.pluginName || cls._fullName,
- arr;
-
- // Want the raw element here.
- this.element = can.$(element)
-
- if (pluginname && pluginname !== 'can_control') {
- // Set element and `className` on element.
- this.element.addClass(pluginname);
- }
-
- (arr = can.data(this.element, "controls")) || can.data(this.element, "controls", arr = []);
- arr.push(this);
-
- // Option merging.
-
- this.options = extend({}, cls.defaults, options);
-
- // Bind all event handlers.
- this.on();
-
- // Gets passed into `init`.
-
- return [this.element, this.options];
- },
-
- on: function(el, selector, eventName, func) {
- if (!el) {
-
- // Adds bindings.
- this.off();
-
- // Go through the cached list of actions and use the processor
- // to bind
- var cls = this.constructor,
- bindings = this._bindings,
- actions = cls.actions,
- element = this.element,
- destroyCB = can.Control._shifter(this, "destroy"),
- funcName, ready;
-
- for (funcName in actions) {
- // Only push if we have the action and no option is `undefined`
- if (actions.hasOwnProperty(funcName) &&
- (ready = actions[funcName] || cls._action(funcName, this.options))) {
- bindings.push(ready.processor(ready.delegate || element,
- ready.parts[2], ready.parts[1], funcName, this));
- }
- }
-
-
- // Setup to be destroyed...
- // don't bind because we don't want to remove it.
- can.bind.call(element, "destroyed", destroyCB);
- bindings.push(function(el) {
- can.unbind.call(el, "destroyed", destroyCB);
- });
- return bindings.length;
- }
-
- if (typeof el == 'string') {
- func = eventName;
- eventName = selector;
- selector = el;
- el = this.element;
- }
-
- if (func === undefined) {
- func = eventName;
- eventName = selector;
- selector = null;
- }
-
- if (typeof func == 'string') {
- func = can.Control._shifter(this, func);
- }
-
- this._bindings.push(binder(el, eventName, func, selector));
-
- return this._bindings.length;
- },
- // Unbinds all event handlers on the controller.
-
- off: function() {
- var el = this.element[0]
- each(this._bindings || [], function(value) {
- value(el);
- });
- // Adds bindings.
- this._bindings = [];
- },
- // Prepares a `control` for garbage collection
-
- destroy: function() {
- //Control already destroyed
- if (this.element === null) {
-
- return;
- }
- var Class = this.constructor,
- pluginName = Class.pluginName || Class._fullName,
- controls;
-
- // Unbind bindings.
- this.off();
-
- if (pluginName && pluginName !== 'can_control') {
- // Remove the `className`.
- this.element.removeClass(pluginName);
- }
-
- // Remove from `data`.
- controls = can.data(this.element, "controls");
- controls.splice(can.inArray(this, controls), 1);
-
- can.trigger(this, "destroyed"); // In case we want to know if the `control` is removed.
-
- this.element = null;
- }
- });
-
- var processors = can.Control.processors,
- // Processors do the binding.
- // They return a function that unbinds when called.
- // The basic processor that binds events.
- basicProcessor = function(el, event, selector, methodName, control) {
- return binder(el, event, can.Control._shifter(control, methodName), selector);
- };
-
- // Set common events to be processed as a `basicProcessor`
- each(["change", "click", "contextmenu", "dblclick", "keydown", "keyup",
- "keypress", "mousedown", "mousemove", "mouseout", "mouseover",
- "mouseup", "reset", "resize", "scroll", "select", "submit", "focusin",
- "focusout", "mouseenter", "mouseleave",
- // #104 - Add touch events as default processors
- // TOOD feature detect?
- "touchstart", "touchmove", "touchcancel", "touchend", "touchleave"
- ], function(v) {
- processors[v] = basicProcessor;
- });
-
- return Control;
- })(__m3, __m1);
-
- // ## util/string/deparam/deparam.js
- var __m20 = (function(can) {
-
- // ## deparam.js
- // `can.deparam`
- // _Takes a string of name value pairs and returns a Object literal that represents those params._
- var digitTest = /^\d+$/,
- keyBreaker = /([^\[\]]+)|(\[\])/g,
- paramTest = /([^?#]*)(#.*)?$/,
- prep = function(str) {
- return decodeURIComponent(str.replace(/\+/g, " "));
- };
-
-
- can.extend(can, {
-
- deparam: function(params) {
-
- var data = {},
- pairs, lastPart;
-
- if (params && paramTest.test(params)) {
-
- pairs = params.split('&'),
-
- can.each(pairs, function(pair) {
-
- var parts = pair.split('='),
- key = prep(parts.shift()),
- value = prep(parts.join("=")),
- current = data;
-
- if (key) {
- parts = key.match(keyBreaker);
-
- for (var j = 0, l = parts.length - 1; j < l; j++) {
- if (!current[parts[j]]) {
- // If what we are pointing to looks like an `array`
- current[parts[j]] = digitTest.test(parts[j + 1]) || parts[j + 1] == "[]" ? [] : {};
- }
- current = current[parts[j]];
- }
- lastPart = parts.pop();
- if (lastPart == "[]") {
- current.push(value);
- } else {
- current[lastPart] = value;
- }
- }
- });
- }
- return data;
- }
- });
- return can;
- })(__m3, __m2);
-
- // ## route/route.js
- var __m19 = (function(can) {
-
- // ## route.js
- // `can.route`
- // _Helps manage browser history (and client state) by synchronizing the
- // `window.location.hash` with a `can.Observe`._
- // Helper methods used for matching routes.
- var
- // `RegExp` used to match route variables of the type ':name'.
- // Any word character or a period is matched.
- matcher = /\:([\w\.]+)/g,
- // Regular expression for identifying &key=value lists.
- paramsMatcher = /^(?:&[^=]+=[^&]*)+/,
- // Converts a JS Object into a list of parameters that can be
- // inserted into an html element tag.
- makeProps = function(props) {
- var tags = [];
- can.each(props, function(val, name) {
- tags.push((name === 'className' ? 'class' : name) + '="' +
- (name === "href" ? val : can.esc(val)) + '"');
- });
- return tags.join(" ");
- },
- // Checks if a route matches the data provided. If any route variable
- // is not present in the data, the route does not match. If all route
- // variables are present in the data, the number of matches is returned
- // to allow discerning between general and more specific routes.
- matchesData = function(route, data) {
- var count = 0,
- i = 0,
- defaults = {};
- // look at default values, if they match ...
- for (var name in route.defaults) {
- if (route.defaults[name] === data[name]) {
- // mark as matched
- defaults[name] = 1;
- count++;
- }
- }
- for (; i < route.names.length; i++) {
- if (!data.hasOwnProperty(route.names[i])) {
- return -1;
- }
- if (!defaults[route.names[i]]) {
- count++;
- }
-
- }
-
- return count;
- },
- onready = !0,
- location = window.location,
- wrapQuote = function(str) {
- return (str + '').replace(/([.?*+\^$\[\]\\(){}|\-])/g, "\\$1");
- },
- each = can.each,
- extend = can.extend;
-
- can.route = function(url, defaults) {
- defaults = defaults || {};
- // Extract the variable names and replace with `RegExp` that will match
- // an atual URL with values.
- var names = [],
- test = url.replace(matcher, function(whole, name, i) {
- names.push(name);
- var next = "\\" + (url.substr(i + whole.length, 1) || can.route._querySeparator);
- // a name without a default value HAS to have a value
- // a name that has a default value can be empty
- // The `\\` is for string-escaping giving single `\` for `RegExp` escaping.
- return "([^" + next + "]" + (defaults[name] ? "*" : "+") + ")";
- });
-
- // Add route in a form that can be easily figured out.
- can.route.routes[url] = {
- // A regular expression that will match the route when variable values
- // are present; i.e. for `:page/:type` the `RegExp` is `/([\w\.]*)/([\w\.]*)/` which
- // will match for any value of `:page` and `:type` (word chars or period).
- test: new RegExp("^" + test + "($|" + wrapQuote(can.route._querySeparator) + ")"),
- // The original URL, same as the index for this entry in routes.
- route: url,
- // An `array` of all the variable names in this route.
- names: names,
- // Default values provided for the variables.
- defaults: defaults,
- // The number of parts in the URL separated by `/`.
- length: url.split('/').length
- };
- return can.route;
- };
-
-
- extend(can.route, {
-
- _querySeparator: '&',
- _paramsMatcher: paramsMatcher,
-
-
- param: function(data, _setRoute) {
- // Check if the provided data keys match the names in any routes;
- // Get the one with the most matches.
- var route,
- // Need to have at least 1 match.
- matches = 0,
- matchCount,
- routeName = data.route,
- propCount = 0;
-
- delete data.route;
-
- each(data, function() {
- propCount++;
- });
- // Otherwise find route.
- each(can.route.routes, function(temp, name) {
- // best route is the first with all defaults matching
-
-
- matchCount = matchesData(temp, data);
- if (matchCount > matches) {
- route = temp;
- matches = matchCount;
- }
- if (matchCount >= propCount) {
- return false;
- }
- });
- // If we have a route name in our `can.route` data, and it's
- // just as good as what currently matches, use that
- if (can.route.routes[routeName] && matchesData(can.route.routes[routeName], data) === matches) {
- route = can.route.routes[routeName];
- }
- // If this is match...
- if (route) {
- var cpy = extend({}, data),
- // Create the url by replacing the var names with the provided data.
- // If the default value is found an empty string is inserted.
- res = route.route.replace(matcher, function(whole, name) {
- delete cpy[name];
- return data[name] === route.defaults[name] ? "" : encodeURIComponent(data[name]);
- }),
- after;
- // Remove matching default values
- each(route.defaults, function(val, name) {
- if (cpy[name] === val) {
- delete cpy[name];
- }
- });
-
- // The remaining elements of data are added as
- // `&` separated parameters to the url.
- after = can.param(cpy);
- // if we are paraming for setting the hash
- // we also want to make sure the route value is updated
- if (_setRoute) {
- can.route.attr('route', route.route);
- }
- return res + (after ? can.route._querySeparator + after : "");
- }
- // If no route was found, there is no hash URL, only paramters.
- return can.isEmptyObject(data) ? "" : can.route._querySeparator + can.param(data);
- },
-
- deparam: function(url) {
- // See if the url matches any routes by testing it against the `route.test` `RegExp`.
- // By comparing the URL length the most specialized route that matches is used.
- var route = {
- length: -1
- };
- each(can.route.routes, function(temp, name) {
- if (temp.test.test(url) && temp.length > route.length) {
- route = temp;
- }
- });
- // If a route was matched.
- if (route.length > -1) {
-
- var // Since `RegExp` backreferences are used in `route.test` (parens)
- // the parts will contain the full matched string and each variable (back-referenced) value.
- parts = url.match(route.test),
- // Start will contain the full matched string; parts contain the variable values.
- start = parts.shift(),
- // The remainder will be the `&key=value` list at the end of the URL.
- remainder = url.substr(start.length - (parts[parts.length - 1] === can.route._querySeparator ? 1 : 0)),
- // If there is a remainder and it contains a `&key=value` list deparam it.
- obj = (remainder && can.route._paramsMatcher.test(remainder)) ? can.deparam(remainder.slice(1)) : {};
-
- // Add the default values for this route.
- obj = extend(true, {}, route.defaults, obj);
- // Overwrite each of the default values in `obj` with those in
- // parts if that part is not empty.
- each(parts, function(part, i) {
- if (part && part !== can.route._querySeparator) {
- obj[route.names[i]] = decodeURIComponent(part);
- }
- });
- obj.route = route.route;
- return obj;
- }
- // If no route was matched, it is parsed as a `&key=value` list.
- if (url.charAt(0) !== can.route._querySeparator) {
- url = can.route._querySeparator + url;
- }
- return can.route._paramsMatcher.test(url) ? can.deparam(url.slice(1)) : {};
- },
-
- data: new can.Observe({}),
-
- routes: {},
-
- ready: function(val) {
- if (val === false) {
- onready = val;
- }
- if (val === true || onready === true) {
- can.route._setup();
- setState();
- }
- return can.route;
- },
-
- url: function(options, merge) {
- if (merge) {
- options = extend({}, curParams, options)
- }
- return "#!" + can.route.param(options);
- },
-
- link: function(name, options, props, merge) {
- return "<a " + makeProps(
- extend({
- href: can.route.url(options, merge)
- }, props)) + ">" + name + "</a>";
- },
-
- current: function(options) {
- return location.hash == "#!" + can.route.param(options)
- },
- _setup: function() {
- // If the hash changes, update the `can.route.data`.
- can.bind.call(window, 'hashchange', setState);
- },
- _getHash: function() {
- return location.href.split(/#!?/)[1] || "";
- },
- _setHash: function(serialized) {
- var path = (can.route.param(serialized, true));
- location.hash = "#!" + path;
- return path;
- }
- });
-
-
- // The functions in the following list applied to `can.route` (e.g. `can.route.attr('...')`) will
- // instead act on the `can.route.data` observe.
- each(['bind', 'unbind', 'delegate', 'undelegate', 'attr', 'removeAttr'], function(name) {
- can.route[name] = function() {
- // `delegate` and `undelegate` require
- // the `can/observe/delegate` plugin
- if (!can.route.data[name]) {
- return;
- }
-
- return can.route.data[name].apply(can.route.data, arguments);
- }
- })
-
- var // A ~~throttled~~ debounced function called multiple times will only fire once the
- // timer runs down. Each call resets the timer.
- timer,
- // Intermediate storage for `can.route.data`.
- curParams,
- // Deparameterizes the portion of the hash of interest and assign the
- // values to the `can.route.data` removing existing values no longer in the hash.
- // setState is called typically by hashchange which fires asynchronously
- // So it's possible that someone started changing the data before the
- // hashchange event fired. For this reason, it will not set the route data
- // if the data is changing or the hash already matches the hash that was set.
- setState = can.route.setState = function() {
- var hash = can.route._getHash();
- curParams = can.route.deparam(hash);
-
- // if the hash data is currently changing, or
- // the hash is what we set it to anyway, do NOT change the hash
- if (!changingData || hash !== lastHash) {
- can.route.attr(curParams, true);
- }
- },
- // The last hash caused by a data change
- lastHash,
- // Are data changes pending that haven't yet updated the hash
- changingData;
-
- // If the `can.route.data` changes, update the hash.
- // Using `.serialize()` retrieves the raw data contained in the `observable`.
- // This function is ~~throttled~~ debounced so it only updates once even if multiple values changed.
- // This might be able to use batchNum and avoid this.
- can.route.bind("change", function(ev, attr) {
- // indicate that data is changing
- changingData = 1;
- clearTimeout(timer);
- timer = setTimeout(function() {
- // indicate that the hash is set to look like the data
- changingData = 0;
- var serialized = can.route.data.serialize();
-
- lastHash = can.route._setHash(serialized);
- }, 1);
- });
- // `onready` event...
- can.bind.call(document, "ready", can.route.ready);
-
- // Libraries other than jQuery don't execute the document `ready` listener
- // if we are already DOM ready
- if ((document.readyState === 'complete' || document.readyState === "interactive") && onready) {
- can.route.ready();
- }
-
- // extend route to have a similar property
- // that is often checked in mustache to determine
- // an object's observability
- can.route.constructor.canMakeObserve = can.Observe.canMakeObserve;
-
- return can.route;
- })(__m3, __m7, __m20);
-
- // ## control/route/route.js
- var __m21 = (function(can) {
-
- // ## control/route.js
- // _Controller route integration._
-
- can.Control.processors.route = function(el, event, selector, funcName, controller) {
- selector = selector || "";
- can.route(selector);
- var batchNum,
- check = function(ev, attr, how) {
- if (can.route.attr('route') === (selector) &&
- (ev.batchNum === undefined || ev.batchNum !== batchNum)) {
-
- batchNum = ev.batchNum;
-
- var d = can.route.attr();
- delete d.route;
- if (can.isFunction(controller[funcName])) {
- controller[funcName](d);
- } else {
- controller[controller[funcName]](d);
- }
-
- }
- };
- can.route.bind('change', check);
- return function() {
- can.route.unbind('change', check);
- };
- };
-
- return can;
- })(__m3, __m19, __m18);
-
- window['can'] = __m5;
- })();
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.min.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.min.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.jquery.min.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,11 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:22 GMT
- * Licensed MIT
- * Includes: CanJS default build
- * Download from: http://canjs.us/
- */
-!function(undefined){var __m5=function(){var a=window.can||{};("undefined"==typeof GLOBALCAN||GLOBALCAN!==!1)&&(window.can=a),a.isDeferred=function(a){var b=this.isFunction;return a&&b(a.then)&&b(a.pipe)};var b=0;return a.cid=function(a,c){return a._cid?a._cid:a._cid=(c||"")+ ++b},a.VERSION="@EDGE",a}(),__m6=function(a){return a.each=function(a,b,c){var d,e=0;if(a)if("number"==typeof a.length&&a.pop)for(a.attr&&a.attr("length"),d=a.length;d>e&&b.call(c||a[e],a[e],e,a)!==!1;e++);else if(a.hasOwnProperty)for(d in a)if(a.hasOwnProperty(d)&&b.call(c||a[d],a[d],d,a)===!1)break;return a},a}(__m5),__m3=function(a,b){a.extend(b,a,{trigger:function(b,c,d){b.trigger?b.trigger(c,d):a.event.trigger(c,d,b,!0)},addEvent:function(b,c){return a([this]).bind(b,c),this},removeEvent:function(b,c){return a([this]).unbind(b,c),this},buildFragment:function(b,c){var d,e=a.buildFragment;return b=[b],c=c||document,c=!c.nodeType&&c[0]||c,c=c.ownerDocument||c,d=e.call(jQuery,b,c),d.cacheable?a.clone(d.fragment):d.fragment||d},$:a,each:b.each}),a.each(["bind","unbind","undelegate","delegate"],function(c,d){b[d]=function(){var b=this[d]?this:a([this]);return b[d].apply(b,arguments),this}}),a.each(["append","filter","addClass","remove","data","get"],function(a,c){b[c]=function(a){return a[c].apply(a,b.makeArray(arguments).slice(1))}});var c=a.cleanData;return a.cleanData=function(d){a.each(d,function(a,c){c&&b.trigger(c,"destroyed",[],!1)}),c(d)},b}(jQuery,__m5,__m6),__m2=function(a){var b=/_|-/,c=/\=\=/,d=/([A-Z]+)([A-Z][a-z])/g,e=/([a-z\d])([A-Z])/g,f=/([a-z\d])([A-Z])/g,g=/\{([^\}]+)\}/g,h=/"/g,i=/'/g,j=function(a,b,c){var d=a[b];return d===undefined&&c===!0&&(d=a[b]={}),d},k=function(a){return/^f|^o/.test(typeof a)};return a.extend(a,{esc:function(a){var b=null===a||a===undefined||isNaN(a)&&"NaN"==""+a;return(""+(b?"":a)).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(h,""").replace(i,"'")},getObject:function(b,c,d){var e,f,g,h,i=b?b.split("."):[],l=i.length,m=0;if(c=a.isArray(c)?c:[c||window],h=c.length,!l)return c[0];for(m;h>m;m++){for(e=c[m],g=undefined,f=0;l>f&&k(e);f++)g=e,e=j(g,i[f]);if(g!==undefined&&e!==undefined)break}if(d===!1&&e!==undefined&&delete g[i[f-1]],d===!0&&e===undefined)for(e=c[0],f=0;l>f&&k(e);f++)e=j(e,i[f],!0);return e},capitalize:function(a){return a.charAt(0).toUpperCase()+a.slice(1)},underscore:function(a){return a.replace(c,"/").replace(d,"$1_$2").replace(e,"$1_$2").replace(f,"_").toLowerCase()},sub:function(b,c,d){var e=[];return b=b||"",e.push(b.replace(g,function(b,f){var g=a.getObject(f,c,d===!0?!1:undefined);return g===undefined?(e=null,""):k(g)&&e?(e.push(g),""):""+g})),null===e?e:e.length<=1?e[0]:e},replacer:g,undHash:b}),a}(__m3),__m1=function(a){var b=0;return a.Construct=function(){return arguments.length?a.Construct.extend.apply(a.Construct,arguments):void 0},a.extend(a.Construct,{newInstance:function(){var a,b=this.instance();return b.setup&&(a=b.setup.apply(b,arguments)),b.init&&b.init.apply(b,a||arguments),b},_inherit:function(b,c,d){a.extend(d||b,b||{})},_overwrite:function(a,b,c,d){a[c]=d},setup:function(b){this.defaults=a.extend(!0,{},b.defaults,this.defaults)},instance:function(){b=1;var a=new this;return b=0,a},extend:function(c,d,e){function f(){return b?void 0:this.constructor!==f&&arguments.length?arguments.callee.extend.apply(arguments.callee,arguments):this.constructor.newInstance.apply(this.constructor,arguments)}"string"!=typeof c&&(e=d,d=c,c=null),e||(e=d,d=null),e=e||{};var g,h,i,j,k=this,l=this.prototype;j=this.instance(),a.Construct._inherit(e,l,j);for(g in k)k.hasOwnProperty(g)&&(f[g]=k[g]);if(a.Construct._inherit(d,k,f),c){var m=c.split("."),h=m.pop(),n=a.getObject(m.join("."),window,!0),i=n,o=a.underscore(c.replace(/\./g,"_")),p=a.underscore(h);n[h]=f}a.extend(f,{constructor:f,prototype:j,namespace:i,_shortName:p,fullName:c,_fullName:o}),h!==undefined&&(f.shortName=h),f.prototype.constructor=f;var q=[k].concat(a.makeArray(arguments)),r=f.setup.apply(f,q);return f.init&&f.init.apply(f,r||q),f}}),a.Construct}(__m2),__m8=function(a){return a.bindAndSetup=function(){return a.addEvent.apply(this,arguments),this._init||(this._bindings?this._bindings++:(this._bindings=1,this._bindsetup&&this._bindsetup())),this},a.unbindAndTeardown=function(){return a.removeEvent.apply(this,arguments),this._bindings--,this._bindings||this._bindteardown&&this._bindteardown(),this},a}(__m3),__m7=function(a){var b=function(b){return b&&!a.isDeferred(b)&&(a.isArray(b)||a.isPlainObject(b)||b instanceof a.Observe)},c=function(b,c){return a.each(b,function(a){a&&a.unbind&&a.unbind("change"+c)})},d=function(b,d,g,h,i){return h=h||f,i=i||f.List,b instanceof f?g._bindings&&c([b],g._cid):b=a.isArray(b)?new i(b):new h(b),g._bindings&&e(b,d,g),b},e=function(b,c,d){b.bind("change"+d._cid,function(){var e=a.makeArray(arguments),f=e.shift();e[0]=("*"===c?[d.indexOf(b),e[0]]:[c,e[0]]).join("."),f.triggeredNS=f.triggeredNS||{},f.triggeredNS[d._cid]||(f.triggeredNS[d._cid]=!0,a.trigger(d,f,e))})};observeId=0,serialize=function(c,d,e){return c.each(function(c,f){e[f]=b(c)&&a.isFunction(c[d])?c[d]():c}),e},attrParts=function(b,c){return c?[b]:a.isArray(b)?b:(""+b).split(".")},batchNum=1,transactions=0,batchEvents=[],stopCallbacks=[],makeBindSetup=function(a){return function(){var b=this;this._each(function(c,d){c&&c.bind&&e(c,a||d,b)})}};var f=a.Map=a.Observe=a.Construct({bind:a.bindAndSetup,unbind:a.unbindAndTeardown,id:"id",canMakeObserve:b,startBatch:function(a){transactions++,a&&stopCallbacks.push(a)},stopBatch:function(b,c){if(b?transactions=0:transactions--,0==transactions){var d=batchEvents.slice(0),e=stopCallbacks.slice(0);batchEvents=[],stopCallbacks=[],batchNum++,c&&this.startBatch(),a.each(d,function(b){a.trigger.apply(a,b)}),a.each(e,function(a){a()})}},triggerBatch:function(b,c,d){if(!b._init){if(0==transactions)return a.trigger(b,c,d);c="string"==typeof c?{type:c}:c,c.batchNum=batchNum,batchEvents.push([b,c,d])}},keys:function(a){var b=[];f.__reading&&f.__reading(a,"__keys");for(var c in a._data)b.push(c);return b}},{setup:function(b){this._data={},a.cid(this,".observe"),this._init=1,this.attr(b),this.bind("change"+this._cid,a.proxy(this._changes,this)),delete this._init},_bindsetup:makeBindSetup(),_bindteardown:function(){var a=this._cid;this._each(function(b){c([b],a)})},_changes:function(a,b,c,d,e){f.triggerBatch(this,{type:b,batchNum:a.batchNum},[d,e])},_triggerChange:function(){f.triggerBatch(this,"change",a.makeArray(arguments))},_each:function(a){var b=this.__get();for(var c in b)b.hasOwnProperty(c)&&a(b[c],c)},attr:function(a,b){var c=typeof a;return"string"!==c&&"number"!==c?this._attrs(a,b):b===undefined?(f.__reading&&f.__reading(this,a),this._get(a)):(this._set(a,b),this)},each:function(){return f.__reading&&f.__reading(this,"__keys"),a.each.apply(undefined,[this.__get()].concat(a.makeArray(arguments)))},removeAttr:function(b){var c=this instanceof a.Observe.List,d=attrParts(b),e=d.shift(),g=c?this[e]:this._data[e];return d.length?g.removeAttr(d):(c?this.splice(e,1):e in this._data&&(delete this._data[e],e in this.constructor.prototype||delete this[e],f.triggerBatch(this,"__keys"),this._triggerChange(e,"remove",undefined,g)),g)},_get:function(a){var b="string"==typeof a&&!!~a.indexOf(".")&&this.__get(a);if(b)return b;var c=attrParts(a),d=this.__get(c.shift());return c.length?d?d._get(c):undefined:d},__get:function(a){return a?this._data[a]:this._data},_set:function(a,c,d){var e=attrParts(a,d),f=e.shift(),g=this.__get(f);if(b(g)&&e.length)g._set(e,c);else{if(e.length)throw"can.Observe: Object does not exist";this.__convert&&(c=this.__convert(f,c)),this.__set(f,c,g)}},__set:function(a,e,g){if(e!==g){var h=this.__get().hasOwnProperty(a)?"set":"add";this.___set(a,b(e)?d(e,a,this):e),"add"==h&&f.triggerBatch(this,"__keys",undefined),this._triggerChange(a,h,e,g),g&&c([g],this._cid)}},___set:function(a,b){this._data[a]=b,a in this.constructor.prototype||(this[a]=b)},bind:a.bindAndSetup,unbind:a.unbindAndTeardown,serialize:function(){return serialize(this,"serialize",{})},_attrs:function(c,d){if(c===undefined)return serialize(this,"attr",{});c=a.extend({},c);var e,g,h=this;f.startBatch(),this.each(function(e,f){return g=c[f],g===undefined?(d&&h.removeAttr(f),void 0):(h.__convert&&(g=h.__convert(f,g)),g instanceof a.Observe?h.__set(f,g,e):b(e)&&b(g)&&e.attr?e.attr(g,d):e!=g&&h.__set(f,g,e),delete c[f],void 0)});for(var e in c)g=c[e],this._set(e,g,!0);return f.stopBatch(),this},compute:function(b){return a.compute(this,b)}}),g=[].splice,h=f({setup:function(b,c){this.length=0,a.cid(this,".observe"),this._init=1,a.isDeferred(b)?this.replace(b):this.push.apply(this,a.makeArray(b||[])),this.bind("change"+this._cid,a.proxy(this._changes,this)),a.extend(this,c),delete this._init},_triggerChange:function(a,b,c,d){f.prototype._triggerChange.apply(this,arguments),~a.indexOf(".")||("add"===b?(f.triggerBatch(this,b,[c,+a]),f.triggerBatch(this,"length",[this.length])):"remove"===b?(f.triggerBatch(this,b,[d,+a]),f.triggerBatch(this,"length",[this.length])):f.triggerBatch(this,b,[c,+a]))},__get:function(a){return a?this[a]:this},___set:function(a,b){this[a]=b,+a>=this.length&&(this.length=+a+1)},_each:function(a){for(var b=this.__get(),c=0;c<b.length;c++)a(b[c],c)},_bindsetup:makeBindSetup("*"),serialize:function(){return serialize(this,"serialize",[])},splice:function(e,f){var h,i=a.makeArray(arguments);for(h=2;h<i.length;h++){var j=i[h];b(j)&&(i[h]=d(j,"*",this,this.constructor.Observe,this.constructor))}f===undefined&&(f=i[1]=this.length-e);var k=g.apply(this,i);return a.Observe.startBatch(),f>0&&(this._triggerChange(""+e,"remove",undefined,k),c(k,this._cid)),i.length>2&&this._triggerChange(""+e,"add",i.slice(2),k),a.Observe.stopBatch(),k},_attrs:function(b,c){return b===undefined?serialize(this,"attr",[]):(b=a.makeArray(b),f.startBatch(),this._updateAttrs(b,c),f.stopBatch(),void 0)},_updateAttrs:function(a,c){for(var d=Math.min(a.length,this.length),e=0;d>e;e++){var f=this[e],g=a[e];b(f)&&b(g)?f.attr(g,c):f!=g&&this._set(e,g)}a.length>this.length?this.push.apply(this,a.slice(this.length)):a.length<this.length&&c&&this.splice(a.length)}}),i=function(b){return b[0]&&a.isArray(b[0])?b[0]:a.makeArray(b)};return a.each({push:"length",unshift:0},function(a,c){var e=[][c];h.prototype[c]=function(){var c,f,g=[],h=a?this.length:0,i=arguments.length;for(this.constructor;i--;)f=arguments[i],g[i]=b(f)?d(f,"*",this,this.constructor.Observe,this.constructor):f;return c=e.apply(this,g),(!this.comparator||g.length)&&this._triggerChange(""+h,"add",g,undefined),c}}),a.each({pop:"length",shift:0},function(a,b){h.prototype[b]=function(){var c=i(arguments),d=a&&this.length?this.length-1:0,e=[][b].apply(this,c);return this._triggerChange(""+d,"remove",undefined,[e]),e&&e.unbind&&e.unbind("change"+this._cid),e}}),a.extend(h.prototype,{indexOf:function(b){return this.attr("length"),a.inArray(b,this)},join:[].join,reverse:[].reverse,slice:function(){var a=Array.prototype.slice.apply(this,arguments);return new this.constructor(a)},concat:function(){var b=[];return a.each(a.makeArray(arguments),function(c,d){b[d]=c instanceof a.Observe.List?c.serialize():c}),new this.constructor(Array.prototype.concat.apply(this.serialize(),b))},forEach:function(b,c){a.each(this,b,c||this)},replace:function(b){return a.isDeferred(b)?b.then(a.proxy(this.replace,this)):this.splice.apply(this,[0,this.length].concat(a.makeArray(b||[]))),this}}),a.List=f.List=h,f.setup=function(){a.Construct.setup.apply(this,arguments),this.List=f.List({Observe:this},{})},f}(__m3,__m8,__m1),__m9=function(a){var b=function(b,c){var d;a.Observe&&(d=a.Observe.__reading,a.Observe.__reading=function(a,b){e.push({obj:a,attr:b+""})});var e=[],f=b.call(c);return a.Observe&&(a.Observe.__reading=d),{value:f,observed:e}},c=function(c,d,e,f){var g,h={},i=!0,j={value:undefined,teardown:function(){for(var a in h){var b=h[a];b.observe.obj.unbind(b.observe.attr,k),delete h[a]}}},k=function(a){if(!(f&&!f.bound||a.batchNum!==undefined&&a.batchNum===g)){var b=j.value,c=l();j.value=c,c!==b&&e(c,b),g=g=a.batchNum}},l=function(){var e=b(c,d),f=e.observed,g=e.value;i=!i,a.each(f,function(a){h[a.obj._cid+"|"+a.attr]?h[a.obj._cid+"|"+a.attr].matched=i:(h[a.obj._cid+"|"+a.attr]={matched:i,observe:a},a.obj.bind(a.attr,k))});for(var j in h){var l=h[j];l.matched!==i&&(l.observe.obj.unbind(l.observe.attr,k),delete h[j])}return g};return j.value=l(),j.isListening=!a.isEmptyObject(h),j};return a.compute=function(d,e,f){if(d&&d.isComputed)return d;var g,h,i,j={bound:!1,hasDependencies:!1},k=function(){},l=function(){},m=function(){return i},n=function(a){i=a},o=!0;if(h=function(b){if(arguments.length){var c=i,d=n.call(e,b,c);return h.hasDependencies?m.call(e):(i=d===undefined?m.call(e):d,c!==i&&a.Observe.triggerBatch(h,"change",[i,c]),i)}return a.Observe.__reading&&o&&a.Observe.__reading(h,"change"),j.bound?i:m.call(e)},"function"==typeof d)n=d,m=d,o=f===!1?!1:!0,h.hasDependencies=!1,k=function(a){g=c(d,e||this,a,j),h.hasDependencies=g.isListening,i=g.value},l=function(){g.teardown()};else if(e)if("string"==typeof e){var p=e,q=d instanceof a.Observe;q&&(h.hasDependencies=!0),m=function(){return q?d.attr(p):d[p]},n=function(a){q?d.attr(p,a):d[p]=a};var r;k=function(c){r=function(){c(m(),i)},a.bind.call(d,f||p,r),i=b(m).value},l=function(){a.unbind.call(d,f||p,r)}}else if("function"==typeof e)i=d,n=e;else{i=d;var s=e;m=s.get||m,n=s.set||n,k=s.on||k,l=s.off||l}else i=d;h.isComputed=!0,a.cid(h,"compute");var t=function(b,c){i=b,a.Observe.triggerBatch(h,"change",[b,c])};return a.extend(h,{_bindsetup:function(){j.bound=!0,k.call(this,t)},_bindteardown:function(){l.call(this,t),j.bound=!1},bind:a.bindAndSetup,unbind:a.unbindAndTeardown})},a.compute.binder=c,a.compute}(__m3,__m8),__m10=function(a){var b=function(b,c,d){var e=new a.Deferred;return b.then(function(){var b=a.makeArray(arguments);b[0]=c[d](b[0]),e.resolveWith(e,b)},function(){e.rejectWith(this,arguments)}),"function"==typeof b.abort&&(e.abort=function(){return b.abort()}),e},c=0,d=function(b){return a.Observe.__reading&&a.Observe.__reading(b,b.constructor.id),b.__get(b.constructor.id)},e=function(b,c,d,e,f,g){var h={};if("string"==typeof b){var i=b.split(/\s+/);h.url=i.pop(),i.length&&(h.type=i.pop())}else a.extend(h,b);return h.data="object"!=typeof c||a.isArray(c)?c:a.extend(h.data||{},c),h.url=a.sub(h.url,h.data,!0),a.ajax(a.extend({type:d||"post",dataType:e||"json",success:f,error:g},h))},f=function(b,c,e,f,g){var h;a.isArray(b)?(h=b[1],b=b[0]):h=b.serialize(),h=[h];var i,j,k=b.constructor;return"destroy"==c&&h.shift(),"create"!==c&&h.unshift(d(b)),j=k[c].apply(k,h),i=j.pipe(function(a){return b[g||c+"d"](a,j),b}),j.abort&&(i.abort=function(){j.abort()}),i.then(e,f),i},g={create:{url:"_shortName",type:"post"},update:{data:function(b,c){c=c||{};var d=this.id;return c[d]&&c[d]!==b&&(c["new"+a.capitalize(b)]=c[d],delete c[d]),c[d]=b,c},type:"put"},destroy:{type:"delete",data:function(a){var b={};return b.id=b[this.id]=a,b}},findAll:{url:"_shortName"},findOne:{}},h=function(a,b){return function(c){return c=a.data?a.data.apply(this,arguments):c,e(b||this[a.url||"_url"],c,a.type||"get")}};a.Model=a.Observe({fullName:"can.Model",_reqs:0,setup:function(b){if(this.store={},a.Observe.setup.apply(this,arguments),a.Model){this.List=i({Observe:this},{});var d=this,e=a.proxy(this._clean,d);a.each(g,function(c,f){if(a.isFunction(d[f])||(d[f]=h(c,d[f])),d["make"+a.capitalize(f)]){var g=d["make"+a.capitalize(f)](d[f]);a.Construct._overwrite(d,b,f,function(){a.Model._reqs++;var b=g.apply(this,arguments),c=b.then(e,e);return c.abort=b.abort,c})}}),"can.Model"!=d.fullName&&d.fullName||(d.fullName="Model"+ ++c),a.Model._reqs=0,this._url=this._shortName+"/{"+this.id+"}"}},_ajax:h,_makeRequest:f,_clean:function(){if(a.Model._reqs--,!a.Model._reqs)for(var b in this.store)this.store[b]._bindings||delete this.store[b];return arguments[0]},models:function(b,c){if(a.Model._reqs++,b){if(b instanceof this.List)return b;var d=this,e=[],f=c instanceof a.Observe.List?c:new(d.List||i),g=a.isArray(b),h=b instanceof i,j=g?b:h?b.serialize():b.data;return f.length&&f.splice(0),a.each(j,function(a){e.push(d.model(a))}),f.push.apply(f,e),g||a.each(b,function(a,b){"data"!==b&&f.attr(b,a)}),setTimeout(a.proxy(this._clean,this),1),f}},model:function(b){if(b){b instanceof this&&(b=b.serialize());var c=b[this.id],d=(c||0===c)&&this.store[c]?this.store[c].attr(b,this.removeAttr||!1):new this(b);return a.Model._reqs&&(this.store[b[this.id]]=d),d}}},{isNew:function(){var a=d(this);return!(a||0===a)},save:function(a,b){return f(this,this.isNew()?"create":"update",a,b)},destroy:function(b,c){if(this.isNew()){var d=this,e=a.Deferred();return e.then(b,c),e.done(function(a){d.destroyed(a)}).resolve(d)}return f(this,"destroy",b,c,"destroyed")},_bindsetup:function(){return this.constructor.store[this.__get(this.constructor.id)]=this,a.Observe.prototype._bindsetup.apply(this,arguments)},_bindteardown:function(){return delete this.constructor.store[d(this)],a.Observe.prototype._bindteardown.apply(this,arguments)},___set:function(b,c){a.Observe.prototype.___set.call(this,b,c),b===this.constructor.id&&this._bindings&&(this.constructor.store[d(this)]=this)}}),a.each({makeFindAll:"models",makeFindOne:"model",makeCreate:"model",makeUpdate:"model"},function(c,d){a.Model[d]=function(d){return function(){var e=a.makeArray(arguments),f=a.isFunction(e[1])?e.splice(0,1):e.splice(0,2),g=b(d.apply(this,f),this,c);return g.then(e[0],e[1]),g}}}),a.each(["created","updated","destroyed"],function(b){a.Model.prototype[b]=function(c){var d,e=this.constructor;d=c&&"object"==typeof c&&this.attr(c.attr?c.attr():c),a.trigger(this,"change",b),a.trigger(e,b,this)}});var i=a.Model.List=a.Observe.List({setup:function(b){a.isPlainObject(b)&&!a.isArray(b)?(a.Observe.List.prototype.setup.apply(this),this.replace(this.constructor.Observe.findAll(b))):a.Observe.List.prototype.setup.apply(this,arguments)},_changes:function(b,c){if(a.Observe.List.prototype._changes.apply(this,arguments),/\w+\.destroyed/.test(c)){var d=this.indexOf(b.target);-1!=d&&this.splice(d,1)}}});return a.Model}(__m3,__m7),__m11=function(a){var b=a.isFunction,c=a.makeArray,d=1,e=a.view=a.template=function(c,d,f,g){b(f)&&(g=f,f=undefined);var h=function(a){return e.frag(a)},i=b(g)?function(a){g(h(a))}:null,j=e.render(c,d,f,i),k=a.Deferred();return b(j)?j:a.isDeferred(j)?(j.then(function(a,b){k.resolve.call(k,h(a),b)},function(){k.fail.apply(k,arguments)}),k):h(j)};a.extend(e,{frag:function(a,b){return e.hookup(e.fragment(a),b)},fragment:function(b){var c=a.buildFragment(b,document.body);return c.childNodes.length||c.appendChild(document.createTextNode("")),c},toId:function(b){return a.map(b.toString().split(/\/|\./g),function(a){return a?a:void 0}).join("_")},hookup:function(b,c){var d,f,g=[];return a.each(b.childNodes?a.makeArray(b.childNodes):b,function(b){1===b.nodeType&&(g.push(b),g.push.apply(g,a.makeArray(b.getElementsByTagName("*"))))}),a.each(g,function(a){a.getAttribute&&(d=a.getAttribute("data-view-id"))&&(f=e.hookups[d])&&(f(a,c,d),delete e.hookups[d],a.removeAttribute("data-view-id"))}),b},hookups:{},hook:function(a){return e.hookups[++d]=a," data-view-id='"+d+"'"},cached:{},cachedRenderers:{},cache:!0,register:function(a){this.types["."+a.suffix]=a},types:{},ext:".ejs",registerScript:function(){},preload:function(){},render:function(d,f,j,k){b(j)&&(k=j,j=undefined);var l=h(f);if(l.length){var m=new a.Deferred,n=a.extend({},f);return l.push(g(d,!0)),a.when.apply(a,l).then(function(b){var d,e=c(arguments),g=e.pop();if(a.isDeferred(f))n=i(b);else for(var h in f)a.isDeferred(f[h])&&(n[h]=i(e.shift()));d=g(n,j),m.resolve(d,n),k&&k(d,n)},function(){m.reject.apply(m,arguments)}),m}var o,p=b(k),m=g(d,p);if(p)o=m,m.then(function(a){k(f?a(f,j):a)});else{if("resolved"===m.state()&&m.__view_id){var q=e.cachedRenderers[m.__view_id];return f?q(f,j):q}m.then(function(a){o=f?a(f,j):a})}return o},registerView:function(b,c,d,f){var g=(d||e.types[e.ext]).renderer(b,c);return f=f||new a.Deferred,e.cache&&(e.cached[b]=f,f.__view_id=b,e.cachedRenderers[b]=g),f.resolve(g)}});var f=function(a,b){if(!a.length)throw"can.view: No template or empty template:"+b},g=function(b,c){var d,g,h,i=b.match(/\.[\w\d]+$/);if(b.match(/^#/)&&(b=b.substr(1)),(g=document.getElementById(b))&&(i="."+g.type.match(/\/(x\-)?(.+)/)[2]),i||e.cached[b]||(b+=i=e.ext),a.isArray(i)&&(i=i[0]),h=e.toId(b),b.match(/^\/\//)){var j=b.substr(2);b=window.steal?steal.config().root.mapJoin(""+steal.id(j)):j}if(d=e.types[i],e.cached[h])return e.cached[h];if(g)return e.registerView(h,g.innerHTML,d);var k=new a.Deferred;return a.ajax({async:c,url:b,dataType:"text",error:function(a){f("",b),k.reject(a)},success:function(a){f(a,b),e.registerView(h,a,d,k)}}),k},h=function(b){var c=[];if(a.isDeferred(b))return[b];for(var d in b)a.isDeferred(b[d])&&c.push(b[d]);return c},i=function(b){return a.isArray(b)&&"success"===b[1]?b[0]:b};return window.steal&&steal.type("view js",function(a,b){var c=e.types["."+a.type],d=e.toId(a.id);a.text="steal('"+(c.plugin||"can/view/"+a.type)+"',function(can){return "+"can.view.preload('"+d+"',"+a.text+");\n})",b()}),a.extend(e,{register:function(b){this.types["."+b.suffix]=b,window.steal&&steal.type(b.suffix+" view js",function(a,b){var c=e.types["."+a.type],d=e.toId(a.id+"");a.text=c.script(d,a.text),b()}),e[b.suffix]=function(c,d){if(!d){var f=function(){return e.frag(f.render.apply(this,arguments))};return f.render=function(){var a=b.renderer(null,c);return a.apply(a,arguments)},f}return e.preload(c,b.renderer(c,d)),a.view(c)}},registerScript:function(a,b,c){return"can.view.preload('"+b+"',"+e.types["."+a].script(b,c)+");"},preload:function(b,c){function d(){return e.frag(c.apply(this,arguments))}return e.cached[b]=(new a.Deferred).resolve(function(a,b){return c.call(a,a,b)}),d.render=c,d}}),a}(__m3),__m14=function(){var a={tagToContentPropMap:{option:"textContent"in document.createElement("option")?"textContent":"innerText",textarea:"value"},attrMap:{"class":"className",value:"value",innerText:"innerText",textContent:"textContent",checked:!0,disabled:!0,readonly:!0,required:!0},defaultValue:["input","textarea"],tagMap:{"":"span",table:"tbody",tr:"td",ol:"li",ul:"li",tbody:"tr",thead:"tr",tfoot:"tr",select:"option",optgroup:"option"},reverseTagMap:{tr:"tbody",option:"select",td:"tr",th:"tr",li:"ul"},getParentNode:function(a,b){return b&&11===a.parentNode.nodeType?b:a.parentNode},setAttr:function(b,c,d){var e=b.nodeName.toString().toLowerCase(),f=a.attrMap[c];f===!0?b[c]=!0:f?(b[f]=d,"value"===f&&can.inArray(e,a.defaultValue)>=0&&(b.defaultValue=d)):b.setAttribute(c,d)},getAttr:function(b,c){return(a.attrMap[c]&&b[a.attrMap[c]]?b[a.attrMap[c]]:b.getAttribute(c))||""},removeAttr:function(b,c){a.attrMap[c]===!0?b[c]=!1:b.removeAttribute(c)},contentText:function(a){return"string"==typeof a?a:a||0===a?""+a:""}};return a}(),__m13=function(can,elements){var newLine=/(\r|\n)+/g,clean=function(a){return a.split("\\").join("\\\\").split("\n").join("\\n").split('"').join('\\"').split(" ").join("\\t")},getTag=function(a,b,c){if(a)return a;for(;c<b.length;){if("<"==b[c]&&elements.reverseTagMap[b[c+1]])return elements.reverseTagMap[b[c+1]];c++}return""},bracketNum=function(a){return--a.split("{").length- --a.split("}").length},myEval=function(script){eval(script)},attrReg=/([^\s]+)[\s]*=[\s]*$/,startTxt="var ___v1ew = [];",finishTxt="return ___v1ew.join('')",put_cmd="___v1ew.push(",insert_cmd=put_cmd,htmlTag=null,quote=null,beforeQuote=null,rescan=null,status=function(){return quote?"'"+beforeQuote.match(attrReg)[1]+"'":htmlTag?1:0};return can.view.Scanner=Scanner=function(a){can.extend(this,{text:{},tokens:[]},a),this.tokenReg=[],this.tokenSimple={"<":"<",">":">",'"':'"',"'":"'"},this.tokenComplex=[],this.tokenMap={};for(var b,c=0;b=this.tokens[c];c++)b[2]?(this.tokenReg.push(b[2]),this.tokenComplex.push({abbr:b[1],re:new RegExp(b[2]),rescan:b[3]})):(this.tokenReg.push(b[1]),this.tokenSimple[b[1]]=b[0]),this.tokenMap[b[0]]=b[1];this.tokenReg=new RegExp("("+this.tokenReg.slice(0).concat(["<",">",'"',"'"]).join("|")+")","g")},Scanner.prototype={helpers:[{name:/\s*\(([\$\w]+)\)\s*->([^\n]*)/,fn:function(a){var b=/\s*\(([\$\w]+)\)\s*->([^\n]*)/,c=a.match(b);return"can.proxy(function(__){var "+c[1]+"=can.$(__);"+c[2]+"}, this);"}}],scan:function(a,b){var c=[],d=0,e=this.tokenSimple,f=this.tokenComplex;a=a.replace(newLine,"\n"),this.transform&&(a=this.transform(a)),a.replace(this.tokenReg,function(b,g){var h=arguments[arguments.length-2];if(h>d&&c.push(a.substring(d,h)),e[b])c.push(b);else for(var i,j=0;i=f[j];j++)if(i.re.test(b)){c.push(i.abbr),i.rescan&&c.push(i.rescan(g));break}d=h+g.length}),d<a.length&&c.push(a.substr(d));var g,h,i,j="",k=[startTxt+(this.text.start||"")],l=function(a,b){k.push(put_cmd,'"',clean(a),'"'+(b||"")+");")},m=[],n=null,o=!1,p="",q=[],r=!1,s=0,t=this.tokenMap;for(htmlTag=quote=beforeQuote=null;(i=c[s++])!==undefined;){if(null===n)switch(i){case t.left:case t.escapeLeft:case t.returnLeft:o=htmlTag&&1;case t.commentLeft:n=i,j.length&&l(j),j="";break;case t.escapeFull:o=htmlTag&&1,rescan=1,n=t.escapeLeft,j.length&&l(j),rescan=c[s++],j=rescan.content||rescan,rescan.before&&l(rescan.before),c.splice(s,0,t.right);break;case t.commentFull:break;case t.templateLeft:j+=t.left;break;case"<":0!==c[s].indexOf("!--")&&(htmlTag=1,o=0),j+=i;break;case">":htmlTag=0;var u="/"==j.substr(j.length-1)||"--"==j.substr(j.length-2);o||!r&&elements.tagToContentPropMap[q[q.length-1]]?(u?l(j.substr(0,j.length-1),',can.view.pending(),"/>"'):l(j,',can.view.pending(),">"'),j="",o=0):j+=i,(u||r)&&(q.pop(),p=q[q.length-1],r=!1);break;case"'":case'"':htmlTag&&(quote&"e===i?quote=null:null===quote&&(quote=i,beforeQuote=g));default:"<"===g&&(p=i.split(/\s/)[0],0===p.indexOf("/")&&q[q.length-1]===p.substr(1)?(p=q[q.length-1],r=!0):q.push(p)),j+=i}else switch(i){case t.right:case t.returnRight:switch(n){case t.left:h=bracketNum(j),1==h?(k.push(insert_cmd,"can.view.txt(0,'"+getTag(p,c,s)+"',"+status()+",this,function(){",startTxt,j),m.push({before:"",after:finishTxt+"}));\n"})):(d=m.length&&-1==h?m.pop():{after:";"},d.before&&k.push(d.before),k.push(j,";",d.after));break;case t.escapeLeft:case t.returnLeft:h=bracketNum(j),h&&m.push({before:finishTxt,after:"}));"});for(var v=n===t.escapeLeft?1:0,w={insert:insert_cmd,tagName:getTag(p,c,s),status:status()},x=0;x<this.helpers.length;x++){var y=this.helpers[x];if(y.name.test(j)){j=y.fn(j,w),y.name.source==/^>[\s]*\w*/.source&&(v=0);break}}"object"==typeof j?j.raw&&k.push(j.raw):k.push(insert_cmd,"can.view.txt("+v+",'"+p+"',"+status()+",this,function(){ "+(this.text.escape||"")+"return ",j,h?startTxt:"}));"),rescan&&rescan.after&&rescan.after.length&&(l(rescan.after.length),rescan=null)}n=null,j="";break;case t.templateLeft:j+=t.left;break;default:j+=i}g=i}j.length&&l(j),k.push(";");var z=k.join(""),A={out:"with(_VIEW) { with (_CONTEXT) {"+z+" "+finishTxt+"}}"};return myEval.call(A,"this.fn = (function(_CONTEXT,_VIEW){"+A.out+"});\r\n//@ sourceURL="+b+".js"),A}},Scanner}(__m11,__m14),__m17=function(a){var b=!0;try{document.createTextNode("")._=0}catch(c){b=!1}var d={},e={},f={},g="ejs_"+Math.random(),h=0,i=function(a){if(b||3!==a.nodeType)return a[g]?a[g]:a[g]=(a.nodeName?"element_":"obj_")+ ++h;for(var c in e)if(e[c]===a)return c;return e["text_"+ ++h]=a,"text_"+h},j=function(b,c){var e=d[i(b)];if(e){var f=a.inArray(c,e);f>=0&&e.splice(f,1),e.length||delete d[i(b)]}},k=function(a,b){var c=d[i(a)];c||(c=d[i(a)]=[]),c.push(b)},l={id:i,replace:function(b,c){b=a.makeArray(b);var e=b[0];a.each(a.makeArray(d[i(e)]),function(d){var g=f[d],h=a.inArray(e,g),i=a.inArray(b[b.length-1],g);if(h>=0&&i>=0){for(var m=h;i>=m;m++){var n=g[m];j(n,d)}g.splice.apply(g,[h,i-h+1].concat(c)),a.each(c,function(a){k(a,d)})}else l.unregister(g)})},register:function(b){var c=i(b);f[c]=b,a.each(b,function(a){k(a,c)})},unregister:function(b){var c=i(b);a.each(b,function(a){j(a,c)}),delete f[c]},nodeMap:d,nodeListMap:f};return l}(__m3),__m16=function(a,b,c,d){var e=function(b,c,d){var e=function(){d(f),a.unbind.call(b,"destroyed",e)},f={teardownCheck:function(a){a||e()}};return a.bind.call(b,"destroyed",e),c(f),f},f=function(a,b,c){return e(a,function(){b.bind("change",c)},function(a){b.unbind("change",c),a.nodeList&&d.unregister(a.nodeList)})},g=function(a){return(a||"").replace(/['"]/g,"").split("=")};insertElementsAfter=function(a,b){var c=a[a.length-1];c.nextSibling?c.parentNode.insertBefore(b,c.nextSibling):c.parentNode.appendChild(b)};var h={nodeLists:d,list:function(c,f,g,h,i){var j=[],k=function(b,c,e){var f=document.createDocumentFragment(),k=[];if(a.each(c,function(b){var c=g.call(h,b),d=a.view.frag(c,i);k.push(a.makeArray(d.childNodes)),f.appendChild(d)}),j[e]){var l=j[e][0];l.parentNode.insertBefore(f,l)}else insertElementsAfter(0==e?[m]:j[e-1],f);a.each(k,function(a){d.register(a)}),[].splice.apply(j,[e,0].concat(k))},l=function(b,c,e){var f=j.splice(e,c.length),g=[];a.each(f,function(a){[].push.apply(g,a),d.replace(a,[]),d.unregister(a)}),a.remove(a.$(g))},i=b.getParentNode(c,i),m=document.createTextNode("");e(i,function(){f.bind("add",k).bind("remove",l)},function(){f.unbind("add",k).unbind("remove",l),a.each(j,function(a){d.unregister(a)})}),insertElementsAfter([c],m),a.remove(a.$(c)),k({},f,0)},html:function(c,e,g){var h,g=b.getParentNode(c,g),i=f(g,e,function(a,b){var c=h[0].parentNode;c&&j(b),i.teardownCheck(h[0].parentNode)}),j=function(b){var e=a.view.frag(b,g),f=a.makeArray(e.childNodes);if(insertElementsAfter(h||[c],e),h){var j=a.makeArray(h);d.replace(h,f),a.remove(a.$(j))}else a.remove(a.$(c)),h=f,i.nodeList=h,d.register(h)};j(e(),[c])},text:function(a,c,d){var e=b.getParentNode(a,d),g=f(a.parentNode!==e?a.parentNode:e,c,function(a,b){"unknown"!=typeof h.nodeValue&&(h.nodeValue=""+b),g.teardownCheck(h.parentNode)}),h=document.createTextNode(c());a.parentNode!==e?(e=a.parentNode,e.insertBefore(h,a),e.removeChild(a)):(e.insertBefore(h,a),e.removeChild(a))},attributes:function(a,c,d){var e=function(c){var d=g(c),e=d.shift();e!=h&&h&&b.removeAttr(a,h),e&&(b.setAttr(a,e,d.join("=")),h=e)};if(f(a,c,function(a,b){e(b)}),arguments.length>=3)var h=g(d)[0];else e(c())},attributePlaceholder:"__!!__",attributeReplace:/__!!__/g,attribute:function(c,d,e){f(c,e,function(){b.setAttr(c,d,j.render())});var g,i=a.$(c);g=a.data(i,"hooks"),g||a.data(i,"hooks",g={});var j,k=b.getAttr(c,d),l=k.split(h.attributePlaceholder),m=[];m.push(l.shift(),l.join(h.attributePlaceholder)),g[d]?g[d].computes.push(e):g[d]={render:function(){var a=0,c=k?k.replace(h.attributeReplace,function(){return b.contentText(j.computes[a++]())}):b.contentText(j.computes[a++]());return c},computes:[e],batchNum:undefined},j=g[d],m.splice(1,0,e()),b.setAttr(c,d,m.join(""))}};return h}(__m3,__m14,__m11,__m17),__m15=function(a,b,c){var d=[],e=function(a){var c=b.tagMap[a]||"span";return"span"===c?"@@!!@@":"<"+c+">"+e(c)+"</"+c+">"},f=function(b,c){if("string"==typeof b)return b;if(!b&&0!==b)return"";var e=b.hookup&&function(a,c){b.hookup.call(b,a,c)}||"function"==typeof b&&b;return e?c?"<"+c+" "+a.view.hook(e)+"></"+c+">":(d.push(e),""):""+b},g=function(b){return"string"==typeof b||"number"==typeof b?a.esc(b):f(b)};return a.extend(a.view,{live:c,setupLists:function(){var b,c=a.view.lists;return a.view.lists=function(a,c){b={list:a,renderer:c}},function(){return a.view.lists=c,b}},pending:function(){var b=d.slice(0);return lastHookups=b,d=[],a.view.hook(function(c){a.each(b,function(a){a(c)})})},txt:function(h,i,j,k,l){var m=a.view.setupLists(),n=function(){},o=function(){p.unbind("change",n)},p=a.compute(l,k,!1);p.bind("change",n);var q=b.tagMap[i]||"span",r=m(),s=p();if(r)return"<"+q+a.view.hook(function(a,b){c.list(a,r.list,r.renderer,k,b)})+"></"+q+">";if(!p.hasDependencies)return o(),(h||0!==j?g:f)(s,0===j&&q);var t=b.tagToContentPropMap[i];if(0!==j||t){if(1===j)return d.push(function(a){c.attributes(a,p,p()),o()}),p();var u=0===j?t:j;return(0===j?lastHookups:d).push(function(a){c.attribute(a,u,p),o()
-}),c.attributePlaceholder}return"<"+q+a.view.hook(h?function(a,b){c.text(a,p,b),o()}:function(a,b){c.html(a,p,b),o()})+">"+e(q)+"</"+q+">"}}),a}(__m11,__m14,__m16,__m2),__m12=function(a){var b=a.extend,c=function(a){if(this.constructor!=c){var d=new c(a);return function(a,b){return d.render(a,b)}}return"function"==typeof a?(this.template={fn:a},void 0):(b(this,a),this.template=this.scanner.scan(this.text,this.name),void 0)};return a.EJS=c,c.prototype.render=function(a,b){return a=a||{},this.template.fn.call(a,a,new c.Helpers(a,b||{}))},b(c.prototype,{scanner:new a.view.Scanner({tokens:[["templateLeft","<%%"],["templateRight","%>"],["returnLeft","<%=="],["escapeLeft","<%="],["commentLeft","<%#"],["left","<%"],["right","%>"],["returnRight","%>"]],transform:function(a){return a.replace(/<%([\s\S]+?)%>/gm,function(a,b){var c,d,e=[];b.replace(/[{}]/gm,function(a,b){e.push([a,b])});do for(c=!1,d=e.length-2;d>=0;d--)if("{"==e[d][0]&&"}"==e[d+1][0]){e.splice(d,2),c=!0;break}while(c);if(e.length>=2){var f,g=["<%"],h=0;for(d=0;f=e[d];d++)g.push(b.substring(h,h=f[1])),"{"==f[0]&&d<e.length-1||"}"==f[0]&&d>0?g.push("{"==f[0]?"{ %><% ":" %><% }"):g.push(f[0]),++h;return g.push(b.substring(h),"%>"),g.join("")}return"<%"+b+"%>"})}})}),c.Helpers=function(a,c){this._data=a,this._extras=c,b(this,c)},c.Helpers.prototype={list:function(b,c){a.each(b,function(a,d){c(a,d,b)})},each:function(b,c){a.isArray(b)?this.list(b,c):a.view.lists(b,c)}},a.view.register({suffix:"ejs",script:function(a,b){return"can.EJS(function(_CONTEXT,_VIEW) { "+new c({text:b,name:a}).template.out+" })"},renderer:function(a,b){return c({text:b,name:a})}}),a}(__m3,__m11,__m2,__m9,__m13,__m15),__m18=function(a){var b,c=function(b,c,d){return a.bind.call(b,c,d),function(){a.unbind.call(b,c,d)}},d=a.isFunction,e=a.extend,f=a.each,g=[].slice,h=/\{([^\}]+)\}/g,i=a.getObject("$.event.special",[a])||{},j=function(b,c,d,e){return a.delegate.call(b,c,d,e),function(){a.undelegate.call(b,c,d,e)}},k=function(b,d,e,f){return f?j(b,a.trim(f),d,e):c(b,d,e)},l=a.Control=a.Construct({setup:function(){if(a.Construct.setup.apply(this,arguments),a.Control){var b,c=this;c.actions={};for(b in c.prototype)c._isAction(b)&&(c.actions[b]=c._action(b))}},_shifter:function(b,c){var e="string"==typeof c?b[c]:c;return d(e)||(e=b[e]),function(){return b.called=c,e.apply(b,[this.nodeName?a.$(this):this].concat(g.call(arguments,0)))}},_isAction:function(a){var b=this.prototype[a],c=typeof b;return"constructor"!==a&&("function"==c||"string"==c&&d(this.prototype[b]))&&!!(i[a]||m[a]||/[^\w]/.test(a))},_action:function(c,d){if(h.lastIndex=0,d||!h.test(c)){var e=d?a.sub(c,[d,window]):c;if(!e)return null;var f=a.isArray(e),g=f?e[1]:e,i=g.split(/\s+/g),j=i.pop();return{processor:m[j]||b,parts:[g,i.join(" "),j],delegate:f?e[0]:undefined}}},processors:{},defaults:{}},{setup:function(b,c){var d,f=this.constructor,g=f.pluginName||f._fullName;return this.element=a.$(b),g&&"can_control"!==g&&this.element.addClass(g),(d=a.data(this.element,"controls"))||a.data(this.element,"controls",d=[]),d.push(this),this.options=e({},f.defaults,c),this.on(),[this.element,this.options]},on:function(b,c,d,e){if(!b){this.off();var f,g,h=this.constructor,i=this._bindings,j=h.actions,l=this.element,m=a.Control._shifter(this,"destroy");for(f in j)j.hasOwnProperty(f)&&(g=j[f]||h._action(f,this.options))&&i.push(g.processor(g.delegate||l,g.parts[2],g.parts[1],f,this));return a.bind.call(l,"destroyed",m),i.push(function(b){a.unbind.call(b,"destroyed",m)}),i.length}return"string"==typeof b&&(e=d,d=c,c=b,b=this.element),e===undefined&&(e=d,d=c,c=null),"string"==typeof e&&(e=a.Control._shifter(this,e)),this._bindings.push(k(b,d,e,c)),this._bindings.length},off:function(){var a=this.element[0];f(this._bindings||[],function(b){b(a)}),this._bindings=[]},destroy:function(){if(null!==this.element){var b,c=this.constructor,d=c.pluginName||c._fullName;this.off(),d&&"can_control"!==d&&this.element.removeClass(d),b=a.data(this.element,"controls"),b.splice(a.inArray(this,b),1),a.trigger(this,"destroyed"),this.element=null}}}),m=a.Control.processors,b=function(b,c,d,e,f){return k(b,c,a.Control._shifter(f,e),d)};return f(["change","click","contextmenu","dblclick","keydown","keyup","keypress","mousedown","mousemove","mouseout","mouseover","mouseup","reset","resize","scroll","select","submit","focusin","focusout","mouseenter","mouseleave","touchstart","touchmove","touchcancel","touchend","touchleave"],function(a){m[a]=b}),l}(__m3,__m1),__m20=function(a){var b=/^\d+$/,c=/([^\[\]]+)|(\[\])/g,d=/([^?#]*)(#.*)?$/,e=function(a){return decodeURIComponent(a.replace(/\+/g," "))};return a.extend(a,{deparam:function(f){var g,h,i={};return f&&d.test(f)&&(g=f.split("&"),a.each(g,function(a){var d=a.split("="),f=e(d.shift()),g=e(d.join("=")),j=i;if(f){d=f.match(c);for(var k=0,l=d.length-1;l>k;k++)j[d[k]]||(j[d[k]]=b.test(d[k+1])||"[]"==d[k+1]?[]:{}),j=j[d[k]];h=d.pop(),"[]"==h?j.push(g):j[h]=g}})),i}}),a}(__m3,__m2),__m19=function(a){var b=/\:([\w\.]+)/g,c=/^(?:&[^=]+=[^&]*)+/,d=function(b){var c=[];return a.each(b,function(b,d){c.push(("className"===d?"class":d)+'="'+("href"===d?b:a.esc(b))+'"')}),c.join(" ")},e=function(a,b){var c=0,d=0,e={};for(var f in a.defaults)a.defaults[f]===b[f]&&(e[f]=1,c++);for(;d<a.names.length;d++){if(!b.hasOwnProperty(a.names[d]))return-1;e[a.names[d]]||c++}return c},f=!0,g=window.location,h=function(a){return(a+"").replace(/([.?*+\^$\[\]\\(){}|\-])/g,"\\$1")},i=a.each,j=a.extend;a.route=function(c,d){d=d||{};var e=[],f=c.replace(b,function(b,f,g){e.push(f);var h="\\"+(c.substr(g+b.length,1)||a.route._querySeparator);return"([^"+h+"]"+(d[f]?"*":"+")+")"});return a.route.routes[c]={test:new RegExp("^"+f+"($|"+h(a.route._querySeparator)+")"),route:c,names:e,defaults:d,length:c.split("/").length},a.route},j(a.route,{_querySeparator:"&",_paramsMatcher:c,param:function(c,d){var f,g,h=0,k=c.route,l=0;if(delete c.route,i(c,function(){l++}),i(a.route.routes,function(a){return g=e(a,c),g>h&&(f=a,h=g),g>=l?!1:void 0}),a.route.routes[k]&&e(a.route.routes[k],c)===h&&(f=a.route.routes[k]),f){var m,n=j({},c),o=f.route.replace(b,function(a,b){return delete n[b],c[b]===f.defaults[b]?"":encodeURIComponent(c[b])});return i(f.defaults,function(a,b){n[b]===a&&delete n[b]}),m=a.param(n),d&&a.route.attr("route",f.route),o+(m?a.route._querySeparator+m:"")}return a.isEmptyObject(c)?"":a.route._querySeparator+a.param(c)},deparam:function(b){var c={length:-1};if(i(a.route.routes,function(a){a.test.test(b)&&a.length>c.length&&(c=a)}),c.length>-1){var d=b.match(c.test),e=d.shift(),f=b.substr(e.length-(d[d.length-1]===a.route._querySeparator?1:0)),g=f&&a.route._paramsMatcher.test(f)?a.deparam(f.slice(1)):{};return g=j(!0,{},c.defaults,g),i(d,function(b,d){b&&b!==a.route._querySeparator&&(g[c.names[d]]=decodeURIComponent(b))}),g.route=c.route,g}return b.charAt(0)!==a.route._querySeparator&&(b=a.route._querySeparator+b),a.route._paramsMatcher.test(b)?a.deparam(b.slice(1)):{}},data:new a.Observe({}),routes:{},ready:function(b){return b===!1&&(f=b),(b===!0||f===!0)&&(a.route._setup(),o()),a.route},url:function(b,c){return c&&(b=j({},l,b)),"#!"+a.route.param(b)},link:function(b,c,e,f){return"<a "+d(j({href:a.route.url(c,f)},e))+">"+b+"</a>"},current:function(b){return g.hash=="#!"+a.route.param(b)},_setup:function(){a.bind.call(window,"hashchange",o)},_getHash:function(){return g.href.split(/#!?/)[1]||""},_setHash:function(b){var c=a.route.param(b,!0);return g.hash="#!"+c,c}}),i(["bind","unbind","delegate","undelegate","attr","removeAttr"],function(b){a.route[b]=function(){return a.route.data[b]?a.route.data[b].apply(a.route.data,arguments):void 0}});var k,l,m,n,o=a.route.setState=function(){var b=a.route._getHash();l=a.route.deparam(b),n&&b===m||a.route.attr(l,!0)};return a.route.bind("change",function(){n=1,clearTimeout(k),k=setTimeout(function(){n=0;var b=a.route.data.serialize();m=a.route._setHash(b)},1)}),a.bind.call(document,"ready",a.route.ready),"complete"!==document.readyState&&"interactive"!==document.readyState||!f||a.route.ready(),a.route.constructor.canMakeObserve=a.Observe.canMakeObserve,a.route}(__m3,__m7,__m20),__m21=function(a){return a.Control.processors.route=function(b,c,d,e,f){d=d||"",a.route(d);var g,h=function(b){if(a.route.attr("route")===d&&(b.batchNum===undefined||b.batchNum!==g)){g=b.batchNum;var c=a.route.attr();delete c.route,a.isFunction(f[e])?f[e](c):f[f[e]](c)}};return a.route.bind("change",h),function(){a.route.unbind("change",h)}},a}(__m3,__m19,__m18);window.can=__m5}();
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.object.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.object.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.object.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,137 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:29 GMT
- * Licensed MIT
- * Includes: can/util/object
- * Download from: http://canjs.com
- */
-(function(can) {
-
- var isArray = can.isArray,
- // essentially returns an object that has all the must have comparisons ...
- // must haves, do not return true when provided undefined
- cleanSet = function(obj, compares) {
- var copy = can.extend({}, obj);
- for (var prop in copy) {
- var compare = compares[prop] === undefined ? compares["*"] : compares[prop];
- if (same(copy[prop], undefined, compare)) {
- delete copy[prop]
- }
- }
- return copy;
- },
- propCount = function(obj) {
- var count = 0;
- for (var prop in obj) count++;
- return count;
- };
-
- can.Object = {};
-
- var same = can.Object.same = function(a, b, compares, aParent, bParent, deep) {
- var aType = typeof a,
- aArray = isArray(a),
- comparesType = typeof compares,
- compare;
-
- if (comparesType == 'string' || compares === null) {
- compares = compareMethods[compares];
- comparesType = 'function'
- }
- if (comparesType == 'function') {
- return compares(a, b, aParent, bParent)
- }
- compares = compares || {};
-
- if (a instanceof Date) {
- return a === b;
- }
- if (deep === -1) {
- return aType === 'object' || a === b;
- }
- if (aType !== typeof b || aArray !== isArray(b)) {
- return false;
- }
- if (a === b) {
- return true;
- }
- if (aArray) {
- if (a.length !== b.length) {
- return false;
- }
- for (var i = 0; i < a.length; i++) {
- compare = compares[i] === undefined ? compares["*"] : compares[i]
- if (!same(a[i], b[i], a, b, compare)) {
- return false;
- }
- };
- return true;
- } else if (aType === "object" || aType === 'function') {
- var bCopy = can.extend({}, b);
- for (var prop in a) {
- compare = compares[prop] === undefined ? compares["*"] : compares[prop];
- if (!same(a[prop], b[prop], compare, a, b, deep === false ? -1 : undefined)) {
- return false;
- }
- delete bCopy[prop];
- }
- // go through bCopy props ... if there is no compare .. return false
- for (prop in bCopy) {
- if (compares[prop] === undefined || !same(undefined, b[prop], compares[prop], a, b, deep === false ? -1 : undefined)) {
- return false;
- }
- }
- return true;
- }
- return false;
- };
-
- can.Object.subsets = function(checkSet, sets, compares) {
- var len = sets.length,
- subsets = [],
- checkPropCount = propCount(checkSet),
- setLength;
-
- for (var i = 0; i < len; i++) {
- //check this subset
- var set = sets[i];
- if (can.Object.subset(checkSet, set, compares)) {
- subsets.push(set)
- }
- }
- return subsets;
- };
-
- can.Object.subset = function(subset, set, compares) {
- // go through set {type: 'folder'} and make sure every property
- // is in subset {type: 'folder', parentId :5}
- // then make sure that set has fewer properties
- // make sure we are only checking 'important' properties
- // in subset (ones that have to have a value)
-
- var setPropCount = 0,
- compares = compares || {};
-
- for (var prop in set) {
-
- if (!same(subset[prop], set[prop], compares[prop], subset, set)) {
- return false;
- }
- }
- return true;
- }
-
- var compareMethods = {
- "null": function() {
- return true;
- },
- i: function(a, b) {
- return ("" + a).toLowerCase() == ("" + b).toLowerCase()
- }
- }
-
- return can.Object;
-
- })(can);
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.attributes.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.attributes.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.attributes.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,174 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:29 GMT
- * Licensed MIT
- * Includes: can/observe/attributes
- * Download from: http://canjs.com
- */
-(function(can, Observe) {
-
- can.each([can.Observe, can.Model], function(clss) {
- // in some cases model might not be defined quite yet.
- if (clss === undefined) {
- return;
- }
- var isObject = function(obj) {
- return typeof obj === 'object' && obj !== null && obj;
- };
-
- can.extend(clss, {
-
- attributes: {},
-
-
- convert: {
- "date": function(str) {
- var type = typeof str;
- if (type === "string") {
- return isNaN(Date.parse(str)) ? null : Date.parse(str)
- } else if (type === 'number') {
- return new Date(str)
- } else {
- return str
- }
- },
- "number": function(val) {
- return parseFloat(val);
- },
- "boolean": function(val) {
- if (val === 'false' || val === '0' || !val) {
- return false;
- }
- return true;
- },
- "default": function(val, oldVal, error, type) {
- var construct = can.getObject(type),
- context = window,
- realType;
- // if type has a . we need to look it up
- if (type.indexOf(".") >= 0) {
- // get everything before the last .
- realType = type.substring(0, type.lastIndexOf("."));
- // get the object before the last .
- context = can.getObject(realType);
- }
- return typeof construct == "function" ? construct.call(context, val, oldVal) : val;
- }
- },
-
- serialize: {
- "default": function(val, type) {
- return isObject(val) && val.serialize ? val.serialize() : val;
- },
- "date": function(val) {
- return val && val.getTime()
- }
- }
- });
-
- // overwrite setup to do this stuff
- var oldSetup = clss.setup;
-
-
- clss.setup = function(superClass, stat, proto) {
- var self = this;
- oldSetup.call(self, superClass, stat, proto);
-
- can.each(["attributes"], function(name) {
- if (!self[name] || superClass[name] === self[name]) {
- self[name] = {};
- }
- });
-
- can.each(["convert", "serialize"], function(name) {
- if (superClass[name] != self[name]) {
- self[name] = can.extend({}, superClass[name], self[name]);
- }
- });
- };
- });
-
- var oldSetup = can.Observe.prototype.setup;
-
- can.Observe.prototype.setup = function(obj) {
-
- var diff = {};
-
- oldSetup.call(this, obj);
-
- can.each(this.constructor.defaults, function(value, key) {
- if (!this.hasOwnProperty(key)) {
- diff[key] = value;
- }
- }, this);
-
- this._init = 1;
- this.attr(diff);
- delete this._init;
- };
-
- can.Observe.prototype.__convert = function(prop, value) {
- // check if there is a
-
- var Class = this.constructor,
- oldVal = this.attr(prop),
- type, converter;
-
- if (Class.attributes) {
- // the type of the attribute
- type = Class.attributes[prop];
- converter = Class.convert[type] || Class.convert['default'];
- }
-
- return value === null || !type ?
- // just use the value
- value :
- // otherwise, pass to the converter
- converter.call(Class, value, oldVal, function() {}, type);
- };
-
- can.Observe.prototype.serialize = function(attrName, stack) {
- var where = {},
- Class = this.constructor,
- attrs = {};
-
- stack = can.isArray(stack) ? stack : [];
- stack.push(this._cid);
-
- if (attrName !== undefined) {
- attrs[attrName] = this[attrName];
- } else {
- attrs = this.__get();
- }
-
- can.each(attrs, function(val, name) {
- var type, converter;
-
- // If this is an observe, check that it wasn't serialized earlier in the stack.
- if (val instanceof can.Observe && can.inArray(val._cid, stack) > -1) {
- // Since this object has already been serialized once,
- // just reference the id (or undefined if it doesn't exist).
- where[name] = val.attr('id');
- } else {
- type = Class.attributes ? Class.attributes[name] : 0;
- converter = Class.serialize ? Class.serialize[type] : 0;
-
- // if the value is an object, and has a attrs or serialize function
- where[name] = val && typeof val.serialize == 'function' ?
- // call attrs or serialize to get the original data back
- val.serialize(undefined, stack) :
- // otherwise if we have a converter
- converter ?
- // use the converter
- converter(val, type) :
- // or return the val
- val;
- }
- });
-
- return attrName != undefined ? where[attrName] : where;
- };
- return can.Observe;
- })(can);
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.delegate.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.delegate.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/can.observe.delegate.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,215 +0,0 @@
-/*!
- * CanJS - 1.1.6
- * http://canjs.us/
- * Copyright (c) 2013 Bitovi
- * Wed, 29 May 2013 18:59:29 GMT
- * Licensed MIT
- * Includes: can/observe/delegate
- * Download from: http://canjs.com
- */
-(function(can) {
-
-
-
- // ** - 'this' will be the deepest item changed
- // * - 'this' will be any changes within *, but * will be the
- // this returned
-
- // tells if the parts part of a delegate matches the broken up props of the event
- // gives the prop to use as 'this'
- // - parts - the attribute name of the delegate split in parts ['foo','*']
- // - props - the split props of the event that happened ['foo','bar','0']
- // - returns - the attribute to delegate too ('foo.bar'), or null if not a match
- var delegateMatches = function(parts, props) {
- //check props parts are the same or
- var len = parts.length,
- i = 0,
- // keeps the matched props we will use
- matchedProps = [],
- prop;
-
- // if the event matches
- for (i; i < len; i++) {
- prop = props[i]
- // if no more props (but we should be matching them)
- // return null
- if (typeof prop !== 'string') {
- return null;
- } else
- // if we have a "**", match everything
- if (parts[i] == "**") {
- return props.join(".");
- } else
- // a match, but we want to delegate to "*"
- if (parts[i] == "*") {
- // only do this if there is nothing after ...
- matchedProps.push(prop);
- } else if (prop === parts[i]) {
- matchedProps.push(prop);
- } else {
- return null;
- }
- }
- return matchedProps.join(".");
- },
- // gets a change event and tries to figure out which
- // delegates to call
- delegateHandler = function(event, prop, how, newVal, oldVal) {
- // pre-split properties to save some regexp time
- var props = prop.split("."),
- delegates = (this._observe_delegates || []).slice(0),
- delegate,
- attr,
- matchedAttr,
- hasMatch,
- valuesEqual;
- event.attr = prop;
- event.lastAttr = props[props.length - 1];
-
- // for each delegate
- for (var i = 0; delegate = delegates[i++];) {
-
- // if there is a batchNum, this means that this
- // event is part of a series of events caused by a single
- // attrs call. We don't want to issue the same event
- // multiple times
- // setting the batchNum happens later
- if ((event.batchNum && delegate.batchNum === event.batchNum) || delegate.undelegated) {
- continue;
- }
-
- // reset match and values tests
- hasMatch = undefined;
- valuesEqual = true;
-
- // yeah, all this under here has to be redone v
-
- // for each attr in a delegate
- for (var a = 0; a < delegate.attrs.length; a++) {
-
- attr = delegate.attrs[a];
-
- // check if it is a match
- if (matchedAttr = delegateMatches(attr.parts, props)) {
- hasMatch = matchedAttr;
- }
- // if it has a value, make sure it's the right value
- // if it's set, we should probably check that it has a
- // value no matter what
- if (attr.value && valuesEqual) {
- valuesEqual = attr.value === "" + this.attr(attr.attr)
- } else if (valuesEqual && delegate.attrs.length > 1) {
- // if there are multiple attributes, each has to at
- // least have some value
- valuesEqual = this.attr(attr.attr) !== undefined
- }
- }
-
-
- // if there is a match and valuesEqual ... call back
- if (hasMatch && valuesEqual) {
- // how to get to the changed property from the delegate
- var from = prop.replace(hasMatch + ".", "");
-
- // if this event is part of a batch, set it on the delegate
- // to only send one event
- if (event.batchNum) {
- delegate.batchNum = event.batchNum
- }
-
- // if we listen to change, fire those with the same attrs
- // TODO: the attrs should probably be using from
- if (delegate.event === 'change') {
- arguments[1] = from;
- event.curAttr = hasMatch;
- delegate.callback.apply(this.attr(hasMatch), can.makeArray(arguments));
- } else if (delegate.event === how) {
-
- // if it's a match, callback with the location of the match
- delegate.callback.apply(this.attr(hasMatch), [event, newVal, oldVal, from]);
- } else if (delegate.event === 'set' &&
- how == 'add') {
- // if we are listening to set, we should also listen to add
- delegate.callback.apply(this.attr(hasMatch), [event, newVal, oldVal, from]);
- }
- }
-
- }
- };
-
- can.extend(can.Observe.prototype, {
-
- delegate: function(selector, event, handler) {
- selector = can.trim(selector);
- var delegates = this._observe_delegates || (this._observe_delegates = []),
- attrs = [],
- selectorRegex = /([^\s=,]+)(?:=("[^",]*"|'[^',]*'|[^\s"',]*))?(,?)\s*/g,
- matches;
-
- // parse each property in the selector
- while (matches = selectorRegex.exec(selector)) {
- // we need to do a little doctoring to make up for the quotes.
- if (matches[2] && can.inArray(matches[2].substr(0, 1), ['"', "'"]) >= 0) {
- matches[2] = matches[2].substr(1, -1);
- }
-
- attrs.push({
- // the attribute name
- attr: matches[1],
- // the attribute name, pre-split for speed
- parts: matches[1].split('.'),
- // the value associated with this property (if there was one given)
- value: matches[2],
- // whether this selector combines with the one after it with AND or OR
- or: matches[3] === ','
- });
- }
-
- // delegates has pre-processed info about the event
- delegates.push({
- // the attrs name for unbinding
- selector: selector,
- // an object of attribute names and values {type: 'recipe',id: undefined}
- // undefined means a value was not defined
- attrs: attrs,
- callback: handler,
- event: event
- });
- if (delegates.length === 1) {
- this.bind("change", delegateHandler)
- }
- return this;
- },
-
- undelegate: function(selector, event, handler) {
- selector = selector && can.trim(selector);
-
- var i = 0,
- delegates = this._observe_delegates || [],
- delegateOb;
- if (selector) {
- while (i < delegates.length) {
- delegateOb = delegates[i];
- if (delegateOb.callback === handler ||
- (!handler && delegateOb.selector === selector)) {
- delegateOb.undelegated = true;
- delegates.splice(i, 1)
- } else {
- i++;
- }
- }
- } else {
- // remove all delegates
- delegates = [];
- }
- if (!delegates.length) {
- //can.removeData(this, "_observe_delegates");
- this.unbind("change", delegateHandler)
- }
- return this;
- }
- });
- // add helpers for testing ..
- can.Observe.prototype.delegate.matches = delegateMatches;
- return can.Observe;
- })(can);
\ No newline at end of file
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/date.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/date.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/date.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,104 +0,0 @@
-/**
- * Version: 1.0 Alpha-1
- * Build Date: 13-Nov-2007
- * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/) All rights reserved.
- * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
- * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
- */
-Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
-Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
-return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
-return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
-return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
-if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
-var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
-if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
-if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
-if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
-if(x.month||x.months){this.addMonths(x.month||x.months);}
-if(x.year||x.years){this.addYears(x.year||x.years);}
-if(x.day||x.days){this.addDays(x.day||x.days);}
-return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
-return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
-if(!x.second&&x.second!==0){x.second=-1;}
-if(!x.minute&&x.minute!==0){x.minute=-1;}
-if(!x.hour&&x.hour!==0){x.hour=-1;}
-if(!x.day&&x.day!==0){x.day=-1;}
-if(!x.month&&x.month!==0){x.month=-1;}
-if(!x.year&&x.year!==0){x.year=-1;}
-if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
-if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
-if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
-if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
-if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
-if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
-if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
-if(x.timezone){this.setTimezone(x.timezone);}
-if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
-return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
-var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
-return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
-Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
-return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
-var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
-return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
-var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
-return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
-(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
-break;}
-return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
-rx.push(r[0]);s=r[1];}
-return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
-return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
-throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
-return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
-if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
-try{r=(px[i].call(this,s));}catch(e){r=null;}
-if(r){return r;}}
-throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
-try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
-rx.push(r[0]);s=r[1];}
-return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
-return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
-rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
-s=q[1];}
-if(!r){throw new $P.Exception(s);}
-if(q){throw new $P.Exception(q[1]);}
-if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
-return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
-rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
-if(!last&&q[1].length===0){last=true;}
-if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
-p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
-if(rx[1].length<best[1].length){best=rx;}
-if(best[1].length===0){break;}}
-if(best[0].length===0){return best;}
-if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
-best[1]=q[1];}
-return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
-return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
-if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
-var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
-return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
-this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
-var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
-return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
-for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
-if(this.now){return new Date();}
-var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
-if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
-if(!this.unit){this.unit="day";}
-if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
-if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
-this[this.unit+"s"]=this.value*orient;}
-return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
-if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
-if(this.month&&!this.day){this.day=1;}
-return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
-fn=_C[keys]=_.any.apply(null,px);}
-return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
-return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
-return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
-try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
-return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
-return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
Deleted: trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -1,9 +0,0 @@
-(function(k){function n(c,a){k.ajax({url:c,async:!1,cache:a.cache,contentType:"text/plain;charset="+a.encoding,dataType:"text",success:function(b){r(b,a.mode)}})}function r(c,a){for(var b="",e=c.split(/\n/),d=/(\{\d+\})/g,q=/\{(\d+)\}/g,m=/(\\u.{4})/ig,f=0;f<e.length;f++)if(e[f]=e[f].replace(/^\s\s*/,"").replace(/\s\s*$/,""),e[f].length>0&&e[f].match("^#")!="#"){var g=e[f].split("=");if(g.length>0){for(var o=unescape(g[0]).replace(/^\s\s*/,"").replace(/\s\s*$/,""),h=g.length==1?"":g[1];h.match(/\\$/)==
-"\\";)h=h.substring(0,h.length-1),h+=e[++f].replace(/\s\s*$/,"");for(var l=2;l<g.length;l++)h+="="+g[l];h=h.replace(/^\s\s*/,"").replace(/\s\s*$/,"");if(a=="map"||a=="both"){if(g=h.match(m))for(l=0;l<g.length;l++)h=h.replace(g[l],s(g[l]));k.i18n.map[o]=h}if(a=="vars"||a=="both")if(h=h.replace(/"/g,'\\"'),t(o),d.test(h)){for(var g=h.split(d),l=!0,j="",n=[],p=0;p<g.length;p++)if(d.test(g[p])&&(n.length==0||n.indexOf(g[p])==-1))l||(j+=","),j+=g[p].replace(q,"v$1"),n.push(g[p]),l=!1;b+=o+"=function("+
-j+"){";o='"'+h.replace(q,'"+v$1+"')+'"';b+="return "+o+";};"}else b+=o+'="'+h+'";'}}eval(b)}function t(c){if(/\./.test(c))for(var a="",c=c.split(/\./),b=0;b<c.length;b++)b>0&&(a+="."),a+=c[b],eval("typeof "+a+' == "undefined"')&&eval(a+"={};")}function s(c){var a=[],c=parseInt(c.substr(2),16);c>=0&&c<Math.pow(2,16)&&a.push(c);for(var c="",b=0;b<a.length;++b)c+=String.fromCharCode(a[b]);return c}k.i18n={};k.i18n.map={};k.i18n.properties=function(c){c=k.extend({name:"Messages",language:"",path:"",mode:"vars",
-cache:!1,encoding:"UTF-8",callback:null},c);if(c.language===null||c.language=="")c.language=k.i18n.browserLang();if(c.language===null)c.language="";var a=c.name&&c.name.constructor==Array?c.name:[c.name];for(i=0;i<a.length;i++)n(c.path+a[i]+".properties",c),c.language.length>=2&&n(c.path+a[i]+"_"+c.language.substring(0,2)+".properties",c),c.language.length>=5&&n(c.path+a[i]+"_"+c.language.substring(0,5)+".properties",c);c.callback&&c.callback()};k.i18n.prop=function(c){var a=k.i18n.map[c];if(a==null)return"["+
-c+"]";var b;if(typeof a=="string"){for(b=0;(b=a.indexOf("\\",b))!=-1;)a=a[b+1]=="t"?a.substring(0,b)+"\t"+a.substring(b++ +2):a[b+1]=="r"?a.substring(0,b)+"\r"+a.substring(b++ +2):a[b+1]=="n"?a.substring(0,b)+"\n"+a.substring(b++ +2):a[b+1]=="f"?a.substring(0,b)+"\u000c"+a.substring(b++ +2):a[b+1]=="\\"?a.substring(0,b)+"\\"+a.substring(b++ +2):a.substring(0,b)+a.substring(b+1);var e=[],d,j;for(b=0;b<a.length;)if(a[b]=="'")if(b==a.length-1)a=a.substring(0,b);else if(a[b+1]=="'")a=a.substring(0,b)+
-a.substring(++b);else{for(d=b+2;(d=a.indexOf("'",d))!=-1;)if(d==a.length-1||a[d+1]!="'"){a=a.substring(0,b)+a.substring(b+1,d)+a.substring(d+1);b=d-1;break}else a=a.substring(0,d)+a.substring(++d);d==-1&&(a=a.substring(0,b)+a.substring(b+1))}else if(a[b]=="{")if(d=a.indexOf("}",b+1),d==-1)b++;else if(j=parseInt(a.substring(b+1,d)),!isNaN(j)&&j>=0){var m=a.substring(0,b);m!=""&&e.push(m);e.push(j);b=0;a=a.substring(d+1)}else b=d+1;else b++;a!=""&&e.push(a);a=e;k.i18n.map[c]=e}if(a.length==0)return"";
-if(a.lengh==1&&typeof a[0]=="string")return a[0];m="";for(b=0;b<a.length;b++)m+=typeof a[b]=="string"?a[b]:a[b]+1<arguments.length?arguments[a[b]+1]:"{"+a[b]+"}";return m};k.i18n.browserLang=function(){var c=navigator.language||navigator.userLanguage,c=c.toLowerCase();c.length>3&&(c=c.substring(0,3)+c.substring(3).toUpperCase());return c};var j;if(!j)j=function(c,a,b){if(Object.prototype.toString.call(a)!=="[object RegExp]")return typeof j._nativeSplit=="undefined"?c.split(a,b):j._nativeSplit.call(c,
-a,b);var e=[],d=0,k=(a.ignoreCase?"i":"")+(a.multiline?"m":"")+(a.sticky?"y":""),a=RegExp(a.source,k+"g"),m,f,g;c+="";j._compliantExecNpcg||(m=RegExp("^"+a.source+"$(?!\\s)",k));if(b===void 0||+b<0)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;f=a.exec(c);){k=f.index+f[0].length;if(k>d&&(e.push(c.slice(d,f.index)),!j._compliantExecNpcg&&f.length>1&&f[0].replace(m,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===void 0&&(f[a]=void 0)}),f.length>1&&f.index<c.length&&Array.prototype.push.apply(e,
-f.slice(1)),g=f[0].length,d=k,e.length>=b))break;a.lastIndex===f.index&&a.lastIndex++}d===c.length?(g||!a.test(""))&&e.push(""):e.push(c.slice(d));return e.length>b?e.slice(0,b):e},j._compliantExecNpcg=/()??/.exec("")[1]===void 0,j._nativeSplit=String.prototype.split;String.prototype.split=function(c,a){return j(this,c,a)}})(jQuery);
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/js/models/polls.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/js/models/polls.js 2013-06-18 09:15:55 UTC (rev 3835)
@@ -33,10 +33,10 @@
description: "description très longue, mais vraiment très longue pour qu'elle passe en dessous. Enfin j'espère que ce sera assez long",
creatorName: "moi",
choiceAddAllowed: true,
- beginChoiceDate: new Date().getTime(),
- endChoiceDate: new Date().addMinutes(1).getTime(),
- beginDate: new Date().addDays(-5).getTime(),
- endDate: new Date().addDays(5).getTime(),
+ beginChoiceDate: moment.valueOf(),
+ endChoiceDate: moment().add('m', 1).valueOf(),
+ beginDate: moment().subtract('d', 5).valueOf(),
+ endDate: moment().add('d', 5).valueOf(),
choices: [
{
id: 3,
Modified: trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-18 06:22:46 UTC (rev 3834)
+++ trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-18 09:15:55 UTC (rev 3835)
@@ -10,11 +10,11 @@
| <a id="commentSummary" class='link'><i class='icon-comment'></i> <%= comments.attr('length') %></a>
<!-- poll dates -->
<% if (poll.attr('beginDate') && poll.attr('endDate')) { %>
- | <i class='icon-time'></i> <%= pollen.common.date.fromTo(new Date(poll.attr('beginDate')).toString(pollen.common.format.date), new Date(poll.attr('endDate')).toString(pollen.common.format.date)) %>
+ | <i class='icon-time'></i> <%= pollen.common.date.fromTo(moment(poll.attr('beginDate')).format(pollen.common.format.date), moment(poll.attr('endDate')).format(pollen.common.format.date)) %>
<% } else if (poll.attr('beginDate')) { %>
- | <i class='icon-time'></i> <%= pollen.common.date.from(new Date(poll.attr('beginDate')).toString(pollen.common.format.date)) %>
+ | <i class='icon-time'></i> <%= pollen.common.date.from(moment(poll.attr('beginDate')).format(pollen.common.format.date)) %>
<% } else if (poll.attr('endDate')) { %>
- | <i class='icon-time'></i> <%= pollen.common.date.to(new Date(poll.attr('endDate')).toString(pollen.common.format.date)) %>
+ | <i class='icon-time'></i> <%= pollen.common.date.to(moment(poll.attr('endDate')).format(pollen.common.format.date)) %>
<% } %>
</p>
@@ -178,7 +178,7 @@
<%= comment.attr('text') %>
</p>
<div class='footer'>
- <small><%= comment.attr('author') %> | <%= new Date(comment.attr('postDate')).toString(pollen.common.format.dateTime) %></small>
+ <small><%= comment.attr('author') %> | <%= moment(comment.attr('postDate')).format(pollen.common.format.dateTime) %></small>
</div>
</div>
1
0
Author: tchemit
Date: 2013-06-18 08:22:46 +0200 (Tue, 18 Jun 2013)
New Revision: 3834
Url: http://chorem.org/projects/pollen/repository/revisions/3834
Log:
continue services
Added:
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserService.java
trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidCommentFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollenUserFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoteFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActivationTokenException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java
trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java
Removed:
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java
trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/UserServiceTest.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserEmailAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActiviationTokenException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserLoginAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/EmailService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/UserService.java
trunk/pollen-services/src/test/java/org/chorem/pollen/service/UserServiceTest.java
Modified:
trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
trunk/pollen-ui-js/pom.xml
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java
===================================================================
--- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -24,6 +24,7 @@
*/
import javax.persistence.Entity;
+import java.util.Date;
/**
* TODO
@@ -48,4 +49,36 @@
return PollType.GROUP == pollType;
}
+ public boolean isStarted(Date currentDate) {
+ return beginDate == null || beginDate.before(currentDate);
+ }
+
+ public boolean isRunning(Date currentDate) {
+ return !isClosed() &&
+ isStarted(currentDate) &&
+ !isFinished(currentDate);
+ }
+
+ public boolean isFinished(Date currentDate) {
+ return endDate != null && currentDate.after(endDate);
+ }
+
+ public boolean isAddChoiceStarted(Date currentDate) {
+ return isChoiceAddAllowed() &&
+ (beginChoiceDate == null || beginChoiceDate.before(currentDate));
+ }
+
+ public boolean isAddChoiceRunning(Date currentDate) {
+ return isChoiceAddAllowed() &&
+ !isClosed() &&
+ !isFinished(currentDate) &&
+ isAddChoiceStarted(currentDate) &&
+ !isAddChoiceFinished(currentDate);
+ }
+
+ public boolean isAddChoiceFinished(Date currentDate) {
+ return !isChoiceAddAllowed() ||
+ (endChoiceDate != null && endChoiceDate.before(currentDate));
+ }
+
} //Poll
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -26,8 +26,8 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollenUserFormException;
import org.debux.webmotion.server.WebMotionServerListener;
import org.debux.webmotion.server.call.Call;
import org.debux.webmotion.server.call.HttpContext;
@@ -71,9 +71,9 @@
PollenServiceContext serviceContext =
applicationContext.newServiceContext(entityManager);
serviceContext.getUserService().createDefaultUsers();
- } catch (UserEmailAlreadyUsedException e) {
+ } catch (InvalidPollenUserFormException e) {
//Can't happen
- } catch (UserLoginAlreadyUsedException e) {
+ } catch (EntityNotFoundException e) {
//Can't happen
} finally {
entityManager.close();
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -26,6 +26,7 @@
import org.chorem.pollen.persistence.entity.Comment;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidCommentFormException;
import org.debux.webmotion.server.WebMotionController;
import java.util.List;
@@ -43,16 +44,16 @@
return comments;
}
- public Comment getComment(PollenServiceContext context, String commentId) throws EntityNotFoundException {
- return context.getCommentService().getComment(commentId);
+ public Comment getComment(PollenServiceContext context, String pollId, String commentId) throws EntityNotFoundException {
+ return context.getCommentService().getComment(pollId, commentId);
}
- public Comment addComment(PollenServiceContext context, String pollId, Comment comment) throws EntityNotFoundException {
+ public Comment addComment(PollenServiceContext context, String pollId, Comment comment) throws EntityNotFoundException, InvalidCommentFormException {
return context.getCommentService().addComment(pollId, comment);
}
- public Comment editComment(PollenServiceContext context,Comment comment) throws EntityNotFoundException {
- return context.getCommentService().editComment(comment);
+ public Comment editComment(PollenServiceContext context, String pollId, Comment comment) throws EntityNotFoundException, InvalidCommentFormException {
+ return context.getCommentService().editComment(pollId, comment);
}
public void deleteComment(PollenServiceContext context, String pollId, String commentId) throws EntityNotFoundException {
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -28,8 +28,6 @@
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
import org.chorem.pollen.services.exception.FavoriteListImportException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
-import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidFavoriteListFormException;
import org.chorem.pollen.services.exception.InvalidFavoriteListMemberFormException;
import org.debux.webmotion.server.WebMotionController;
@@ -39,7 +37,6 @@
/**
* TODO
- * TODO All method needs a userId connected
*
* @author tchemit <chemit(a)codelutin.com>
* @since 2.0
@@ -51,7 +48,7 @@
return favoriteLists;
}
- public FavoriteList getFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public FavoriteList getFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException {
return context.getFavoriteListService().getFavoriteList(userId, favoriteListId);
}
@@ -59,40 +56,40 @@
return context.getFavoriteListService().createFavoriteList(userId, favoriteList);
}
- public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNotOwnedByUserException, InvalidFavoriteListFormException {
+ public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException {
return context.getFavoriteListService().editFavoriteList(userId, favoriteList);
}
- public void deleteFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public void deleteFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException {
context.getFavoriteListService().deleteFavoriteList(userId, favoriteListId);
}
- public int importFavoriteListMembersFromCsv(PollenServiceContext context, String userId, String favoriteListId, File csvFile) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ public int importFavoriteListMembersFromCsv(PollenServiceContext context, String userId, String favoriteListId, File csvFile) throws EntityNotFoundException, FavoriteListImportException {
return context.getFavoriteListService().importFavoriteListMembersFromCsv(userId, favoriteListId, csvFile);
}
- public int importFavoriteListMembersFromLdap(PollenServiceContext context, String userId, String favoriteListId, String ldap) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ public int importFavoriteListMembersFromLdap(PollenServiceContext context, String userId, String favoriteListId, String ldap) throws EntityNotFoundException, FavoriteListImportException {
return context.getFavoriteListService().importFavoriteListMembersFromLdap(userId, favoriteListId, ldap);
}
- public List<FavoriteListMember> getMembers(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public List<FavoriteListMember> getMembers(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException {
List<FavoriteListMember> members = context.getFavoriteListService().getFavoriteListMembers(userId, favoriteListId);
return members;
}
- public FavoriteListMember getMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ public FavoriteListMember getMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException {
return context.getFavoriteListService().getFavoriteListMember(userId, favoriteListId, memberId);
}
- public FavoriteListMember addMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ public FavoriteListMember addMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException {
return context.getFavoriteListService().addFavoriteListMember(userId, favoriteListId, member);
}
- public FavoriteListMember editMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ public FavoriteListMember editMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException {
return context.getFavoriteListService().editFavoriteListMember(userId, favoriteListId, member);
}
- public void removeMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ public void removeMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException {
context.getFavoriteListService().removeFavoriteListMember(userId, favoriteListId, memberId);
}
}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserService.java (from rev 3831, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollenUserService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,77 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.PollenUser;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollenUserFormException;
+import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException;
+import org.chorem.pollen.services.exception.UserInvalidPasswordException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenUserService extends WebMotionController {
+
+ public List<PollenUser> getUsers(PollenServiceContext context) {
+ List<PollenUser> users = context.getUserService().getUsers();
+ return users;
+ }
+
+ public PollenUser getUser(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ return context.getUserService().getUser(userId);
+ }
+
+ public PollenUser createUser(PollenServiceContext context,
+ PollenUser user,
+ boolean generatePassword) throws EntityNotFoundException, InvalidPollenUserFormException {
+ return context.getUserService().createUser(user, generatePassword);
+
+ }
+
+ public PollenUser editUser(PollenServiceContext context,
+ PollenUser user) throws EntityNotFoundException, InvalidPollenUserFormException {
+ return context.getUserService().editUser(user);
+ }
+
+ public void validateUserEmail(PollenServiceContext context,
+ String userId,
+ String token) throws EntityNotFoundException, UserInvalidEmailActivationTokenException {
+ context.getUserService().validateUserEmail(userId, token);
+ }
+
+ public void changePassword(PollenServiceContext context,
+ String userId,
+ String oldPassword,
+ String newPassword) throws EntityNotFoundException, UserInvalidPasswordException {
+ context.getUserService().changePassword(userId, oldPassword, newPassword);
+ }
+}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,79 +0,0 @@
-package org.chorem.pollen.rest.api.v1;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.PollenUser;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserInvalidEmailActiviationTokenException;
-import org.chorem.pollen.services.exception.UserInvalidPasswordException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserService extends WebMotionController {
-
- public List<PollenUser> getUsers(PollenServiceContext context) {
- List<PollenUser> users = context.getUserService().getUsers();
- return users;
- }
-
- public PollenUser getUser(PollenServiceContext context,
- String userId) throws EntityNotFoundException {
- return context.getUserService().getUser(userId);
- }
-
- public PollenUser createUser(PollenServiceContext context,
- PollenUser user,
- boolean generatePassword) throws UserEmailAlreadyUsedException, UserLoginAlreadyUsedException {
- return context.getUserService().createUser(user, generatePassword);
-
- }
-
- public PollenUser editUser(PollenServiceContext context,
- PollenUser user) throws UserInvalidPasswordException, UserEmailAlreadyUsedException, EntityNotFoundException {
- return context.getUserService().editUser(user);
- }
-
- public void validateUserEmail(PollenServiceContext context,
- String userId,
- String token) throws EntityNotFoundException, UserInvalidEmailActiviationTokenException {
- context.getUserService().validateUserEmail(userId, token);
- }
-
- public void changePassword(PollenServiceContext context,
- String userId,
- String oldPassword,
- String newPassword) throws UserInvalidPasswordException, EntityNotFoundException {
- context.getUserService().changePassword(userId, oldPassword, newPassword);
- }
-}
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -26,6 +26,7 @@
import org.chorem.pollen.persistence.entity.Vote;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidVoteFormException;
import org.debux.webmotion.server.WebMotionController;
import java.util.List;
@@ -43,16 +44,16 @@
return votes;
}
- public Vote getVote(PollenServiceContext context, String voteId) throws EntityNotFoundException {
- return context.getVoteService().getVote(voteId);
+ public Vote getVote(PollenServiceContext context, String pollId, String voteId) throws EntityNotFoundException {
+ return context.getVoteService().getVote(pollId, voteId);
}
- public Vote addVote(PollenServiceContext context, String pollId, Vote vote) throws EntityNotFoundException {
+ public Vote addVote(PollenServiceContext context, String pollId, Vote vote) throws EntityNotFoundException, InvalidVoteFormException {
return context.getVoteService().addVote(pollId, vote);
}
- public Vote editVote(PollenServiceContext context, Vote vote) throws EntityNotFoundException {
- return context.getVoteService().editVote(vote);
+ public Vote editVote(PollenServiceContext context, String pollId, Vote vote) throws EntityNotFoundException, InvalidVoteFormException {
+ return context.getVoteService().editVote(pollId, vote);
}
public void deleteVote(PollenServiceContext context, String pollId, String voteId) throws EntityNotFoundException {
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -27,8 +27,8 @@
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidVoterListFormException;
+import org.chorem.pollen.services.exception.InvalidVoterListMemberFormException;
import org.debux.webmotion.server.WebMotionController;
import java.util.List;
@@ -42,7 +42,7 @@
*/
public class VoterListService extends WebMotionController {
- public VoterList importFavoriteList(PollenServiceContext context, String userId, String pollId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public VoterList importFavoriteList(PollenServiceContext context, String userId, String pollId, String favoriteListId) throws EntityNotFoundException {
return context.getVoterListService().importFavoriteList(userId, pollId, favoriteListId);
}
@@ -76,11 +76,11 @@
return context.getVoterListService().getVoterListMember(pollId, voterListId, memberId);
}
- public VoterListMember addMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ public VoterListMember addMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException, InvalidVoterListMemberFormException {
return context.getVoterListService().addVoterListMember(pollId, voterListId, member);
}
- public VoterListMember editMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ public VoterListMember editMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException, InvalidVoterListMemberFormException {
return context.getVoterListService().editVoterListMember(pollId, voterListId, member);
}
Copied: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java (from rev 3833, trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/UserServiceTest.java)
===================================================================
--- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java (rev 0)
+++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/PollenUserServiceTest.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,84 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.http.client.fluent.Request;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+@Ignore
+public class PollenUserServiceTest extends AbstractPollenRestApiTest {
+
+
+ @Before
+ public void setUp() throws Exception {
+
+ loadFixtures("fixtures");
+ }
+
+ @Test
+ public void testGetUsers() throws Exception {
+
+ Request request = createRequest("/users").Get();
+ String result = request.execute().returnContent().asString();
+
+ assertTrue(result.contains("email"));
+
+
+ }
+
+// @Test
+// public void testGetUser() throws Exception {
+//
+// }
+//
+// @Test
+// public void testCreateUser() throws Exception {
+//
+// }
+//
+// @Test
+// public void testEditUser() throws Exception {
+//
+// }
+//
+// @Test
+// public void testValidateUserEmail() throws Exception {
+//
+// }
+//
+// @Test
+// public void testChangePassword() throws Exception {
+//
+// }
+}
Deleted: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/UserServiceTest.java
===================================================================
--- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/UserServiceTest.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/UserServiceTest.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,84 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.apache.http.client.fluent.Request;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-@Ignore
-public class UserServiceTest extends AbstractPollenRestApiTest {
-
-
- @Before
- public void setUp() throws Exception {
-
- loadFixtures("fixtures");
- }
-
- @Test
- public void testGetUsers() throws Exception {
-
- Request request = createRequest("/users").Get();
- String result = request.execute().returnContent().asString();
-
- assertTrue(result.contains("email"));
-
-
- }
-
-// @Test
-// public void testGetUser() throws Exception {
-//
-// }
-//
-// @Test
-// public void testCreateUser() throws Exception {
-//
-// }
-//
-// @Test
-// public void testEditUser() throws Exception {
-//
-// }
-//
-// @Test
-// public void testValidateUserEmail() throws Exception {
-//
-// }
-//
-// @Test
-// public void testChangePassword() throws Exception {
-//
-// }
-}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -24,18 +24,18 @@
*/
import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.PollenEntityIdFactory;
import org.chorem.pollen.persistence.PollenPersistenceContext;
import org.chorem.pollen.services.config.PollenServiceConfig;
import org.chorem.pollen.services.service.AuthService;
import org.chorem.pollen.services.service.ChoiceService;
import org.chorem.pollen.services.service.CommentService;
-import org.chorem.pollen.services.service.EmailService;
import org.chorem.pollen.services.service.FavoriteListService;
import org.chorem.pollen.services.service.FixturesService;
import org.chorem.pollen.services.service.PollService;
+import org.chorem.pollen.services.service.PollenUserService;
import org.chorem.pollen.services.service.SecurityService;
-import org.chorem.pollen.services.service.UserService;
import org.chorem.pollen.services.service.VoteCountingService;
import org.chorem.pollen.services.service.VoteService;
import org.chorem.pollen.services.service.VoterListService;
@@ -128,8 +128,8 @@
}
@Override
- public UserService getUserService() {
- return newService(UserService.class);
+ public PollenUserService getUserService() {
+ return newService(PollenUserService.class);
}
@Override
@@ -148,11 +148,6 @@
}
@Override
- public EmailService getEmailService() {
- return newService(EmailService.class);
- }
-
- @Override
public FixturesService getFixturesService() {
return newService(FixturesService.class);
}
@@ -169,12 +164,17 @@
@Override
public Locale getLocale() {
- if (locale==null) {
+ if (locale == null) {
locale = Locale.getDefault();
}
return locale;
}
+ @Override
+ public String getCleanMail(String email) {
+ return email == null ? null : StringUtils.lowerCase(email.trim());
+ }
+
public <E extends PollenServiceSupport> E newService(Class<E> serviceClass) {
E service;
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -37,7 +37,7 @@
/**
* TODO
- *
+ * <p/>
* http://www.slideshare.net/chunsaker/securing-rest-apis ?
*
* @author tchemit <chemit(a)codelutin.com>
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -28,12 +28,11 @@
import org.chorem.pollen.services.service.AuthService;
import org.chorem.pollen.services.service.ChoiceService;
import org.chorem.pollen.services.service.CommentService;
-import org.chorem.pollen.services.service.EmailService;
import org.chorem.pollen.services.service.FavoriteListService;
import org.chorem.pollen.services.service.FixturesService;
import org.chorem.pollen.services.service.PollService;
+import org.chorem.pollen.services.service.PollenUserService;
import org.chorem.pollen.services.service.SecurityService;
-import org.chorem.pollen.services.service.UserService;
import org.chorem.pollen.services.service.VoteCountingService;
import org.chorem.pollen.services.service.VoteService;
import org.chorem.pollen.services.service.VoterListService;
@@ -69,14 +68,13 @@
PollService getPollService();
- UserService getUserService();
+ PollenUserService getUserService();
VoteCountingService getVoteCountingService();
VoterListService getVoterListService();
VoteService getVoteService();
- EmailService getEmailService();
FixturesService getFixturesService();
@@ -87,4 +85,6 @@
String encodePassword(String password);
Locale getLocale();
+
+ String getCleanMail(String email);
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -31,7 +31,7 @@
* @author tchemit <chemit(a)codelutin.com>
* @since 2.0
*/
-public abstract class AbstractInvalidFormException extends Exception{
+public abstract class AbstractInvalidFormException extends Exception {
private static final long serialVersionUID = 1L;
protected final Multimap<String, String> errors;
@@ -47,6 +47,6 @@
@Override
public String toString() {
- return super.toString()+ " errors: "+errors;
+ return super.toString() + " errors: " + errors;
}
}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,34 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListMemberNotOwnedByFavoriteListException extends Throwable {
- private static final long serialVersionUID = 1L;
-}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,35 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListNotOwnedByUserException extends Exception {
- private static final long serialVersionUID = 1L;
-
-}
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidCommentFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidCommentFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidCommentFormException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,40 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidCommentFormException extends AbstractInvalidFormException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidCommentFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidCommentFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollenUserFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollenUserFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollenUserFormException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,40 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidPollenUserFormException extends AbstractInvalidFormException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidPollenUserFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollenUserFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoteFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoteFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoteFormException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,40 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidVoteFormException extends AbstractInvalidFormException {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidVoteFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoteFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserEmailAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserEmailAlreadyUsedException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserEmailAlreadyUsedException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,45 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserEmailAlreadyUsedException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- protected final String email;
-
- public UserEmailAlreadyUsedException(String email) {
- this.email = email;
- }
-
- public String getEmail() {
- return email;
- }
-}
Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActivationTokenException.java (from rev 3833, trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActiviationTokenException.java)
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActivationTokenException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActivationTokenException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,34 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class UserInvalidEmailActivationTokenException extends Exception {
+ private static final long serialVersionUID = 1L;
+}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActiviationTokenException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActiviationTokenException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserInvalidEmailActiviationTokenException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,34 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserInvalidEmailActiviationTokenException extends Exception {
- private static final long serialVersionUID = 1L;
-}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserLoginAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserLoginAlreadyUsedException.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/UserLoginAlreadyUsedException.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,45 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserLoginAlreadyUsedException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- protected final String login;
-
- public UserLoginAlreadyUsedException(String login) {
- this.login=login;
- }
-
- public String getLogin() {
- return login;
- }
-}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -47,21 +47,17 @@
*/
public abstract class AbstractPollenService implements PollenServiceSupport {
+ // -- PollenServiceSupport -- //
+
protected PollenServiceContext serviceContext;
- protected void checkHasId(JpaEntity entity) {
- Preconditions.checkState(JpaEntities.isEntityHasId(entity));
- }
-
- protected void checkHasNoId(JpaEntity entity) {
- Preconditions.checkState(JpaEntities.isEntityHasNoId(entity));
- }
-
@Override
public void setServiceContext(PollenServiceContext serviceContext) {
this.serviceContext = serviceContext;
}
+ // -- Delegate serviceContext -- //
+
protected Date getNow() {
return serviceContext.getNow();
}
@@ -70,6 +66,10 @@
return serviceContext.generateToken();
}
+ protected String getCleanMail(String email) {
+ return serviceContext.getCleanMail(email);
+ }
+
protected PollenPersistenceContext getPersistenceContext() {
return serviceContext.getPersistenceContext();
}
@@ -102,7 +102,7 @@
return serviceContext.getSecurityService();
}
- protected UserService getUserService() {
+ protected PollenUserService getUserService() {
return serviceContext.getUserService();
}
@@ -118,10 +118,16 @@
return serviceContext.getVoteService();
}
- protected EmailService getEmailService() {
- return serviceContext.getEmailService();
+ // -- check method -- //
+
+ protected void checkHasId(JpaEntity entity) {
+ Preconditions.checkState(JpaEntities.isEntityHasId(entity));
}
+ protected void checkHasNoId(JpaEntity entity) {
+ Preconditions.checkState(JpaEntities.isEntityHasNoId(entity));
+ }
+
protected <E extends JpaEntity> void checkEntityExists(Class<E> type,
E entity,
String entityId) throws EntityNotFoundException {
@@ -138,18 +144,23 @@
return valid;
}
+ protected boolean checkNot(Multimap<String, String> errors, String field, boolean condition, String error) {
+ boolean valid = check(errors, field, !condition, error);
+ return valid;
+ }
+
protected boolean checkNotNull(Multimap<String, String> errors, String field, Object value, String error) {
boolean valid = check(errors, field, value != null, error);
return valid;
}
protected boolean checkEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) {
- boolean valid = check(errors, field, CollectionUtils.isEmpty(value ), error);
+ boolean valid = check(errors, field, CollectionUtils.isEmpty(value), error);
return valid;
}
protected boolean checkNotEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) {
- boolean valid = check(errors, field, CollectionUtils.isNotEmpty(value ), error);
+ boolean valid = check(errors, field, CollectionUtils.isNotEmpty(value), error);
return valid;
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -26,9 +26,9 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
import org.chorem.pollen.persistence.dao.ChoiceJpaDao;
import org.chorem.pollen.persistence.entity.Choice;
-import org.chorem.pollen.persistence.entity.ChoiceType;
import org.chorem.pollen.persistence.entity.Poll;
import org.chorem.pollen.persistence.entity.PollenPrincipal;
import org.chorem.pollen.services.exception.EntityNotFoundException;
@@ -36,6 +36,7 @@
import org.nuiton.jpa.api.JpaEntities;
import java.util.List;
+import java.util.Set;
/**
* TODO
@@ -69,12 +70,13 @@
Poll poll = getPollService().getPoll(pollId);
- checkChoiceForm(poll.getChoiceType(), choice);
+ checkChoiceForm(poll, choice);
Choice result = saveChoice(poll, choice, null);
getPersistenceContext().getPollDao().merge(poll);
getPersistenceContext().commit();
+ //TODO Notify Choice added
return result;
}
@@ -84,12 +86,13 @@
Poll poll = getPollService().getPoll(pollId);
- checkChoiceForm(poll.getChoiceType(), choice);
+ checkChoiceForm(poll, choice);
Choice result = saveChoice(poll, choice, null);
getPersistenceContext().getChoiceDao().merge(choice);
getPersistenceContext().commit();
+ //TODO Notify Choice edited
return result;
}
@@ -104,9 +107,10 @@
getPersistenceContext().getPollDao().merge(poll);
getPersistenceContext().commit();
+ //TODO Notify Choice deleted
}
- protected Choice getChoice(Poll poll, String choiceId) throws EntityNotFoundException {
+ protected Choice getChoice(Poll poll, String choiceId) throws EntityNotFoundException {
Choice result = poll.getChoiceById(choiceId);
checkEntityExists(Choice.class, result, choiceId);
@@ -170,21 +174,43 @@
return choiceToPersist;
}
- protected void checkChoiceForm(ChoiceType choiceType, Choice choice) throws InvalidChoiceFormException {
+ protected void checkChoiceForm(Poll poll, Choice choice) throws InvalidChoiceFormException {
//TODO use nuiton validator ?
Multimap<String, String> errors = ArrayListMultimap.create();
- switch (choiceType) {
+ boolean choiceExists = JpaEntities.isEntityHasId(choice);
+ Set<String> choiceNames = Sets.newHashSet();
+
+ if (!poll.isChoiceEmpty()) {
+
+ // get all used names
+
+ for (Choice member : poll.getChoice()) {
+
+ if (choiceExists &&
+ member.getId().equals(choice.getId())) {
+ continue;
+ }
+ choiceNames.add(member.getName());
+ }
+ }
+
+ switch (poll.getChoiceType()) {
+
case TEXT:
- //TODO Should check unique choice name ?
+ String choiceName = choice.getName();
+ boolean nameNotBlank = checkNotBlank(errors,
+ "name",
+ choiceName,
+ "choice name can not be empty");
- checkNotBlank(errors,
- "name",
- choice.getName(),
- "choice name can not be empty");
+ if (nameNotBlank) {
+ boolean nameAdded = choiceNames.add(choiceName);
+ check(errors, "name", nameAdded, "choice name already used in this list");
+ }
break;
case DATE:
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/CommentService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -24,9 +24,15 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.entity.Comment;
import org.chorem.pollen.persistence.entity.Poll;
+import org.chorem.pollen.persistence.entity.PollenPrincipal;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidCommentFormException;
+import org.nuiton.jpa.api.JpaEntities;
import java.util.List;
@@ -44,51 +50,116 @@
return poll.getComment();
}
- public Comment getComment(String commentId) throws EntityNotFoundException {
+ public Comment getComment(String pollId, String commentId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(commentId);
- Comment result = getPersistenceContext().getCommentDao().findById(commentId);
- checkEntityExists(Comment.class, result, commentId);
+
+ Poll poll = getPollService().getPoll(pollId);
+
+ Comment result = getComment(poll, commentId);
return result;
}
- public Comment addComment(String pollId, Comment comment) throws EntityNotFoundException {
+ public Comment addComment(String pollId, Comment comment) throws EntityNotFoundException, InvalidCommentFormException {
Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(comment);
checkHasNoId(comment);
+
Poll poll = getPollService().getPoll(pollId);
+ checkCommentForm(poll, comment);
- poll.addComment(comment);
+ Comment result = saveComment(poll, comment);
+
getPersistenceContext().getPollDao().merge(poll);
getPersistenceContext().commit();
-
- Comment result = getComment(comment.getId());
return result;
}
- public Comment editComment(Comment comment) throws EntityNotFoundException {
+ public Comment editComment(String pollId, Comment comment) throws EntityNotFoundException, InvalidCommentFormException {
+ Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(comment);
+ checkHasId(comment);
- // check comment exists
- getComment(comment.getId());
+ Poll poll = getPollService().getPoll(pollId);
+ checkCommentForm(poll, comment);
+ Comment result = saveComment(poll, comment);
+
getPersistenceContext().getCommentDao().merge(comment);
getPersistenceContext().commit();
-
- Comment result = getComment(comment.getId());
return result;
}
public void deleteComment(String pollId, String commentId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(commentId);
+
Poll poll = getPollService().getPoll(pollId);
- Comment comment = getComment(commentId);
- Preconditions.checkNotNull(comment);
+ Comment comment = getComment(poll, commentId);
poll.removeComment(comment);
getPersistenceContext().getPollDao().merge(poll);
-
getPersistenceContext().commit();
}
+ protected Comment getComment(Poll poll, String commentId) throws EntityNotFoundException {
+
+ Comment result = poll.getCommentById(commentId);
+ checkEntityExists(Comment.class, result, commentId);
+ return result;
+ }
+
+ protected void checkCommentForm(Poll poll, Comment comment) throws InvalidCommentFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ checkNotBlank(errors, "text", comment.getText(), "textcan not be empty");
+ boolean authorNotNull = checkNotNull(errors, "author", comment.getAuthor(), "author can not be null");
+ if (authorNotNull) {
+ checkNotBlank(errors, "author.name", comment.getAuthor().getName(), "author name can not be empty");
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidCommentFormException(errors);
+ }
+ }
+
+ protected Comment saveComment(Poll poll, Comment comment) throws EntityNotFoundException {
+
+ boolean commentExists = JpaEntities.isEntityHasId(comment);
+
+ Comment toSave;
+
+ if (commentExists) {
+
+ toSave = getComment(poll, comment.getId());
+ } else {
+
+ toSave = getPersistenceContext().getCommentDao().newInstance();
+ toSave.setPostDate(serviceContext.getNow());
+
+ // -- author -- //
+
+ PollenPrincipal author = getSecurityService().generatePrincipal();
+ toSave.setAuthor(author);
+
+ poll.addComment(toSave);
+ }
+
+ toSave.setText(comment.getText());
+
+ // -- author -- //
+
+ toSave.getAuthor().setName(comment.getAuthor().getName());
+ if (StringUtils.isNotBlank(comment.getAuthor().getEmail())) {
+ toSave.getAuthor().setEmail(StringUtils.lowerCase(comment.getAuthor().getEmail()));
+ }
+
+ return toSave;
+ }
+
}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/EmailService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/EmailService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/EmailService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,39 +0,0 @@
-package org.chorem.pollen.services.service;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.PollenUser;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class EmailService extends AbstractPollenService {
-
- public void onUserCreated(PollenUser user) {
- //TODO
- }
-}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -35,8 +35,6 @@
import org.chorem.pollen.services.PollenTechnicalException;
import org.chorem.pollen.services.exception.EntityNotFoundException;
import org.chorem.pollen.services.exception.FavoriteListImportException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
-import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidFavoriteListFormException;
import org.chorem.pollen.services.exception.InvalidFavoriteListMemberFormException;
import org.nuiton.jpa.api.JpaEntities;
@@ -77,7 +75,7 @@
return result;
}
- public FavoriteList getFavoriteList(String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public FavoriteList getFavoriteList(String userId, String favoriteListId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
@@ -108,7 +106,7 @@
}
public FavoriteList editFavoriteList(String userId,
- FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException, FavoriteListNotOwnedByUserException {
+ FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException {
Preconditions.checkNotNull(favoriteList);
checkHasId(favoriteList);
@@ -128,7 +126,7 @@
return toSave;
}
- public void deleteFavoriteList(String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public void deleteFavoriteList(String userId, String favoriteListId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
@@ -136,19 +134,13 @@
FavoriteList persisted = getFavoriteList(user, favoriteListId);
- // check user own this list
- boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
- if (!ownedByUser) {
- throw new FavoriteListNotOwnedByUserException();
- }
-
user.removeFavoriteList(persisted);
getPersistenceContext().getPollenUserDao().merge(user);
getPersistenceContext().commit();
}
- public List<FavoriteListMember> getFavoriteListMembers(String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ public List<FavoriteListMember> getFavoriteListMembers(String userId, String favoriteListId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
@@ -159,7 +151,7 @@
return favoriteList.getFavoriteListMember();
}
- public FavoriteListMember getFavoriteListMember(String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ public FavoriteListMember getFavoriteListMember(String userId, String favoriteListId, String memberId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(memberId);
@@ -174,7 +166,7 @@
public FavoriteListMember addFavoriteListMember(String userId,
String favoriteListId,
- FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(member);
@@ -199,7 +191,7 @@
public FavoriteListMember editFavoriteListMember(String userId,
String favoriteListId,
- FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(member);
@@ -226,7 +218,7 @@
public void removeFavoriteListMember(String userId,
String favoriteListId,
- String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ String memberId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(memberId);
@@ -245,7 +237,7 @@
public int importFavoriteListMembersFromCsv(String userId,
String favoriteListId,
- File file) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ File file) throws EntityNotFoundException, FavoriteListImportException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(file);
@@ -344,7 +336,7 @@
public int importFavoriteListMembersFromLdap(String userId,
String favoriteListId,
- String ldap) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ String ldap) throws EntityNotFoundException, FavoriteListImportException {
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(ldap);
@@ -429,31 +421,19 @@
return result;
}
- protected FavoriteList getFavoriteList(PollenUser user, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ protected FavoriteList getFavoriteList(PollenUser user, String favoriteListId) throws EntityNotFoundException {
Preconditions.checkNotNull(favoriteListId);
FavoriteList result = user.getFavoriteListById(favoriteListId);
checkEntityExists(FavoriteList.class, result, favoriteListId);
- // check user own this list
- boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
-
- if (!ownedByUser) {
- throw new FavoriteListNotOwnedByUserException();
- }
return result;
}
- protected FavoriteListMember getFavoriteListMember(FavoriteList favoriteList, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
+ protected FavoriteListMember getFavoriteListMember(FavoriteList favoriteList, String memberId) throws EntityNotFoundException {
FavoriteListMember result = favoriteList.getFavoriteListMemberById(memberId);
checkEntityExists(FavoriteListMember.class, result, memberId);
-
- // check favorite list own this member
- boolean ownedByUser = favoriteList.containsFavoriteListMemberById(memberId);
- if (!ownedByUser) {
- throw new FavoriteListMemberNotOwnedByFavoriteListException();
- }
return result;
}
@@ -505,21 +485,19 @@
String choiceField = "favoriteListMember[" + (memberIndex++) + "].";
- boolean notBlankName = checkNotBlank(errors, choiceField + "name", member.getName(), "member name can not be empty");
- if (notBlankName) {
+ boolean nameNotBlank = checkNotBlank(errors, choiceField + "name", member.getName(), "member name can not be empty");
+ if (nameNotBlank) {
boolean added = memberNames.add(member.getName());
check(errors, choiceField + "name", added, "member name already used");
}
- String memberEmail = member.getEmail();
+ String memberEmail = getCleanMail(member.getEmail());
- boolean emailNotNull = checkNotBlank(errors, choiceField + "email", memberEmail, "member email can not be empty");
+ boolean emailNotBlank = checkNotBlank(errors, choiceField + "email", memberEmail, "member email can not be empty");
- if (emailNotNull) {
+ if (emailNotBlank) {
- memberEmail = StringUtils.lowerCase(memberEmail);
-
checkValidEmail(errors, choiceField + "email", memberEmail, "member email is not valid");
boolean emailAdded = memberEmails.add(memberEmail);
check(errors, choiceField + "email", emailAdded, "member email already used in this list");
@@ -559,24 +537,23 @@
}
}
- boolean notBlankName = checkNotBlank(errors, "name", favoriteListMember.getName(), "member name can not be empty");
- if (notBlankName) {
+ boolean nameNotBlank = checkNotBlank(errors, "name", favoriteListMember.getName(), "member name can not be empty");
+ if (nameNotBlank) {
boolean added = memberNames.add(favoriteListMember.getName());
-
check(errors, "name", added, "member name already used");
}
- String memberEmail = favoriteListMember.getEmail();
+ String memberEmail = getCleanMail(favoriteListMember.getEmail());
- boolean emailNotNull = checkNotBlank(errors, "email", memberEmail, "member email can not be empty");
+ boolean emailNotBlank = checkNotBlank(errors, "email", memberEmail, "member email can not be empty");
- if (emailNotNull) {
+ if (emailNotBlank) {
- memberEmail = StringUtils.lowerCase(memberEmail);
-
- checkValidEmail(errors, "email", memberEmail, "member email is not valid");
- boolean emailAdded = memberEmails.add(memberEmail);
- check(errors, "email", emailAdded, "member email already used in this list");
+ boolean emailValid = checkValidEmail(errors, "email", memberEmail, "member email is not valid");
+ if (emailValid) {
+ boolean emailAdded = memberEmails.add(memberEmail);
+ check(errors, "email", emailAdded, "member email already used in this list");
+ }
}
if (!errors.isEmpty()) {
Copied: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java (from rev 3831, trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/UserService.java)
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollenUserService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,256 @@
+package org.chorem.pollen.services.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.commons.lang3.ObjectUtils;
+import org.chorem.pollen.persistence.dao.PollenUserJpaDao;
+import org.chorem.pollen.persistence.entity.PollenUser;
+import org.chorem.pollen.services.PollenServiceSupport;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollenUserFormException;
+import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException;
+import org.chorem.pollen.services.exception.UserInvalidPasswordException;
+import org.nuiton.jpa.api.JpaEntities;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenUserService extends AbstractPollenService implements PollenServiceSupport {
+
+ public List<PollenUser> getUsers() {
+ return getPersistenceContext().getPollenUserDao().findAll();
+ }
+
+ public PollenUser getUser(String userId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(userId);
+
+ PollenUser result = getPersistenceContext().getPollenUserDao().findById(userId);
+ checkEntityExists(PollenUser.class, result, userId);
+ return result;
+ }
+
+ public PollenUser createUser(PollenUser user, boolean generatePassword) throws InvalidPollenUserFormException, EntityNotFoundException {
+ Preconditions.checkNotNull(user);
+ checkHasNoId(user);
+ checkPollenUserForm(user);
+
+ PollenUser result = savePollenUser(user, generatePassword);
+
+ getPersistenceContext().getPollenUserDao().persist(result);
+ getPersistenceContext().commit();
+ //TODO Notify user created
+ return result;
+ }
+
+ public PollenUser editUser(PollenUser user) throws EntityNotFoundException, InvalidPollenUserFormException {
+ Preconditions.checkNotNull(user);
+ checkHasId(user);
+ checkPollenUserForm(user);
+
+ PollenUser result = savePollenUser(user, false);
+
+ getPersistenceContext().getPollenUserDao().merge(result);
+ getPersistenceContext().commit();
+ //TODO Notify user edited
+ return result;
+ }
+
+ public void changePassword(String userId,
+ String oldPassword,
+ String newPassword) throws EntityNotFoundException, UserInvalidPasswordException {
+ Preconditions.checkNotNull(userId);
+ Preconditions.checkNotNull(oldPassword);
+ Preconditions.checkNotNull(newPassword);
+
+ PollenUser user = getUser(userId);
+
+ // check current password
+ String encodedPassword = serviceContext.encodePassword(user.getPassword());
+ if (!encodedPassword.equals(user.getPassword())) {
+ throw new UserInvalidPasswordException();
+ }
+
+ // encode new password and store it in user account
+ String newEncodedPassword = serviceContext.encodePassword(newPassword);
+ user.setPassword(newEncodedPassword);
+
+ getPersistenceContext().getPollenUserDao().merge(user);
+ getPersistenceContext().commit();
+ //TODO Notify PasswordChanged
+ }
+
+ public void validateUserEmail(String userId,
+ String token) throws EntityNotFoundException, UserInvalidEmailActivationTokenException {
+
+ Preconditions.checkNotNull(userId);
+ Preconditions.checkNotNull(token);
+
+ PollenUser user = getUser(userId);
+
+ boolean valid = ObjectUtils.equals(
+ user.getEmailActivationToken(), token);
+
+ if (!valid) {
+ throw new UserInvalidEmailActivationTokenException();
+ }
+
+ // reset token in database
+ user.setEmailActivationToken(null);
+
+ getPersistenceContext().getPollenUserDao().merge(user);
+ getPersistenceContext().commit();
+ }
+
+ public void createDefaultUsers() throws EntityNotFoundException, InvalidPollenUserFormException {
+
+ PollenUser user = getPersistenceContext().getPollenUserDao().newInstance();
+
+ user.setAdministrator(true);
+ String login = "admin";
+ user.setLogin(login);
+ user.setEmail("admin(a)pollen.org");
+ user.setPassword("admin");
+ createUser(user, false);
+ }
+
+ protected void checkPollenUserForm(PollenUser user) throws EntityNotFoundException, InvalidPollenUserFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ boolean userExists = JpaEntities.isEntityHasId(user);
+ PollenUser persisted = userExists ? getUser(user.getId()) : null;
+ PollenUserJpaDao dao = getPersistenceContext().getPollenUserDao();
+
+ String userLogin = user.getLogin();
+ String userEmail = getCleanMail(user.getEmail());
+
+ boolean loginNotBlank = checkNotBlank(errors, "login", userLogin, "login can not be empty");
+
+ if (loginNotBlank && !userExists) {
+ check(errors, "login", !dao.loginExists(userLogin), "login already exists");
+ }
+
+ boolean emailNotblank = checkNotBlank(errors, "email", userEmail, "email can not be empty");
+
+ if (emailNotblank) {
+ checkValidEmail(errors, "email", userEmail, "email is not valid");
+
+
+ if (userExists) {
+
+ // check if email is available only if has changed
+
+ boolean emailChanged = ObjectUtils.notEqual(persisted.getEmail(),
+ userEmail);
+
+ if (emailChanged) {
+ check(errors, "email", !dao.emailExists(userEmail), "email already exists");
+ }
+ } else {
+ check(errors, "email", !dao.emailExists(userEmail), "email already exists");
+ }
+ }
+
+ if (userExists) {
+
+ // check current password
+ String encodedPassword = serviceContext.encodePassword(user.getPassword());
+ check(errors, "password", encodedPassword.equals(persisted.getPassword()), "invalid password");
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidPollenUserFormException(errors);
+ }
+ }
+
+ protected PollenUser savePollenUser(PollenUser user,
+ boolean generatePassword) throws EntityNotFoundException {
+
+ boolean userExists = JpaEntities.isEntityHasId(user);
+
+ PollenUser toSave;
+
+ String userEmail = getCleanMail(user.getEmail());
+
+ String emailValidationToken = null;
+
+ if (userExists) {
+
+ toSave = getUser(user.getId());
+
+ boolean emailChanged = ObjectUtils.notEqual(toSave.getEmail(),
+ userEmail);
+
+ if (emailChanged) {
+
+ // add a new emailValidationtoken
+ emailValidationToken = generateToken();
+
+ //TODO Notify email changed
+ }
+ } else {
+
+ toSave = getPersistenceContext().getPollenUserDao().newInstance();
+
+ // add a emailValidationToken
+ emailValidationToken = generateToken();
+
+ String password;
+
+ if (generatePassword) {
+ // let's generate the new password
+ password = serviceContext.generatePassword();
+ } else {
+ password = user.getPassword();
+ }
+
+ // encode the password
+ String encodedPassword = serviceContext.encodePassword(password);
+
+ toSave.setLogin(user.getLogin());
+ toSave.setPassword(encodedPassword);
+ }
+
+ toSave.setAdministrator(user.isAdministrator());
+ toSave.setName(user.getName());
+ toSave.setLanguage(user.getLanguage());
+ toSave.setEmail(userEmail);
+
+ if (emailValidationToken != null) {
+ toSave.setEmailActivationToken(emailValidationToken);
+ }
+
+ return toSave;
+ }
+}
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/UserService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/UserService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/UserService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,252 +0,0 @@
-package org.chorem.pollen.services.service;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import com.google.common.base.Preconditions;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.chorem.pollen.persistence.dao.PollenUserJpaDao;
-import org.chorem.pollen.persistence.entity.PollenUser;
-import org.chorem.pollen.services.PollenServiceSupport;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserInvalidEmailActiviationTokenException;
-import org.chorem.pollen.services.exception.UserInvalidPasswordException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
-
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserService extends AbstractPollenService implements PollenServiceSupport {
-
- public List<PollenUser> getUsers() {
- return getPollenUserDao().findAll();
- }
-
- public PollenUser getUser(String userId) throws EntityNotFoundException {
- Preconditions.checkNotNull(userId);
-
- PollenUser result = getPollenUserDao().findById(userId);
- checkEntityExists(PollenUser.class, result, userId);
- return result;
- }
-
- public PollenUser createUser(PollenUser user, boolean generatePassword) throws UserLoginAlreadyUsedException, UserEmailAlreadyUsedException {
- Preconditions.checkNotNull(user);
- checkHasNoId(user);
- Preconditions.checkNotNull(user.getLogin());
- Preconditions.checkNotNull(user.getEmail());
-
- PollenUserJpaDao dao = getPollenUserDao();
-
- // check login is available
- boolean loginExists = dao.loginExists(user.getLogin());
- if (loginExists) {
- throw new UserLoginAlreadyUsedException(user.getLogin());
- }
-
- // check email is available
- boolean emailExists = dao.emailExists(user.getEmail());
- if (emailExists) {
- throw new UserEmailAlreadyUsedException(user.getEmail());
- }
-
- PollenUser toCreate = dao.newInstance();
-
- // add a emailValidationToken
- String emailValidationToken = generateToken();
-
- String password;
- if (generatePassword) {
- // let's generate the new password
- password = serviceContext.generatePassword();
- } else {
- password = user.getPassword();
- }
-
- // encode the password
- String encodedPassword = serviceContext.encodePassword(password);
-
- toCreate.setLogin(user.getLogin());
- toCreate.setEmailActivationToken(emailValidationToken);
- toCreate.setPassword(encodedPassword);
-
- copyPollenUser(user, toCreate, true);
-
- dao.persist(toCreate);
- getPersistenceContext().commit();
-
- notifyUserCreated(toCreate);
-
- return toCreate;
- }
-
- public PollenUser editUser(PollenUser user) throws UserInvalidPasswordException, UserEmailAlreadyUsedException, EntityNotFoundException {
- Preconditions.checkNotNull(user);
- checkHasId(user);
-
- PollenUser persisted = getUser(user.getId());
-
- PollenUserJpaDao dao = getPollenUserDao();
-
- // check current password
- String encodedPassword = serviceContext.encodePassword(user.getPassword());
- if (!encodedPassword.equals(persisted.getPassword())) {
- throw new UserInvalidPasswordException();
- }
-
- boolean emailChanged = ObjectUtils.notEqual(persisted.getEmail(),
- user.getEmail());
-
- if (emailChanged) {
-
- // check this email is not used by another user
- boolean emailUsed = dao.emailExists(user.getEmail());
- if (emailUsed) {
- throw new UserEmailAlreadyUsedException(user.getEmail());
- }
-
- // add a new emailValidationtoken
- String emailValidationToken = generateToken();
- persisted.setEmailActivationToken(emailValidationToken);
- }
-
- copyPollenUser(user, persisted, true);
-
- persisted = dao.merge(persisted);
- getPersistenceContext().commit();
-
- if (emailChanged) {
-
- notifyEmailChanged(persisted);
- }
- return persisted;
- }
-
- public void changePassword(String userId,
- String oldPassword,
- String newPassword) throws UserInvalidPasswordException, EntityNotFoundException {
- Preconditions.checkNotNull(userId);
- Preconditions.checkNotNull(oldPassword);
- Preconditions.checkNotNull(newPassword);
-
- PollenUser user = getUser(userId);
-
- // check current password
- String encodedPassword = serviceContext.encodePassword(user.getPassword());
- if (!encodedPassword.equals(user.getPassword())) {
- throw new UserInvalidPasswordException();
- }
-
- // encode new password and store it in user account
- String newEncodedPassword = serviceContext.encodePassword(newPassword);
- user.setPassword(newEncodedPassword);
-
- user = getPollenUserDao().merge(user);
- getPersistenceContext().commit();
-
- notifyPasswordChanged(user);
- }
-
- public void validateUserEmail(String userId,
- String token) throws EntityNotFoundException, UserInvalidEmailActiviationTokenException {
-
- Preconditions.checkNotNull(userId);
- Preconditions.checkNotNull(token);
-
- PollenUser user = getUser(userId);
-
- Preconditions.checkNotNull(user);
-
- boolean valid = ObjectUtils.equals(
- user.getEmailActivationToken(), token);
-
- if (!valid) {
- throw new UserInvalidEmailActiviationTokenException();
- }
-
- // reset token in database
- user.setEmailActivationToken(null);
-
- getPollenUserDao().merge(user);
- getPersistenceContext().commit();
- }
-
- public void createDefaultUsers() throws UserEmailAlreadyUsedException, UserLoginAlreadyUsedException {
-
- PollenUser user = getPollenUserDao().newInstance();
-
- user.setAdministrator(true);
- String login = "admin";
- user.setLogin(login);
- user.setEmail("admin(a)pollen.org");
- user.setPassword("admin");
- createUser(user, false);
- }
-
- protected void notifyUserCreated(PollenUser user) {
-
- //TODO
- }
-
- protected void notifyEmailChanged(PollenUser user) {
-
- //TODO
- }
-
- protected void notifyPasswordChanged(PollenUser user) {
-
- //TODO
- }
-
- protected PollenUserJpaDao getPollenUserDao() {
- return getPersistenceContext().getPollenUserDao();
- }
-
- /**
- * Copy {@code source} user account to {@code destination} one.
- * The email is lower cased in the {@code destination} user account.
- *
- * @param source user account to copy
- * @param destination which receive the copy
- */
- protected void copyPollenUser(PollenUser source,
- PollenUser destination,
- boolean copyEmail) {
-
- destination.setAdministrator(source.isAdministrator());
- destination.setName(source.getName());
- destination.setLanguage(source.getLanguage());
-
- if (copyEmail) {
- // Don't keep case for email
- destination.setEmail(StringUtils.lowerCase(source.getEmail()));
- }
- }
-}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoteService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -24,10 +24,15 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import org.chorem.pollen.persistence.entity.Poll;
import org.chorem.pollen.persistence.entity.Vote;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidVoteFormException;
+import org.nuiton.jpa.api.JpaEntities;
+import java.util.Date;
import java.util.List;
/**
@@ -46,55 +51,124 @@
return result;
}
- public Vote getVote(String voteId) throws EntityNotFoundException{
+ public Vote getVote(String pollId, String voteId) throws EntityNotFoundException {
Preconditions.checkNotNull(voteId);
- Vote result = getPersistenceContext().getVoteDao().findById(voteId);
- checkEntityExists(Vote.class, result, voteId);
+ Poll poll = getPollService().getPoll(pollId);
+
+ Vote result = getVote(poll, voteId);
return result;
}
- public Vote addVote(String pollId, Vote vote)throws EntityNotFoundException {
+
+ public Vote addVote(String pollId, Vote vote) throws EntityNotFoundException, InvalidVoteFormException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(vote);
checkHasNoId(vote);
Poll poll = getPollService().getPoll(pollId);
+ checkVoteForm(poll, vote);
- poll.addVote(vote);
+ Vote result = saveVote(poll, vote);
+
getPersistenceContext().getPollDao().merge(poll);
-
getPersistenceContext().commit();
- Vote result = getVote(vote.getId());
+ //TODO Notify vote added
return result;
}
- public Vote editVote(Vote vote)throws EntityNotFoundException {
+ public Vote editVote(String pollId, Vote vote) throws EntityNotFoundException, InvalidVoteFormException {
Preconditions.checkNotNull(vote);
checkHasId(vote);
- getVote(vote.getId());
+ Poll poll = getPollService().getPoll(pollId);
+ checkVoteForm(poll, vote);
+ Vote result = saveVote(poll, vote);
+
getPersistenceContext().getVoteDao().merge(vote);
getPersistenceContext().commit();
-
- Vote result = getVote(vote.getId());
+ //TODO Notify vote edited
return result;
}
- public void deleteVote(String pollId, String voteId)throws EntityNotFoundException {
+ public void deleteVote(String pollId, String voteId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voteId);
Poll poll = getPollService().getPoll(pollId);
- Vote vote = getVote(voteId);
+ Vote vote = getVote(poll, voteId);
poll.removeVote(vote);
getPersistenceContext().getPollDao().merge(poll);
-
getPersistenceContext().commit();
+ //TODO Notify vote deleted
}
+ protected void checkVoteForm(Poll poll, Vote vote) throws InvalidVoteFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ // poll can't be closed
+ checkNot(errors, "poll", poll.isClosed(), "poll can not be closed");
+
+ Date now = serviceContext.getNow();
+
+ // poll must be started
+ check(errors, "poll", poll.isStarted(now), "poll is not stardted");
+
+ checkNotBlank(errors, "voter.name", vote.getVoter().getName(), "voter name can not be empty");
+
+ //TODO Finish validation
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidVoteFormException(errors);
+ }
+ }
+
+ protected Vote saveVote(Poll poll, Vote vote) throws EntityNotFoundException {
+
+ boolean commentExists = JpaEntities.isEntityHasId(vote);
+
+ Vote toSave;
+
+ if (commentExists) {
+
+ toSave = getVote(poll, vote.getId());
+ } else {
+
+ toSave = getPersistenceContext().getVoteDao().newInstance();
+// toSave.setPostDate(serviceContext.getNow());
+
+ // -- author -- //
+
+// PollenPrincipal author = getSecurityService().generatePrincipal();
+// toSave.setAuthor(author);
+
+ poll.addVote(toSave);
+ }
+
+// toSave.setText(vote.getText());
+//
+// // -- author -- //
+//
+// toSave.getAuthor().setName(vote.getAuthor().getName());
+// if (StringUtils.isNotBlank(vote.getAuthor().getEmail())) {
+// toSave.getAuthor().setEmail(StringUtils.lowerCase(vote.getAuthor().getEmail()));
+// }
+
+ return toSave;
+ }
+
+ protected Vote getVote(Poll poll, String voteId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(voteId);
+
+ Vote result = poll.getVoteById(voteId);
+ checkEntityExists(Vote.class, result, voteId);
+ return result;
+ }
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -28,7 +28,6 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
-import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.dao.VoterListJpaDao;
import org.chorem.pollen.persistence.dao.VoterListMemberJpaDao;
import org.chorem.pollen.persistence.entity.FavoriteList;
@@ -37,7 +36,6 @@
import org.chorem.pollen.persistence.entity.VoterList;
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidVoterListFormException;
import org.chorem.pollen.services.exception.InvalidVoterListMemberFormException;
import org.nuiton.jpa.api.JpaEntities;
@@ -54,7 +52,7 @@
public class VoterListService extends AbstractPollenService {
public VoterList importFavoriteList(String userId, String pollId,
- String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ String favoriteListId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(favoriteListId);
@@ -171,7 +169,7 @@
return result;
}
- public VoterListMember addVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ public VoterListMember addVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException, InvalidVoterListMemberFormException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
@@ -179,6 +177,8 @@
VoterList voterList = getVoterList(pollId, voterListId);
+ checkVoterListMember(voterList, member);
+
VoterListMember result = saveVoterListMember(voterList, member);
getPersistenceContext().getVoterListDao().merge(voterList);
@@ -187,7 +187,7 @@
}
- public VoterListMember editVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ public VoterListMember editVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException, InvalidVoterListMemberFormException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
@@ -195,6 +195,8 @@
VoterList voterList = getVoterList(pollId, voterListId);
+ checkVoterListMember(voterList, member);
+
VoterListMember result = saveVoterListMember(voterList, member);
getPersistenceContext().getVoterListMemberDao().merge(member);
@@ -283,7 +285,7 @@
}
toSave.setName(voterListMember.getName());
- toSave.setEmail(StringUtils.lowerCase(voterListMember.getEmail()));
+ toSave.setEmail(getCleanMail(voterListMember.getEmail()));
toSave.setWeight(voterListMember.getWeight());
return toSave;
@@ -330,21 +332,19 @@
String voterListMemberField = "member[" + (voterListMemberIndex++) + "].";
String voterListMemberName = voterListMember.getName();
- boolean nameNotNull = checkNotBlank(errors, voterListMemberField + "name", voterListMemberName, "member name can not be empty");
+ boolean nameNotBlank = checkNotBlank(errors, voterListMemberField + "name", voterListMemberName, "member name can not be empty");
- if (nameNotNull) {
+ if (nameNotBlank) {
boolean nameAdded = voterListMemberNames.add(voterListMemberName);
check(errors, voterListMemberField + "name", nameAdded, "member name already used in this list");
}
- String voterListMemberEmail = voterListMember.getEmail();
+ String voterListMemberEmail = getCleanMail(voterListMember.getEmail());
- boolean emailNotNull = checkNotBlank(errors, voterListMemberField + "email", voterListMemberEmail, "member email can not be empty");
+ boolean emailNotBlank = checkNotBlank(errors, voterListMemberField + "email", voterListMemberEmail, "member email can not be empty");
- if (emailNotNull) {
+ if (emailNotBlank) {
- voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
-
checkValidEmail(errors, voterListMemberField + "email", voterListMemberEmail, "member email is not valid");
boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
check(errors, voterListMemberField + "email", emailAdded, "member email already used in this list");
@@ -372,7 +372,8 @@
for (VoterListMember member : voterList.getVoterListMember()) {
- if (voterListMemberExists && member.getId().equals(voterListMember.getId())) {
+ if (voterListMemberExists &&
+ member.getId().equals(voterListMember.getId())) {
continue;
}
@@ -381,21 +382,19 @@
}
}
String voterListMemberName = voterListMember.getName();
- boolean nameNotNull = checkNotBlank(errors, "name", voterListMemberName, "member name can not be empty");
+ boolean nameNotblank = checkNotBlank(errors, "name", voterListMemberName, "member name can not be empty");
- if (nameNotNull) {
+ if (nameNotblank) {
boolean nameAdded = voterListMemberNames.add(voterListMemberName);
check(errors, "name", nameAdded, "member name already used in this list");
}
- String voterListMemberEmail = voterListMember.getEmail();
+ String voterListMemberEmail = getCleanMail(voterListMember.getEmail());
- boolean emailNotNull = checkNotBlank(errors, "email", voterListMemberEmail, "member email can not be empty");
+ boolean emailNotBlank = checkNotBlank(errors, "email", voterListMemberEmail, "member email can not be empty");
- if (emailNotNull) {
+ if (emailNotBlank) {
- voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
-
checkValidEmail(errors, "email", voterListMemberEmail, "member email is not valid");
boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
check(errors, "email", emailAdded, "member email already used in this list");
Copied: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java (from rev 3833, trunk/pollen-services/src/test/java/org/chorem/pollen/service/UserServiceTest.java)
===================================================================
--- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java (rev 0)
+++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollenUserServiceTest.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -0,0 +1,203 @@
+package org.chorem.pollen.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.commons.collections.CollectionUtils;
+import org.chorem.pollen.persistence.entity.PollenUser;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollenUserFormException;
+import org.chorem.pollen.services.exception.UserInvalidEmailActivationTokenException;
+import org.chorem.pollen.services.service.PollenUserService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenUserServiceTest extends AbstractPollenServiceTest {
+
+ protected PollenUserService service;
+
+ protected PollenUser user;
+
+ @Before
+ public void setUp() throws ParseException {
+
+ loadFixtures("fixtures");
+
+ service = serviceContext.getUserService();
+
+ serviceContext.setDate(new Date(1363948427576l));
+
+ user = fixture("tony");
+ }
+
+ @Test
+ public void testGetPollenUsers() {
+
+ List<PollenUser> users = service.getUsers();
+
+ Assert.assertNotNull(users);
+ Assert.assertTrue(CollectionUtils.isNotEmpty(users));
+ }
+
+ @Test
+ public void testGetPollenUser() throws EntityNotFoundException {
+
+ try {
+ service.getUser("pollen_user_tony_" + System.nanoTime());
+
+ } catch (EntityNotFoundException e) {
+ Assert.assertTrue(true);
+ }
+
+ PollenUser user = service.getUser(this.user.getId());
+
+ Assert.assertNotNull(user);
+ Assert.assertEquals(this.user, user);
+ }
+
+ @Test
+ public void testCreatePollenUser() throws Exception {
+
+ try {
+ service.createUser(user, false);
+ Assert.fail();
+ } catch (IllegalStateException e) {
+ // Should having id
+ Assert.assertTrue(true);
+ }
+
+ PollenUser newUser = new PollenUser();
+ newUser.setLogin("pollen");
+ newUser.setEmail("pollen(a)pollen.org");
+
+ PollenUser savedUser = service.createUser(newUser, true);
+ Assert.assertNotNull(savedUser);
+ Assert.assertNotNull(savedUser.getId());
+
+ PollenUser newUser2 = new PollenUser();
+ newUser2.setLogin("pollen");
+ newUser2.setEmail("pollen(a)pollen.org");
+
+ try {
+ service.createUser(newUser2, true);
+ Assert.fail();
+ } catch (InvalidPollenUserFormException e) {
+ // not available login
+ // not available email
+ assertErrorKeyFound(e, "login", "email");
+ }
+
+ newUser2.setLogin("pollen2");
+ try {
+ service.createUser(newUser2, true);
+ Assert.fail();
+ } catch (InvalidPollenUserFormException e) {
+ // not available email
+ assertErrorKeyFound(e, "email");
+ }
+
+ newUser2.setEmail("pollen2(a)pollen.org");
+ PollenUser savedUser2 = service.createUser(newUser2, true);
+ Assert.assertNotNull(savedUser2);
+ Assert.assertNotNull(savedUser2.getId());
+ }
+
+ @Test
+ public void testEditUser() throws EntityNotFoundException, InvalidPollenUserFormException {
+
+ PollenUser user = service.getUser(this.user.getId());
+
+ Assert.assertNotNull(user);
+ Assert.assertNull(user.getEmailActivationToken());
+
+ serviceContext.getPersistenceContext().detach(user);
+
+ String originalLogin = user.getLogin();
+
+ user.setLogin("yetanotherlogin");
+ String email = "tony(a)pollen.org";
+ user.setEmail(email);
+
+ try {
+ service.editUser(user);
+ Assert.fail();
+ } catch (InvalidPollenUserFormException e) {
+ // invalid password
+ assertErrorKeyFound(e, "password");
+ }
+
+ user.setPassword("fake");
+ PollenUser savedUser = service.editUser(user);
+ Assert.assertNotNull(savedUser);
+ Assert.assertEquals(originalLogin, savedUser.getLogin());
+ Assert.assertEquals(email, savedUser.getEmail());
+ Assert.assertNotNull(savedUser.getEmailActivationToken());
+ }
+
+ @Test
+ public void testValidateEmail() throws EntityNotFoundException, UserInvalidEmailActivationTokenException, InvalidPollenUserFormException {
+
+ PollenUser user = service.getUser(this.user.getId());
+ Assert.assertNotNull(user);
+ Assert.assertNull(user.getEmailActivationToken());
+
+ serviceContext.getPersistenceContext().detach(user);
+
+ String email = "tony(a)pollen.org";
+ user.setEmail(email);
+ user.setPassword("fake");
+
+ PollenUser savedUser = service.editUser(user);
+ Assert.assertNotNull(savedUser);
+
+ Assert.assertEquals(email, savedUser.getEmail());
+ Assert.assertNotNull(savedUser.getEmailActivationToken());
+
+ try {
+ service.validateUserEmail(user.getId(), "fakeToken");
+ Assert.fail();
+ } catch (UserInvalidEmailActivationTokenException e) {
+ Assert.assertTrue(true);
+ }
+
+ Assert.assertFalse(savedUser.isEmailActivated());
+
+ service.validateUserEmail(user.getId(), savedUser.getEmailActivationToken());
+
+
+ PollenUser reloadedUser = service.getUser(this.user.getId());
+ Assert.assertTrue(reloadedUser.isEmailActivated());
+
+ }
+}
Deleted: trunk/pollen-services/src/test/java/org/chorem/pollen/service/UserServiceTest.java
===================================================================
--- trunk/pollen-services/src/test/java/org/chorem/pollen/service/UserServiceTest.java 2013-06-17 16:40:14 UTC (rev 3833)
+++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/UserServiceTest.java 2013-06-18 06:22:46 UTC (rev 3834)
@@ -1,202 +0,0 @@
-package org.chorem.pollen.service;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.apache.commons.collections.CollectionUtils;
-import org.chorem.pollen.persistence.entity.PollenUser;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserInvalidEmailActiviationTokenException;
-import org.chorem.pollen.services.exception.UserInvalidPasswordException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
-import org.chorem.pollen.services.service.UserService;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.text.ParseException;
-import java.util.Date;
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserServiceTest extends AbstractPollenServiceTest {
-
- protected UserService service;
-
- protected PollenUser user;
-
- @Before
- public void setUp() throws ParseException {
-
- loadFixtures("fixtures");
-
- service = serviceContext.getUserService();
-
- serviceContext.setDate(new Date(1363948427576l));
-
- user = fixture("tony");
- }
-
- @Test
- public void testGetPollenUsers() {
-
- List<PollenUser> users = service.getUsers();
-
- Assert.assertNotNull(users);
- Assert.assertTrue(CollectionUtils.isNotEmpty(users));
- }
-
- @Test
- public void testGetPollenUser() throws EntityNotFoundException {
-
- try {
- service.getUser("pollen_user_tony_" + System.nanoTime());
-
- } catch (EntityNotFoundException e) {
- Assert.assertTrue(true);
- }
-
- PollenUser user = service.getUser(this.user.getId());
-
- Assert.assertNotNull(user);
- Assert.assertEquals(this.user, user);
- }
-
- @Test
- public void testCreatePollenUser() throws Exception {
-
- try {
- service.createUser(user, false);
- Assert.fail();
- } catch (IllegalStateException e) {
- // Should having id
- Assert.assertTrue(true);
- }
-
- PollenUser newUser = new PollenUser();
- newUser.setLogin("pollen");
- newUser.setEmail("pollen(a)pollen.org");
-
- PollenUser savedUser = service.createUser(newUser, true);
- Assert.assertNotNull(savedUser);
- Assert.assertNotNull(savedUser.getId());
-
- PollenUser newUser2 = new PollenUser();
- newUser2.setLogin("pollen");
- newUser2.setEmail("pollen(a)pollen.org");
-
- try {
- service.createUser(newUser2, true);
- Assert.fail();
- } catch (UserLoginAlreadyUsedException e) {
- Assert.assertTrue(true);
- }
-
- newUser2.setLogin("pollen2");
- try {
- service.createUser(newUser2, true);
- Assert.fail();
- } catch (UserEmailAlreadyUsedException e) {
- Assert.assertTrue(true);
- }
-
- newUser2.setEmail("pollen2(a)pollen.org");
- PollenUser savedUser2 = service.createUser(newUser2, true);
- Assert.assertNotNull(savedUser2);
- Assert.assertNotNull(savedUser2.getId());
- }
-
- @Test
- public void testEditUser() throws EntityNotFoundException, UserInvalidPasswordException, UserEmailAlreadyUsedException {
-
- PollenUser user = service.getUser(this.user.getId());
-
- Assert.assertNotNull(user);
- Assert.assertNull(user.getEmailActivationToken());
-
- serviceContext.getPersistenceContext().detach(user);
-
- String originalLogin = user.getLogin();
-
- user.setLogin("yetanotherlogin");
- String email = "tony(a)pollen.org";
- user.setEmail(email);
-
- try {
- service.editUser(user);
- Assert.fail();
- } catch (UserInvalidPasswordException e) {
- Assert.assertTrue(true);
- }
-
- user.setPassword("fake");
- PollenUser savedUser = service.editUser(user);
- Assert.assertNotNull(savedUser);
- Assert.assertEquals(originalLogin, savedUser.getLogin());
- Assert.assertEquals(email, savedUser.getEmail());
- Assert.assertNotNull(savedUser.getEmailActivationToken());
- }
-
- @Test
- public void testValidateEmail() throws EntityNotFoundException, UserInvalidPasswordException, UserEmailAlreadyUsedException, UserInvalidEmailActiviationTokenException {
-
- PollenUser user = service.getUser(this.user.getId());
- Assert.assertNotNull(user);
- Assert.assertNull(user.getEmailActivationToken());
-
- serviceContext.getPersistenceContext().detach(user);
-
- String email = "tony(a)pollen.org";
- user.setEmail(email);
- user.setPassword("fake");
-
- PollenUser savedUser = service.editUser(user);
- Assert.assertNotNull(savedUser);
-
- Assert.assertEquals(email, savedUser.getEmail());
- Assert.assertNotNull(savedUser.getEmailActivationToken());
-
- try {
- service.validateUserEmail(user.getId(), "fakeToken");
- Assert.fail();
- } catch (UserInvalidEmailActiviationTokenException e) {
- Assert.assertTrue(true);
- }
-
- Assert.assertFalse(savedUser.isEmailActivated());
-
- service.validateUserEmail(user.getId(), savedUser.getEmailActivationToken());
-
-
-
- PollenUser reloadedUser = service.getUser(this.user.getId());
- Assert.assertTrue(reloadedUser.isEmailActivated());
-
- }
-}
Property changes on: trunk/pollen-ui-js/pom.xml
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Property changes on: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Property changes on: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
1
0
r3833 - in trunk: . pollen-ui-js pollen-ui-js/src/main pollen-ui-js/src/main/resources pollen-ui-js/src/main/resources/nuiton-js pollen-ui-js/src/main/webapp pollen-ui-js/src/main/webapp/img pollen-ui-js/src/main/webapp/views
by kmorin@users.chorem.org 17 Jun '13
by kmorin@users.chorem.org 17 Jun '13
17 Jun '13
Author: kmorin
Date: 2013-06-17 18:40:14 +0200 (Mon, 17 Jun 2013)
New Revision: 3833
Url: http://chorem.org/projects/pollen/repository/revisions/3833
Log:
start using nuiton-js to handle js libs
Added:
trunk/pollen-ui-js/LICENSE.txt
trunk/pollen-ui-js/README.txt
trunk/pollen-ui-js/changelog.txt
trunk/pollen-ui-js/pom.xml
trunk/pollen-ui-js/src/main/resources/
trunk/pollen-ui-js/src/main/resources/nuiton-js/
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties
trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
Removed:
trunk/pollen-ui-js/src/main/webapp/img/glyphicons-halflings-white.png
trunk/pollen-ui-js/src/main/webapp/img/glyphicons-halflings.png
Modified:
trunk/pollen-ui-js/
trunk/pollen-ui-js/src/main/webapp/index.html
trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
trunk/pom.xml
Property changes on: trunk/pollen-ui-js
___________________________________________________________________
Added: svn:ignore
+ *.iml
Copied: trunk/pollen-ui-js/LICENSE.txt (from rev 3827, trunk/LICENSE.txt)
===================================================================
--- trunk/pollen-ui-js/LICENSE.txt (rev 0)
+++ trunk/pollen-ui-js/LICENSE.txt 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,661 @@
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU Affero General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU Affero General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU Affero General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU Affero General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU AGPL, see
+<http://www.gnu.org/licenses/>.
\ No newline at end of file
Copied: trunk/pollen-ui-js/README.txt (from rev 3827, trunk/README.txt)
===================================================================
--- trunk/pollen-ui-js/README.txt (rev 0)
+++ trunk/pollen-ui-js/README.txt 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,58 @@
+POLLEN
+------
+
+Pollen est une application Web de sondages en ligne qui permet de créer et de
+gérer des sondages avec différents types de choix (texte, date, image).
+Les votants peuvent participer au sondage en suivant un lien qui identifie le
+sondage.
+
+
+INSTALLATION
+------------
+
+Pour installer l'application il suffit de déployer l'archive war dans un
+conteneur Web comme Tomcat.
+
+Par défaut une base de données H2 est créée dans le répertoire /tmp.
+Pour modifier ce comportement par défaut il suffit de créer le fichier
+/etc/pollen.properties et de le remplir avec les propriétés suivantes :
+
+ # Configuration de la base de données
+ hibernate.show_sql=false
+ hibernate.dialect=org.hibernate.dialect.H2Dialect
+ hibernate.connection.username=username
+ hibernate.connection.password=password
+ hibernate.connection.driver_class=org.h2.Driver
+ hibernate.connection.url=jdbc:h2:file://tmp/pollen/pollen
+
+ # Répertoire des images transférées
+ upImgDir=/tmp/pollen/uploadedImages
+
+ # Taille maximal des images transférées (en octets)
+ upload.filesize-max=1048576
+ upload.requestsize-max=10485760
+
+ # Configuration de l'envoi d'emails automatiques
+ email_host=smtp.free.fr
+ email_port=25
+ email_from=bot(a)pollen.org
+
+ # Répertoire des flux de syndication (Atom)
+ feedDir=/tmp/pollen/feeds
+
+ # Adresse du site (utilisée pour les emails de rappel)
+ siteUrl=http://www.site.org/pollen/
+
+Pour une base PostgreSQL on aura :
+
+ hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+ hibernate.connection.driver_class=org.postgresql.Driver
+ hibernate.default_schema=public
+
+Il peut-être nécessaire de redéployer l'application après avoir modifié ce
+fichier.
+
+Un utilisateur avec les droits d'administration est créé automatiquement
+(identifiant "admin", mot de passe "pollen"). Par mesure de sécurité il est
+important de supprimer cet utilisateur après avoir créer un autre compte
+administrateur.
Copied: trunk/pollen-ui-js/changelog.txt (from rev 3827, trunk/changelog.txt)
===================================================================
--- trunk/pollen-ui-js/changelog.txt (rev 0)
+++ trunk/pollen-ui-js/changelog.txt 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,40 @@
+ChangeLog
+=========
+1.2.3
+- Anomalie #101: Sondage à type de dépouillement: Number
+
+1.2.2
+- Rename favicon to favicon.png
+- Use war launcher from nuiton-utils project
+- Evolution #96: Nouveau type de consultation: un nombre
+
+1.2.1
+- Erreur lors de la modification de son vote Issue: 87
+
+1.2.0
+- Fixed a performance problem in the file upload with Winstone.
+- Global dependencies update
+- Use hudson version of winstone web server (original seam unmaintained)
+- Fix slf4j dependency bug between api & impl
+- Evol #54
+- Ano #49
+
+1.1.0
+- liste de votants à partir d'un serveur ldap
+- export de sondage
+- flux de syndication atom
+- création d'un sondage par copie d'un ancien
+- sondages par groupes
+- administration des sondages et des utilisateurs
+- suppression de choix, de votes et de commentaires
+- liste des sondages auxquels l'utilisateur a participé
+- URL forgée pour les votes restreints
+
+1.0.1
+- refonte de la création de sondage
+- sondages restreints
+- listes de votants
+- service de migration
+
+1.0.0
+- initiale release
Added: trunk/pollen-ui-js/pom.xml
===================================================================
--- trunk/pollen-ui-js/pom.xml (rev 0)
+++ trunk/pollen-ui-js/pom.xml 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <!-- ************************************************************* -->
+ <!-- *** POM Relationships *************************************** -->
+ <!-- ************************************************************* -->
+
+ <parent>
+ <groupId>org.chorem</groupId>
+ <artifactId>pollen</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ </parent>
+
+ <!-- ************************************************************* -->
+ <!-- *** Project Information ************************************* -->
+ <!-- ************************************************************* -->
+
+ <name>Pollen :: UI (JS) </name>
+ <description>Pollen UI</description>
+
+ <groupId>org.chorem.pollen</groupId>
+ <artifactId>pollen-ui-js</artifactId>
+ <packaging>pom</packaging>
+
+ <!-- ************************************************************* -->
+ <!-- *** Build Environment ************************************** -->
+ <!-- ************************************************************* -->
+
+ <build>
+
+ <plugins>
+
+ <plugin>
+ <groupId>ro.isdc.wro4j</groupId>
+ <artifactId>wro4j-maven-plugin</artifactId>
+ <version>1.7.0</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-wro</artifactId>
+ <version>1.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-jquery</artifactId>
+ <version>1.9.1-2</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-bootstrap</artifactId>
+ <version>2.3.2-1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.nuiton.js</groupId>
+ <artifactId>nuiton-js-canjs</artifactId>
+ <version>1.1.6-1</version>
+ </dependency>
+
+ </dependencies>
+
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ <configuration>
+ <targetGroups>pollen-ui-js</targetGroups>
+ <minimize>true</minimize>
+ <wroFile>${basedir}/src/main/resources/nuiton-js/wro.xml</wroFile>
+ <extraConfigFile>${basedir}/src/main/resources/nuiton-js/wro.properties</extraConfigFile>
+ <contextFolder>${basedir}/src/main/webapp/</contextFolder>
+ <destinationFolder>${basedir}/src/main/webapp/</destinationFolder>
+ <wroManagerFactory>org.nuiton.js.wro.NuitonJsMavenWroManagerFactory</wroManagerFactory>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
+</project>
Added: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties
===================================================================
--- trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties (rev 0)
+++ trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.properties 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,4 @@
+debug=false
+preProcessors=forceCssDataUri,cssUrlRewriting,cssImport,semicolonAppender,cssMinJawr
+postProcessors=cssVariables,jsMin
+uriLocators=uri,classpath
\ No newline at end of file
Added: trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml
===================================================================
--- trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml (rev 0)
+++ trunk/pollen-ui-js/src/main/resources/nuiton-js/wro.xml 2013-06-17 16:40:14 UTC (rev 3833)
@@ -0,0 +1,17 @@
+<groups xmlns="http://www.isdc.ro/wro">
+
+ <group name='pollen-ui-js'>
+ <group-ref>jquery</group-ref>
+ <group-ref>bootstrap-responsive</group-ref>
+ <group-ref>can.jquery</group-ref>
+ <group-ref>can.object</group-ref>
+ <group-ref>can.fixture</group-ref>
+ <group-ref>can.observe.attributes</group-ref>
+ <group-ref>can.observe.delegate</group-ref>
+
+ <!-- scpecifique nuiton profiling -->
+ <!--<css>/nuiton-profiling.css</css>-->
+ <!--<js>/nuiton-profiling.js</js>-->
+ </group>
+
+</groups>
Deleted: trunk/pollen-ui-js/src/main/webapp/img/glyphicons-halflings-white.png
===================================================================
(Binary files differ)
Deleted: trunk/pollen-ui-js/src/main/webapp/img/glyphicons-halflings.png
===================================================================
(Binary files differ)
Modified: trunk/pollen-ui-js/src/main/webapp/index.html
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-17 15:36:31 UTC (rev 3832)
+++ trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-17 16:40:14 UTC (rev 3833)
@@ -1,15 +1,15 @@
<!DOCTYPE html>
-<html lang="fr">
+<html lang="fr" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<title>Pollen</title>
- <link rel="stylesheet" href="css/bootstrap.min.css">
- <link rel="stylesheet" href="css/style.css">
+ <link rel="stylesheet" href="pollen-ui-js.css"></link>
+ <link rel="stylesheet" href="css/style.css"></link>
</head>
<body>
- <div class="navbar navbar-inverse navbar navbar-static-top">
+ <div class="navbar navbar-inverse navbar-static-top">
<div class="navbar-inner">
<div class='container'>
<a class="brand" href="#">Pollen</a>
@@ -28,13 +28,7 @@
</div>
- <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.js"></script>
- <script src="js/libs/bootstrap.min.js"></script>
- <script src="js/libs/can.jquery.js"></script>
- <script src="js/libs/can.object.js"></script>
- <script src="js/libs/can.fixture.js"></script>
- <script src="js/libs/can.observe.attributes.js"></script>
- <script src="js/libs/can.observe.delegate.js"></script>
+ <script src="pollen-ui-js.js"></script>
<script src="js/libs/jquery.scrollto.js"></script>
<script src="js/libs/date.js"></script>
<script src="js/libs/jquery.i18n.properties-min-1.0.9.js"></script>
Modified: trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-17 15:36:31 UTC (rev 3832)
+++ trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-17 16:40:14 UTC (rev 3833)
@@ -1,2 +1,7 @@
<li><%== can.route.link(pollen.menu.home, {}) %></li>
-<li><%== can.route.link(pollen.menu.polls, { type: 'poll', action: 'edit' }) %></li>
\ No newline at end of file
+<li class="dropdown">
+ <a href="#" role="button" class="dropdown-toggle" data-toggle="dropdown"><%= pollen.menu.polls %> <b class="caret"></b></a>
+ <ul class="dropdown-menu" role="menu">
+ <li role="presentation"><%== can.route.link(pollen.menu.polls, { type: 'poll', action: 'edit' }, { role: 'menuitem', tabIndex: "-1" }, false) %></li>
+ </ul>
+</li>
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-17 15:36:31 UTC (rev 3832)
+++ trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-17 16:40:14 UTC (rev 3833)
@@ -49,10 +49,24 @@
</button>
<!-- form to add a new choice to the poll -->
- <form id="addChoiceForm" class="collapse">
- <input type="text" name="name" placeholder="<%= pollen.choice.name.placeholder %>"/>
- <textarea name="description" placeholder="<%= pollen.choice.description.placeholder %>"></textarea>
- <button type="submit" class="btn btn-primary"><%= pollen.common.validate %></button>
+ <form id="addChoiceForm" class="collapse form-horizontal">
+ <div class="control-group">
+ <label class="control-label" ><%= pollen.choice.name.placeholder %></label>
+ <div class="controls">
+ <input type="text" name="name" placeholder="<%= pollen.choice.name.placeholder %>"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" ><%= pollen.choice.description.placeholder %></label>
+ <div class="controls">
+ <textarea name="description" placeholder="<%= pollen.choice.description.placeholder %>"></textarea>
+ </div>
+ </div>
+ <div class="control-group">
+ <div class="controls">
+ <button type="submit" class="btn btn-primary"><%= pollen.common.validate %></button>
+ </div>
+ </div>
</form>
<% } %>
</div>
@@ -136,10 +150,24 @@
<%= pollen.vote.comments.list.button.addComment %> <i class="icon-collapse"></i>
</button>
- <form id="addCommentForm" class="collapse">
- <input type="text" name="author" placeholder="<%= pollen.vote.comments.add.field.userName.placeholder %>"/>
- <textarea name="message" placeholder="<%= pollen.vote.comments.add.field.message.placeholder %>"></textarea>
- <button type="submit" class="btn btn-primary">Valider</button>
+ <form id="addCommentForm" class="collapse form-horizontal">
+ <div class="control-group">
+ <label class="control-label" ><%= pollen.vote.comments.add.field.userName.placeholder %></label>
+ <div class="controls">
+ <input type="text" name="author" placeholder="<%= pollen.vote.comments.add.field.userName.placeholder %>"/>
+ </div>
+ </div>
+ <div class="control-group">
+ <label class="control-label" ><%= pollen.vote.comments.add.field.message.placeholder %></label>
+ <div class="controls">
+ <textarea name="message" placeholder="<%= pollen.vote.comments.add.field.message.placeholder %>"></textarea>
+ </div>
+ </div>
+ <div class="control-group">
+ <div class="controls">
+ <button type="submit" class="btn btn-primary"><%= pollen.common.validate %></button>
+ </div>
+ </div>
</form>
<div class='list alternate-colors'>
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2013-06-17 15:36:31 UTC (rev 3832)
+++ trunk/pom.xml 2013-06-17 16:40:14 UTC (rev 3833)
@@ -135,6 +135,7 @@
<module>pollen-persistence</module>
<module>pollen-services</module>
<module>pollen-rest-api</module>
+ <module>pollen-ui-js</module>
</modules>
<scm>
1
0
r3832 - in trunk: pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1 pollen-services/src/main/java/org/chorem/pollen/services/exception pollen-services/src/main/java/org/chorem/pollen/services/service
by tchemit@users.chorem.org 17 Jun '13
by tchemit@users.chorem.org 17 Jun '13
17 Jun '13
Author: tchemit
Date: 2013-06-17 17:36:31 +0200 (Mon, 17 Jun 2013)
New Revision: 3832
Url: http://chorem.org/projects/pollen/repository/revisions/3832
Log:
review favorite list service
Added:
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListMemberFormException.java
Removed:
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java
Modified:
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -28,11 +28,10 @@
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
import org.chorem.pollen.services.exception.FavoriteListImportException;
-import org.chorem.pollen.services.exception.FavoriteListMemberEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNameAlreadyUsedException;
import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
-import org.chorem.pollen.services.exception.FavoriteListNameAlreadyUsedException;
import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
+import org.chorem.pollen.services.exception.InvalidFavoriteListFormException;
+import org.chorem.pollen.services.exception.InvalidFavoriteListMemberFormException;
import org.debux.webmotion.server.WebMotionController;
import java.io.File;
@@ -52,15 +51,15 @@
return favoriteLists;
}
- public FavoriteList getFavoriteList(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
- return context.getFavoriteListService().getFavoriteList(favoriteListId);
+ public FavoriteList getFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().getFavoriteList(userId, favoriteListId);
}
- public FavoriteList createFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException {
+ public FavoriteList createFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException {
return context.getFavoriteListService().createFavoriteList(userId, favoriteList);
}
- public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException, FavoriteListNotOwnedByUserException {
+ public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNotOwnedByUserException, InvalidFavoriteListFormException {
return context.getFavoriteListService().editFavoriteList(userId, favoriteList);
}
@@ -76,24 +75,24 @@
return context.getFavoriteListService().importFavoriteListMembersFromLdap(userId, favoriteListId, ldap);
}
- public List<FavoriteListMember> getMembers(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
- List<FavoriteListMember> members = context.getFavoriteListService().getFavoriteListMembers(favoriteListId);
+ public List<FavoriteListMember> getMembers(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ List<FavoriteListMember> members = context.getFavoriteListService().getFavoriteListMembers(userId, favoriteListId);
return members;
}
- public FavoriteListMember getMember(PollenServiceContext context, String memberId) throws EntityNotFoundException {
- return context.getFavoriteListService().getFavoriteListMember(memberId);
+ public FavoriteListMember getMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().getFavoriteListMember(userId, favoriteListId, memberId);
}
- public FavoriteListMember addMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException {
- return context.getFavoriteListService().addFavoriteListMember(favoriteListId, member);
+ public FavoriteListMember addMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().addFavoriteListMember(userId, favoriteListId, member);
}
- public FavoriteListMember editMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException, FavoriteListMemberNotOwnedByFavoriteListException {
- return context.getFavoriteListService().editFavoriteListMember(favoriteListId, member);
+ public FavoriteListMember editMember(PollenServiceContext context, String userId, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().editFavoriteListMember(userId, favoriteListId, member);
}
- public void removeMember(PollenServiceContext context, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
- context.getFavoriteListService().removeFavoriteListMember(favoriteListId, memberId);
+ public void removeMember(PollenServiceContext context, String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ context.getFavoriteListService().removeFavoriteListMember(userId, favoriteListId, memberId);
}
}
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -27,6 +27,7 @@
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidVoterListFormException;
import org.debux.webmotion.server.WebMotionController;
@@ -41,8 +42,8 @@
*/
public class VoterListService extends WebMotionController {
- public VoterList importFavoriteList(PollenServiceContext context, String pollId, String favoriteListId) throws EntityNotFoundException {
- return context.getVoterListService().importFavoriteList(pollId, favoriteListId);
+ public VoterList importFavoriteList(PollenServiceContext context, String userId, String pollId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ return context.getVoterListService().importFavoriteList(userId, pollId, favoriteListId);
}
public List<VoterList> getVoterLists(PollenServiceContext context, String pollId) throws EntityNotFoundException {
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -1,45 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListMemberEmailAlreadyUsedException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- protected final String email;
-
- public FavoriteListMemberEmailAlreadyUsedException(String email) {
- this.email = email;
- }
-
- public String getEmail() {
- return email;
- }
-}
\ No newline at end of file
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -1,45 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListMemberNameAlreadyUsedException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- protected final String name;
-
- public FavoriteListMemberNameAlreadyUsedException(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-}
\ No newline at end of file
Deleted: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -1,45 +0,0 @@
-package org.chorem.pollen.services.exception;
-
-/*
- * #%L
- * Pollen :: Service
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListNameAlreadyUsedException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- protected final String name;
-
- public FavoriteListNameAlreadyUsedException(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-}
\ No newline at end of file
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListFormException.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -0,0 +1,41 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidFavoriteListFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidFavoriteListFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListMemberFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListMemberFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListMemberFormException.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -0,0 +1,41 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidFavoriteListMemberFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidFavoriteListMemberFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidFavoriteListMemberFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/FavoriteListService.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -24,9 +24,10 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.entity.FavoriteList;
import org.chorem.pollen.persistence.entity.FavoriteListMember;
@@ -34,11 +35,11 @@
import org.chorem.pollen.services.PollenTechnicalException;
import org.chorem.pollen.services.exception.EntityNotFoundException;
import org.chorem.pollen.services.exception.FavoriteListImportException;
-import org.chorem.pollen.services.exception.FavoriteListMemberEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNameAlreadyUsedException;
import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
-import org.chorem.pollen.services.exception.FavoriteListNameAlreadyUsedException;
import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
+import org.chorem.pollen.services.exception.InvalidFavoriteListFormException;
+import org.chorem.pollen.services.exception.InvalidFavoriteListMemberFormException;
+import org.nuiton.jpa.api.JpaEntities;
import org.nuiton.util.StringUtil;
import javax.naming.NamingEnumeration;
@@ -76,41 +77,26 @@
return result;
}
- public FavoriteList getFavoriteList(String favoriteListId) throws EntityNotFoundException {
+ public FavoriteList getFavoriteList(String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
- FavoriteList result = getPersistenceContext().getFavoriteListDao().findById(favoriteListId);
- checkEntityExists(FavoriteList.class, result, favoriteListId);
+
+ PollenUser user = getUserService().getUser(userId);
+
+ FavoriteList result = getFavoriteList(user, favoriteListId);
return result;
}
public FavoriteList createFavoriteList(String userId,
- FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException {
+ FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteList);
checkHasNoId(favoriteList);
- String favoriteListName = favoriteList.getName();
-
- // can't accept favorite list without name
- Preconditions.checkArgument(StringUtils.isNotEmpty(favoriteListName));
-
PollenUser user = getUserService().getUser(userId);
- // check there is not already a favorite list with same name
- boolean nameFound = false;
- if (!user.isFavoriteListEmpty()) {
- for (FavoriteList list : user.getFavoriteList()) {
- if (favoriteListName.equals(list.getName())) {
- nameFound = true;
- break;
- }
- }
- }
+ checkFavoriteListForm(user, favoriteList);
- if (nameFound) {
- throw new FavoriteListNameAlreadyUsedException(favoriteListName);
- }
-
FavoriteList toSave = getPersistenceContext().getFavoriteListDao().newInstance();
copyFavoriteList(favoriteList, toSave);
@@ -122,51 +108,22 @@
}
public FavoriteList editFavoriteList(String userId,
- FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException, FavoriteListNotOwnedByUserException {
+ FavoriteList favoriteList) throws EntityNotFoundException, InvalidFavoriteListFormException, FavoriteListNotOwnedByUserException {
Preconditions.checkNotNull(favoriteList);
checkHasId(favoriteList);
- String favoriteListName = favoriteList.getName();
-
- // can't accept favorite list without name
- Preconditions.checkArgument(StringUtils.isNotEmpty(favoriteListName));
-
// get user
PollenUser user = getUserService().getUser(userId);
- // get list
- FavoriteList toSave = getFavoriteList(favoriteList.getId());
+ // get list to save
+ FavoriteList toSave = getFavoriteList(user, favoriteList.getId());
- // check user own this list
- boolean ownedByUser = user.containsFavoriteListById(favoriteList.getId());
+ checkFavoriteListForm(user, favoriteList);
- if (!ownedByUser) {
- throw new FavoriteListNotOwnedByUserException();
- }
- if (ObjectUtils.notEqual(favoriteListName, toSave.getName())) {
+ copyFavoriteList(favoriteList, toSave);
- // check that this name is not existing in another list
- boolean nameFound = false;
- if (!user.isFavoriteListEmpty()) {
- for (FavoriteList list : user.getFavoriteList()) {
- if (toSave != list &&
- favoriteListName.equals(list.getName())) {
-
- // found another list with same name
- nameFound = true;
- break;
- }
- }
- }
- if (nameFound) {
- throw new FavoriteListNameAlreadyUsedException(favoriteListName);
- }
- }
-
- copyFavoriteList(favoriteList, toSave);
getPersistenceContext().getFavoriteListDao().merge(toSave);
-
getPersistenceContext().commit();
return toSave;
}
@@ -177,7 +134,7 @@
PollenUser user = getUserService().getUser(userId);
- FavoriteList persisted = getFavoriteList(favoriteListId);
+ FavoriteList persisted = getFavoriteList(user, favoriteListId);
// check user own this list
boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
@@ -186,62 +143,49 @@
}
user.removeFavoriteList(persisted);
+
getPersistenceContext().getPollenUserDao().merge(user);
-
getPersistenceContext().commit();
}
- public List<FavoriteListMember> getFavoriteListMembers(String favoriteListId) throws EntityNotFoundException {
+ public List<FavoriteListMember> getFavoriteListMembers(String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
+ PollenUser user = getUserService().getUser(userId);
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
+
return favoriteList.getFavoriteListMember();
}
- public FavoriteListMember getFavoriteListMember(String memberId) throws EntityNotFoundException {
+ public FavoriteListMember getFavoriteListMember(String userId, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
+ Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(memberId);
- FavoriteListMember result = getPersistenceContext().getFavoriteListMemberDao().findById(memberId);
- checkEntityExists(FavoriteListMember.class, result, memberId);
+
+ PollenUser user = getUserService().getUser(userId);
+
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
+
+ FavoriteListMember result = getFavoriteListMember(favoriteList, memberId);
return result;
}
- public FavoriteListMember addFavoriteListMember(String favoriteListId,
- FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNameAlreadyUsedException, FavoriteListMemberEmailAlreadyUsedException {
+ public FavoriteListMember addFavoriteListMember(String userId,
+ String favoriteListId,
+ FavoriteListMember member) throws EntityNotFoundException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(member);
checkHasNoId(member);
- // can't accept member without name
- String memberName = member.getName();
- Preconditions.checkArgument(StringUtils.isNotEmpty(memberName));
+ PollenUser user = getUserService().getUser(userId);
- // can't accept member without email
- String memberEmail = member.getEmail();
- Preconditions.checkArgument(StringUtils.isNotEmpty(memberEmail));
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
- // lowerCase email
- memberEmail = StringUtils.lowerCase(memberEmail);
+ checkFavoriteListMemberForm(favoriteList, member);
- //TODO Validate email form
-
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
-
- if (!favoriteList.isFavoriteListMemberEmpty()) {
-
- for (FavoriteListMember listMember : favoriteList.getFavoriteListMember()) {
-
- // check there is no other member with same name
- if (memberName.equals(listMember.getName())) {
- throw new FavoriteListMemberNameAlreadyUsedException(memberName);
- }
- // check there is no other member with same email
- if (memberEmail.equals(listMember.getEmail())) {
- throw new FavoriteListMemberEmailAlreadyUsedException(memberEmail);
- }
- }
- }
-
FavoriteListMember newMember =
getPersistenceContext().getFavoriteListMemberDao().newInstance();
copyFavoriteListMember(member, newMember);
@@ -253,60 +197,25 @@
return newMember;
}
- public FavoriteListMember editFavoriteListMember(String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListMemberNameAlreadyUsedException, FavoriteListMemberEmailAlreadyUsedException {
+ public FavoriteListMember editFavoriteListMember(String userId,
+ String favoriteListId,
+ FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, InvalidFavoriteListMemberFormException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
+ Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(member);
checkHasId(member);
- // can't accept member without name
- String memberName = member.getName();
- Preconditions.checkArgument(StringUtils.isNotEmpty(memberName));
- // can't accept member without email
- String memberEmail = member.getEmail();
- Preconditions.checkArgument(StringUtils.isNotEmpty(memberEmail));
+ PollenUser user = getUserService().getUser(userId);
- // lowerCase email
- memberEmail = StringUtils.lowerCase(memberEmail);
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
- //TODO Validate email form
-
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
-
String memberId = member.getId();
- FavoriteListMember toSave = getFavoriteListMember(memberId);
+ FavoriteListMember toSave = getFavoriteListMember(favoriteList, memberId);
- // check favorite list own this member
- boolean ownedByUser = favoriteList.containsFavoriteListMemberById(memberId);
- if (!ownedByUser) {
- throw new FavoriteListMemberNotOwnedByFavoriteListException();
- }
+ checkFavoriteListMemberForm(favoriteList, member);
-
- if (!memberName.equals(toSave.getName())) {
-
- // name has changed must check name is available in the list
- for (FavoriteListMember listMember : favoriteList.getFavoriteListMember()) {
-
- // check there is no other member with same name
- if (!memberId.equals(listMember.getId()) &&
- memberName.equals(listMember.getName())) {
- throw new FavoriteListMemberNameAlreadyUsedException(memberName);
- }
- }
- }
-
- if (!memberEmail.equals(toSave.getEmail())) {
-
- // email has changed must check name is available in the list
- for (FavoriteListMember listMember : favoriteList.getFavoriteListMember()) {
-
- if (!memberId.equals(listMember.getId()) &&
- memberEmail.equals(listMember.getEmail())) {
- throw new FavoriteListMemberEmailAlreadyUsedException(memberEmail);
- }
- }
- }
copyFavoriteListMember(member, toSave);
getPersistenceContext().getFavoriteListMemberDao().merge(toSave);
@@ -315,19 +224,18 @@
return toSave;
}
- public void removeFavoriteListMember(String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
+ public void removeFavoriteListMember(String userId,
+ String favoriteListId,
+ String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
Preconditions.checkNotNull(memberId);
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
+ PollenUser user = getUserService().getUser(userId);
- FavoriteListMember member = getFavoriteListMember(memberId);
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
- // check favorite list own this member
- boolean ownedByUser = favoriteList.containsFavoriteListMemberById(memberId);
- if (!ownedByUser) {
- throw new FavoriteListMemberNotOwnedByFavoriteListException();
- }
+ FavoriteListMember member = getFavoriteListMember(favoriteList, memberId);
favoriteList.removeFavoriteListMember(member);
@@ -335,7 +243,8 @@
getPersistenceContext().commit();
}
- public int importFavoriteListMembersFromCsv(String userId, String favoriteListId,
+ public int importFavoriteListMembersFromCsv(String userId,
+ String favoriteListId,
File file) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
Preconditions.checkNotNull(userId);
Preconditions.checkNotNull(favoriteListId);
@@ -343,14 +252,8 @@
PollenUser user = getUserService().getUser(userId);
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
- // check user own this list
- boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
- if (!ownedByUser) {
- throw new FavoriteListNotOwnedByUserException();
- }
-
Locale locale = serviceContext.getLocale();
Set<String> usedName = Sets.newHashSet();
@@ -447,14 +350,8 @@
PollenUser user = getUserService().getUser(userId);
- FavoriteList favoriteList = getFavoriteList(favoriteListId);
+ FavoriteList favoriteList = getFavoriteList(user, favoriteListId);
- // check user own this list
- boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
- if (!ownedByUser) {
- throw new FavoriteListNotOwnedByUserException();
- }
-
Locale locale = serviceContext.getLocale();
Set<String> usedName = Sets.newHashSet();
@@ -532,6 +429,34 @@
return result;
}
+ protected FavoriteList getFavoriteList(PollenUser user, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ Preconditions.checkNotNull(favoriteListId);
+
+ FavoriteList result = user.getFavoriteListById(favoriteListId);
+ checkEntityExists(FavoriteList.class, result, favoriteListId);
+
+ // check user own this list
+ boolean ownedByUser = user.containsFavoriteListById(favoriteListId);
+
+ if (!ownedByUser) {
+ throw new FavoriteListNotOwnedByUserException();
+ }
+ return result;
+ }
+
+ protected FavoriteListMember getFavoriteListMember(FavoriteList favoriteList, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
+
+ FavoriteListMember result = favoriteList.getFavoriteListMemberById(memberId);
+ checkEntityExists(FavoriteListMember.class, result, memberId);
+
+ // check favorite list own this member
+ boolean ownedByUser = favoriteList.containsFavoriteListMemberById(memberId);
+ if (!ownedByUser) {
+ throw new FavoriteListMemberNotOwnedByFavoriteListException();
+ }
+ return result;
+ }
+
protected void copyFavoriteList(FavoriteList source,
FavoriteList destination) {
@@ -544,4 +469,119 @@
destination.setName(source.getName());
destination.setEmail(StringUtils.lowerCase(source.getEmail()));
}
+
+ protected void checkFavoriteListForm(PollenUser user, FavoriteList favoriteList) throws InvalidFavoriteListFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ String favoriteListName = favoriteList.getName();
+
+ // can't accept favorite list without name
+ checkNotBlank(errors, "name", favoriteListName, "name can not be empty");
+
+
+ // check there is not already a favorite list with same name
+ boolean nameFound = false;
+ if (!user.isFavoriteListEmpty()) {
+ for (FavoriteList list : user.getFavoriteList()) {
+ if (favoriteListName.equals(list.getName())) {
+ nameFound = true;
+ break;
+ }
+ }
+ }
+
+ check(errors, "name", !nameFound, "name already used by another favorite list");
+
+ if (!favoriteList.isFavoriteListMemberEmpty()) {
+
+ int memberIndex = 0;
+
+ Set<String> memberNames = Sets.newHashSet();
+ Set<String> memberEmails = Sets.newHashSet();
+
+ for (FavoriteListMember member : favoriteList.getFavoriteListMember()) {
+
+ String choiceField = "favoriteListMember[" + (memberIndex++) + "].";
+
+ boolean notBlankName = checkNotBlank(errors, choiceField + "name", member.getName(), "member name can not be empty");
+ if (notBlankName) {
+ boolean added = memberNames.add(member.getName());
+
+ check(errors, choiceField + "name", added, "member name already used");
+ }
+
+ String memberEmail = member.getEmail();
+
+ boolean emailNotNull = checkNotBlank(errors, choiceField + "email", memberEmail, "member email can not be empty");
+
+ if (emailNotNull) {
+
+ memberEmail = StringUtils.lowerCase(memberEmail);
+
+ checkValidEmail(errors, choiceField + "email", memberEmail, "member email is not valid");
+ boolean emailAdded = memberEmails.add(memberEmail);
+ check(errors, choiceField + "email", emailAdded, "member email already used in this list");
+ }
+ }
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidFavoriteListFormException(errors);
+ }
+ }
+
+
+ protected void checkFavoriteListMemberForm(FavoriteList favoriteList, FavoriteListMember favoriteListMember) throws InvalidFavoriteListMemberFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ boolean voterListMemberExists = JpaEntities.isEntityHasId(favoriteListMember);
+
+ Set<String> memberNames = Sets.newHashSet();
+ Set<String> memberEmails = Sets.newHashSet();
+
+ if (!favoriteList.isFavoriteListMemberEmpty()) {
+
+ // get all used names
+
+ for (FavoriteListMember member : favoriteList.getFavoriteListMember()) {
+
+ if (voterListMemberExists && member.getId().equals(member.getId())) {
+ continue;
+ }
+
+ memberNames.add(member.getName());
+ memberEmails.add(member.getEmail());
+ }
+ }
+
+ boolean notBlankName = checkNotBlank(errors, "name", favoriteListMember.getName(), "member name can not be empty");
+ if (notBlankName) {
+ boolean added = memberNames.add(favoriteListMember.getName());
+
+ check(errors, "name", added, "member name already used");
+ }
+
+ String memberEmail = favoriteListMember.getEmail();
+
+ boolean emailNotNull = checkNotBlank(errors, "email", memberEmail, "member email can not be empty");
+
+ if (emailNotNull) {
+
+ memberEmail = StringUtils.lowerCase(memberEmail);
+
+ checkValidEmail(errors, "email", memberEmail, "member email is not valid");
+ boolean emailAdded = memberEmails.add(memberEmail);
+ check(errors, "email", emailAdded, "member email already used in this list");
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidFavoriteListMemberFormException(errors);
+ }
+ }
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -274,8 +274,10 @@
if (poll.isFreePoll()) {
checkEmpty(errors, "voterList", poll.getVoterList(), "can't have voterList with free poll");
- } else {
- checkNotEmpty(errors, "voterList", poll.getVoterList(), "must have voterList with not free poll");
+ } else if (poll.isRestrictedPoll()) {
+ check(errors, "voterList", 1 == poll.sizeVoterList(), "must have a unique voterList with a resitricted poll");
+ } else if (poll.isGroupPoll()) {
+ checkNotEmpty(errors, "voterList", poll.getVoterList(), "must have at least one voterList with a group poll");
}
if (!poll.isChoiceEmpty()) {
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-15 14:29:32 UTC (rev 3831)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-17 15:36:31 UTC (rev 3832)
@@ -37,6 +37,7 @@
import org.chorem.pollen.persistence.entity.VoterList;
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
import org.chorem.pollen.services.exception.InvalidVoterListFormException;
import org.chorem.pollen.services.exception.InvalidVoterListMemberFormException;
import org.nuiton.jpa.api.JpaEntities;
@@ -52,14 +53,14 @@
*/
public class VoterListService extends AbstractPollenService {
- public VoterList importFavoriteList(String pollId,
- String favoriteListId) throws EntityNotFoundException {
+ public VoterList importFavoriteList(String userId, String pollId,
+ String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(favoriteListId);
Poll poll = getPollService().getPoll(pollId);
- FavoriteList favoriteList = getFavoriteListService().getFavoriteList(favoriteListId);
+ FavoriteList favoriteList = getFavoriteListService().getFavoriteList(userId, favoriteListId);
VoterListJpaDao dao = getPersistenceContext().getVoterListDao();
VoterList result = dao.newInstance();
1
0
r3831 - in trunk: pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1 pollen-services/src/main/java/org/chorem/pollen/services/exception pollen-services/src/main/java/org/chorem/pollen/services/service pollen-services/src/test/java/org/chorem/pollen/service pollen-ui-js/src/main/webapp/bundle pollen-ui-js/src/main/webapp/js/libs
by tchemit@users.chorem.org 15 Jun '13
by tchemit@users.chorem.org 15 Jun '13
15 Jun '13
Author: tchemit
Date: 2013-06-15 16:29:32 +0200 (Sat, 15 Jun 2013)
New Revision: 3831
Url: http://chorem.org/projects/pollen/repository/revisions/3831
Log:
continue edit form + add service poll test
Added:
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListMemberFormException.java
trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java
Modified:
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java
trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
Modified: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -27,6 +27,7 @@
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidVoterListFormException;
import org.debux.webmotion.server.WebMotionController;
import java.util.List;
@@ -53,11 +54,11 @@
return context.getVoterListService().getVoterList(pollId, voterListId);
}
- public VoterList addVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException {
+ public VoterList addVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException, InvalidVoterListFormException {
return context.getVoterListService().addVoterList(pollId, voterList);
}
- public VoterList editVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException {
+ public VoterList editVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException, InvalidVoterListFormException {
return context.getVoterListService().editVoterList(pollId, voterList);
}
@@ -66,23 +67,23 @@
}
public Set<VoterListMember> getMembers(PollenServiceContext context, String pollId, String voterListId) throws EntityNotFoundException {
- Set<VoterListMember> members = context.getVoterListService().getMembers(pollId, voterListId);
+ Set<VoterListMember> members = context.getVoterListService().getVoterListMembers(pollId, voterListId);
return members;
}
public VoterListMember getMember(PollenServiceContext context, String pollId, String voterListId, String memberId) throws EntityNotFoundException {
- return context.getVoterListService().getMember(pollId, voterListId, memberId);
+ return context.getVoterListService().getVoterListMember(pollId, voterListId, memberId);
}
public VoterListMember addMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
- return context.getVoterListService().addMember(pollId, voterListId, member);
+ return context.getVoterListService().addVoterListMember(pollId, voterListId, member);
}
public VoterListMember editMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
- return context.getVoterListService().editMember(pollId, voterListId, member);
+ return context.getVoterListService().editVoterListMember(pollId, voterListId, member);
}
public void deleteMember(PollenServiceContext context, String pollId, String voterListId, String memberId) throws EntityNotFoundException {
- context.getVoterListService().deleteMember(pollId, voterListId, memberId);
+ context.getVoterListService().deleteVoterListMember(pollId, voterListId, memberId);
}
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -44,4 +44,9 @@
public Multimap<String, String> getErrors() {
return errors;
}
+
+ @Override
+ public String toString() {
+ return super.toString()+ " errors: "+errors;
+ }
}
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListFormException.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -0,0 +1,41 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidVoterListFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidVoterListFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListMemberFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListMemberFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListMemberFormException.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -0,0 +1,41 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidVoterListMemberFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidVoterListMemberFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidVoterListMemberFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -25,6 +25,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.Multimap;
+import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.PollenPersistenceContext;
import org.chorem.pollen.services.PollenServiceContext;
@@ -35,6 +36,7 @@
import org.nuiton.jpa.api.JpaEntity;
import org.nuiton.util.StringUtil;
+import java.util.Collection;
import java.util.Date;
/**
@@ -141,6 +143,16 @@
return valid;
}
+ protected boolean checkEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) {
+ boolean valid = check(errors, field, CollectionUtils.isEmpty(value ), error);
+ return valid;
+ }
+
+ protected boolean checkNotEmpty(Multimap<String, String> errors, String field, Collection<?> value, String error) {
+ boolean valid = check(errors, field, CollectionUtils.isNotEmpty(value ), error);
+ return valid;
+ }
+
protected boolean checkNotBlank(Multimap<String, String> errors, String field, String value, String error) {
boolean valid = check(errors, field, StringUtils.isNotBlank(value), error);
return valid;
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -25,6 +25,7 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
@@ -111,6 +112,9 @@
creator.setName(user.getName());
creator.setEmail(user.getEmail());
}
+
+ result.setChoice(Lists.<Choice>newArrayList());
+ result.setVoterList(Lists.<VoterList>newArrayList());
return result;
}
@@ -266,12 +270,12 @@
checkNotNull(errors, "voteCountingType", poll.getVoteCountingType(), "voteCountingType can not be null");
checkNotBlank(errors, "title", poll.getTitle(), "title can not be empty");
- check(errors, "choice", poll.isChoiceEmpty(), "need at least one choice");
+ checkNotEmpty(errors, "choice", poll.getChoice(), "need at least one choice");
if (poll.isFreePoll()) {
- check(errors, "pollType", poll.isVoterListEmpty(), "can't have voterList with free poll");
+ checkEmpty(errors, "voterList", poll.getVoterList(), "can't have voterList with free poll");
} else {
- check(errors, "pollType", !poll.isVoterListEmpty(), "must have voterList with not free poll");
+ checkNotEmpty(errors, "voterList", poll.getVoterList(), "must have voterList with not free poll");
}
if (!poll.isChoiceEmpty()) {
@@ -313,44 +317,50 @@
for (VoterList voterList : poll.getVoterList()) {
- String voterListField = "voterList[" + (voterListIndex++) + "]";
+ String voterListField = "voterList[" + (voterListIndex++) + "].";
- checkNotBlank(errors, voterListField + ".name", voterList.getName(), "voterList name can not be empty");
- check(errors, voterListField + ".weight", voterList.getWeight() > 0, "voterList weight must be greater than 0");
- check(errors, voterListField + ".member", !voterList.isVoterListMemberEmpty(), "voterList must contains at least one member");
+ boolean notBlankName = checkNotBlank(errors, voterListField + "name", voterList.getName(), "voterList name can not be empty");
- boolean added = voterListNames.add(voterList.getName());
+ if (notBlankName) {
+ boolean added = voterListNames.add(voterList.getName());
- check(errors, voterListField, added, "voterList name already used");
+ check(errors, voterListField + "name", added, "voterList name already used");
+ }
+ check(errors, voterListField + "weight", voterList.getWeight() > 0, "voterList weight must be greater than 0");
+ boolean withMember = checkNotEmpty(errors, voterListField + "member", voterList.getVoterListMember(), "voterList must contains at least one member");
- Set<String> voterListMemberNames = Sets.newHashSet();
- Set<String> voterListMemberEmails = Sets.newHashSet();
+ if (withMember) {
+ Set<String> voterListMemberNames = Sets.newHashSet();
+ Set<String> voterListMemberEmails = Sets.newHashSet();
- int voterListMemberIndex = 0;
+ int voterListMemberIndex = 0;
- for (VoterListMember voterListMember : voterList.getVoterListMember()) {
+ for (VoterListMember voterListMember : voterList.getVoterListMember()) {
- String voterListMemberField = voterListField + ".member[" + (voterListMemberIndex++) + "]";
+ String voterListMemberField = voterListField + "member[" + (voterListMemberIndex++) + "].";
- String voterListMemberName = voterListMember.getName();
- boolean nameNotNull = checkNotBlank(errors, voterListMemberField + ".name", voterListMemberName, "member name can not be empty");
+ String voterListMemberName = voterListMember.getName();
+ boolean nameNotNull = checkNotBlank(errors, voterListMemberField + "name", voterListMemberName, "member name can not be empty");
- if (nameNotNull) {
- boolean nameAdded = voterListMemberNames.add(voterListMemberName);
- check(errors, voterListMemberField + ".name", nameAdded, "member name already used in this list");
- }
+ if (nameNotNull) {
+ boolean nameAdded = voterListMemberNames.add(voterListMemberName);
+ check(errors, voterListMemberField + "name", nameAdded, "member name already used in this list");
+ }
- String voterListMemberEmail = voterListMember.getEmail();
+ String voterListMemberEmail = voterListMember.getEmail();
- boolean emailNotNull = checkNotBlank(errors, voterListMemberField + ".email", voterListMemberEmail, "member email can not be empty");
+ boolean emailNotNull = checkNotBlank(errors, voterListMemberField + "email", voterListMemberEmail, "member email can not be empty");
- if (emailNotNull) {
+ if (emailNotNull) {
- voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
+ voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
- checkValidEmail(errors, voterListMemberField + ".email", voterListMemberEmail, "member email is not valid");
- boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
- check(errors, voterListMemberField + ".email", emailAdded, "member email already used in this list");
+ checkValidEmail(errors, voterListMemberField + "email", voterListMemberEmail, "member email is not valid");
+ boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
+ check(errors, voterListMemberField + "email", emailAdded, "member email already used in this list");
+ }
+
+ check(errors, voterListMemberField + "weight", voterListMember.getWeight() > 0, "member weight must be greater than 0");
}
}
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -39,6 +39,7 @@
PollenPrincipal principal = pollenPrincipalDao.newInstance();
principal.setToken(serviceContext.generateToken());
principal.setCreationDate(serviceContext.getNow());
+ pollenPrincipalDao.persist(principal);
return principal;
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -24,6 +24,10 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.dao.VoterListJpaDao;
import org.chorem.pollen.persistence.dao.VoterListMemberJpaDao;
@@ -33,6 +37,8 @@
import org.chorem.pollen.persistence.entity.VoterList;
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidVoterListFormException;
+import org.chorem.pollen.services.exception.InvalidVoterListMemberFormException;
import org.nuiton.jpa.api.JpaEntities;
import java.util.List;
@@ -75,7 +81,6 @@
poll.addVoterList(result);
getPersistenceContext().getPollDao().merge(poll);
-
getPersistenceContext().commit();
return result;
}
@@ -85,25 +90,28 @@
Poll poll = getPollService().getPoll(pollId);
- List<VoterList> result = poll.getVoterList();
+ List<VoterList> result = Lists.newArrayList(poll.getVoterList());
return result;
}
public VoterList getVoterList(String pollId, String voterListId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
- VoterList result = getPersistenceContext().getVoterListDao().findById(voterListId);
- checkEntityExists(VoterList.class, result, voterListId);
+ Poll poll = getPollService().getPoll(pollId);
+ VoterList result = getVoterList(poll, voterListId);
return result;
}
- public VoterList addVoterList(String pollId, VoterList voterList) throws EntityNotFoundException {
+ public VoterList addVoterList(String pollId, VoterList voterList) throws EntityNotFoundException, InvalidVoterListFormException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterList);
checkHasNoId(voterList);
Poll poll = getPollService().getPoll(pollId);
+ checkVoterList(poll, voterList);
+
VoterList result = saveVoterList(poll, voterList);
getPersistenceContext().getPollDao().merge(poll);
@@ -111,12 +119,14 @@
return result;
}
- public VoterList editVoterList(String pollId, VoterList voterList) throws EntityNotFoundException {
+ public VoterList editVoterList(String pollId, VoterList voterList) throws EntityNotFoundException, InvalidVoterListFormException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterList);
checkHasId(voterList);
Poll poll = getPollService().getPoll(pollId);
+ checkVoterList(poll, voterList);
+
VoterList result = saveVoterList(poll, voterList);
getPersistenceContext().getVoterListDao().merge(voterList);
@@ -130,16 +140,16 @@
Poll poll = getPollService().getPoll(pollId);
- VoterList voterList = getVoterList(pollId, voterListId);
+ VoterList voterList = getVoterList(poll, voterListId);
poll.removeVoterList(voterList);
getPersistenceContext().getPollDao().merge(poll);
-
getPersistenceContext().commit();
}
- public Set<VoterListMember> getMembers(String pollId, String voterListId) throws EntityNotFoundException {
+ public Set<VoterListMember> getVoterListMembers(String pollId, String voterListId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
VoterList voterList = getVoterList(pollId, voterListId);
@@ -148,26 +158,20 @@
return result;
}
- public VoterListMember getMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ public VoterListMember getVoterListMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(memberId);
VoterList voterList = getVoterList(pollId, voterListId);
- VoterListMember result = getMember(voterList, memberId);
+ VoterListMember result = getVoterListMember(voterList, memberId);
checkEntityExists(VoterListMember.class, result, memberId);
return result;
}
-
- public VoterListMember getMember(VoterList voterList, String memberId) throws EntityNotFoundException {
- Preconditions.checkNotNull(memberId);
-
- VoterListMember result = voterList.getVoterListMemberById(memberId);
- checkEntityExists(VoterListMember.class, result, memberId);
- return result;
- }
-
- public VoterListMember addMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ public VoterListMember addVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
checkHasNoId(member);
@@ -181,7 +185,9 @@
return result;
}
- public VoterListMember editMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+
+ public VoterListMember editVoterListMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
checkHasId(member);
@@ -195,13 +201,14 @@
return result;
}
- public void deleteMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ public void deleteVoterListMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(memberId);
VoterList voterList = getVoterList(pollId, voterListId);
- VoterListMember member = getMember(voterList, memberId);
+ VoterListMember member = getVoterListMember(voterList, memberId);
voterList.removeVoterListMember(member);
getPersistenceContext().getVoterListDao().merge(voterList);
@@ -209,34 +216,48 @@
getPersistenceContext().commit();
}
+ protected VoterList getVoterList(Poll poll, String voterListId) throws EntityNotFoundException {
+
+ VoterList result = poll.getVoterListById(voterListId);
+ checkEntityExists(VoterList.class, result, voterListId);
+ return result;
+ }
+
+ protected VoterListMember getVoterListMember(VoterList voterList, String memberId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(memberId);
+
+ VoterListMember result = voterList.getVoterListMemberById(memberId);
+ checkEntityExists(VoterListMember.class, result, memberId);
+ return result;
+ }
+
protected VoterList saveVoterList(Poll poll, VoterList voterList) throws EntityNotFoundException {
boolean voterListExists = JpaEntities.isEntityHasId(voterList);
- VoterList voterListToPersist;
+ VoterList toSave;
if (voterListExists) {
- voterListToPersist =
- getVoterListService().getVoterList(poll.getId(), voterList.getId());
+ toSave = getVoterList(poll, voterList.getId());
} else {
VoterListJpaDao voterListDao =
getPersistenceContext().getVoterListDao();
- voterListToPersist = voterListDao.newInstance();
+ toSave = voterListDao.newInstance();
- poll.addVoterList(voterListToPersist);
+ poll.addVoterList(toSave);
}
- voterListToPersist.setName(voterList.getName());
- voterListToPersist.setWeight(voterList.getWeight());
+ toSave.setName(voterList.getName());
+ toSave.setWeight(voterList.getWeight());
for (VoterListMember voterListMember : voterList.getVoterListMember()) {
- saveVoterListMember(voterListToPersist, voterListMember);
+ saveVoterListMember(toSave, voterListMember);
}
- return voterListToPersist;
+ return toSave;
}
protected VoterListMember saveVoterListMember(VoterList voterList,
@@ -245,26 +266,143 @@
boolean voterListMemberExists =
JpaEntities.isEntityHasId(voterListMember);
- VoterListMember voterListMemberToPersist;
+ VoterListMember toSave;
if (voterListMemberExists) {
- voterListMemberToPersist =
- getMember(voterList, voterListMember.getId());
+ toSave = getVoterListMember(voterList, voterListMember.getId());
} else {
VoterListMemberJpaDao voterListMemberDao =
getPersistenceContext().getVoterListMemberDao();
- voterListMemberToPersist = voterListMemberDao.newInstance();
+ toSave = voterListMemberDao.newInstance();
- voterList.addVoterListMember(voterListMemberToPersist);
+ voterList.addVoterListMember(toSave);
}
- voterListMemberToPersist.setName(voterListMember.getName());
- voterListMemberToPersist.setEmail(StringUtils.lowerCase(voterListMember.getEmail()));
- voterListMemberToPersist.setWeight(voterListMember.getWeight());
+ toSave.setName(voterListMember.getName());
+ toSave.setEmail(StringUtils.lowerCase(voterListMember.getEmail()));
+ toSave.setWeight(voterListMember.getWeight());
- return voterListMemberToPersist;
+ return toSave;
}
+
+ protected void checkVoterList(Poll poll, VoterList voterList) throws InvalidVoterListFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ boolean voterListExists = JpaEntities.isEntityHasId(voterList);
+
+ Set<String> voterListNames = Sets.newHashSet();
+
+ if (!poll.isVoterListEmpty()) {
+
+ // get all used names
+
+ for (VoterList lists : poll.getVoterList()) {
+
+ if (voterListExists && lists.getId().equals(voterList.getId())) {
+ continue;
+ }
+
+ voterListNames.add(voterList.getName());
+ }
+ }
+
+ checkNotBlank(errors, "name", voterList.getName(), "voterList name can not be empty");
+ check(errors, "weight", voterList.getWeight() > 0, "voterList weight must be greater than 0");
+ checkNotEmpty(errors, "member", voterList.getVoterListMember(), "voterList must contains at least one member");
+
+ boolean added = voterListNames.add(voterList.getName());
+
+ check(errors, "name", added, "voterList name already used");
+
+ Set<String> voterListMemberNames = Sets.newHashSet();
+ Set<String> voterListMemberEmails = Sets.newHashSet();
+
+ int voterListMemberIndex = 0;
+
+ for (VoterListMember voterListMember : voterList.getVoterListMember()) {
+
+ String voterListMemberField = "member[" + (voterListMemberIndex++) + "].";
+
+ String voterListMemberName = voterListMember.getName();
+ boolean nameNotNull = checkNotBlank(errors, voterListMemberField + "name", voterListMemberName, "member name can not be empty");
+
+ if (nameNotNull) {
+ boolean nameAdded = voterListMemberNames.add(voterListMemberName);
+ check(errors, voterListMemberField + "name", nameAdded, "member name already used in this list");
+ }
+
+ String voterListMemberEmail = voterListMember.getEmail();
+
+ boolean emailNotNull = checkNotBlank(errors, voterListMemberField + "email", voterListMemberEmail, "member email can not be empty");
+
+ if (emailNotNull) {
+
+ voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
+
+ checkValidEmail(errors, voterListMemberField + "email", voterListMemberEmail, "member email is not valid");
+ boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
+ check(errors, voterListMemberField + "email", emailAdded, "member email already used in this list");
+ }
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidVoterListFormException(errors);
+ }
+ }
+
+ protected void checkVoterListMember(VoterList voterList, VoterListMember voterListMember) throws InvalidVoterListMemberFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ boolean voterListMemberExists = JpaEntities.isEntityHasId(voterListMember);
+
+ Set<String> voterListMemberNames = Sets.newHashSet();
+ Set<String> voterListMemberEmails = Sets.newHashSet();
+ if (!voterList.isVoterListMemberEmpty()) {
+
+ // get all used names
+
+ for (VoterListMember member : voterList.getVoterListMember()) {
+
+ if (voterListMemberExists && member.getId().equals(voterListMember.getId())) {
+ continue;
+ }
+
+ voterListMemberNames.add(voterListMember.getName());
+ voterListMemberEmails.add(voterListMember.getEmail());
+ }
+ }
+ String voterListMemberName = voterListMember.getName();
+ boolean nameNotNull = checkNotBlank(errors, "name", voterListMemberName, "member name can not be empty");
+
+ if (nameNotNull) {
+ boolean nameAdded = voterListMemberNames.add(voterListMemberName);
+ check(errors, "name", nameAdded, "member name already used in this list");
+ }
+
+ String voterListMemberEmail = voterListMember.getEmail();
+
+ boolean emailNotNull = checkNotBlank(errors, "email", voterListMemberEmail, "member email can not be empty");
+
+ if (emailNotNull) {
+
+ voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
+
+ checkValidEmail(errors, "email", voterListMemberEmail, "member email is not valid");
+ boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
+ check(errors, "email", emailAdded, "member email already used in this list");
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidVoterListMemberFormException(errors);
+ }
+ }
}
Modified: trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java
===================================================================
--- trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2013-06-15 10:58:03 UTC (rev 3830)
+++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/AbstractPollenServiceTest.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -23,11 +23,14 @@
* #L%
*/
+import com.google.common.collect.Multimap;
import org.chorem.pollen.persistence.JpaPollenPersistenceContext;
import org.chorem.pollen.services.PollenFixtures;
+import org.chorem.pollen.services.PollenServiceSupport;
import org.chorem.pollen.services.config.PollenServiceConfig;
+import org.chorem.pollen.services.exception.AbstractInvalidFormException;
import org.chorem.pollen.services.service.FixturesService;
-import org.chorem.pollen.services.PollenServiceSupport;
+import org.junit.Assert;
import org.junit.Rule;
import org.nuiton.jpa.junit.JpaEntityManagerRule;
@@ -114,4 +117,14 @@
}
+ protected void assertErrorKeyFound(AbstractInvalidFormException e, String... keys) {
+ Multimap<String, String> errors = e.getErrors();
+
+ Assert.assertEquals("Expected " + keys.length + " errors, but had " + errors.keySet(), keys.length, errors.keySet().size());
+ for (String key : keys) {
+
+ Assert.assertTrue("Expected error:" + key + ", but not found among:" + errors.keySet(), errors.containsKey(key));
+ }
+ }
+
}
Added: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java
===================================================================
--- trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java (rev 0)
+++ trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java 2013-06-15 14:29:32 UTC (rev 3831)
@@ -0,0 +1,322 @@
+package org.chorem.pollen.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.Choice;
+import org.chorem.pollen.persistence.entity.ChoiceType;
+import org.chorem.pollen.persistence.entity.Poll;
+import org.chorem.pollen.persistence.entity.PollType;
+import org.chorem.pollen.persistence.entity.VoterList;
+import org.chorem.pollen.persistence.entity.VoterListMember;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollFormException;
+import org.chorem.pollen.services.service.PollService;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollServiceTest extends AbstractPollenServiceTest {
+
+ protected PollService service;
+
+ @Before
+ public void setUp() throws ParseException {
+
+ loadFixtures("fixtures");
+
+ service = serviceContext.getPollService();
+
+ serviceContext.setDate(new Date(1363948427576l));
+ }
+
+ @Test
+ public void testCreateFreePoll() throws EntityNotFoundException, InvalidPollFormException {
+
+ Poll poll = service.getNewPoll(null, ChoiceType.TEXT);
+
+ poll.setPollType(PollType.FREE);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // missing title
+ // missing choice
+ assertErrorKeyFound(e, "title", "choice");
+ }
+
+ poll.setTitle("poll1");
+
+ Choice choice1 = new Choice();
+ poll.addChoice(choice1);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // missing choice name
+ assertErrorKeyFound(e, "choice[0].name");
+ }
+
+ choice1.setName("A");
+ choice1.setDescription("Choice A");
+
+
+ Choice choice2 = new Choice();
+ choice2.setName("A");
+ choice2.setDescription("Choice B");
+ poll.addChoice(choice2);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // duplicated choice name
+ assertErrorKeyFound(e, "choice[1].name");
+ }
+
+ choice2.setName("B");
+
+
+ Poll createdPoll = service.createPoll(null, poll);
+ Assert.assertNotNull(createdPoll);
+ Assert.assertNotNull(createdPoll.getId());
+
+ Poll reloadedPoll = service.getPoll(createdPoll.getId());
+ Assert.assertEquals(createdPoll, reloadedPoll);
+
+ Assert.assertEquals(serviceContext.getNow(), createdPoll.getBeginDate());
+
+ Assert.assertNotNull(createdPoll.getCreator());
+ Assert.assertNotNull(createdPoll.getCreator().getId());
+ Assert.assertNotNull(createdPoll.getCreator().getToken());
+ Assert.assertNull(createdPoll.getCreator().getName());
+ Assert.assertNull(createdPoll.getCreator().getEmail());
+ Assert.assertNull(createdPoll.getComment());
+ Assert.assertNull(createdPoll.getVote());
+ Assert.assertNull(createdPoll.getVoterList());
+
+ Assert.assertNotNull(createdPoll.getChoice());
+ Assert.assertEquals(2, createdPoll.sizeChoice());
+
+
+ Choice createdChoice1 = createdPoll.getChoice(0);
+ Assert.assertNotNull(createdChoice1);
+ Assert.assertNotNull(createdChoice1.getId());
+
+ Choice reloadedChoice1 = serviceContext.getChoiceService().getChoice(createdPoll.getId(), createdChoice1.getId());
+ Assert.assertEquals(createdChoice1, reloadedChoice1);
+
+ Assert.assertEquals(choice1.getName(), createdChoice1.getName());
+ Assert.assertEquals(choice1.getDescription(), createdChoice1.getDescription());
+ Assert.assertEquals(createdPoll.getCreator(), createdChoice1.getCreator());
+
+ Choice createdChoice2 = createdPoll.getChoice(1);
+ Assert.assertNotNull(createdChoice2);
+ Assert.assertNotNull(createdChoice2.getId());
+
+ Choice reloadedChoice2 = serviceContext.getChoiceService().getChoice(createdPoll.getId(), createdChoice2.getId());
+ Assert.assertEquals(createdChoice2, reloadedChoice2);
+
+ Assert.assertEquals(choice2.getName(), createdChoice2.getName());
+ Assert.assertEquals(choice2.getDescription(), createdChoice2.getDescription());
+ Assert.assertEquals(createdPoll.getCreator(), createdChoice2.getCreator());
+
+ }
+
+ @Test
+ public void testCreateRestrictedPoll() throws EntityNotFoundException, InvalidPollFormException {
+
+ Poll poll = service.getNewPoll(null, ChoiceType.TEXT);
+ poll.setPollType(PollType.RESTRICTED);
+
+ poll.setTitle("poll1");
+
+ Choice choice1 = new Choice();
+ choice1.setName("A");
+ choice1.setDescription("Choice A");
+
+ poll.addChoice(choice1);
+
+ Choice choice2 = new Choice();
+ choice2.setName("B");
+ choice2.setDescription("Choice B");
+
+ poll.addChoice(choice2);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // missing voterList
+ assertErrorKeyFound(e, "voterList");
+ }
+
+ // add voter list
+ VoterList voterList = new VoterList();
+
+ poll.addVoterList(voterList);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // missing name
+ // missing weight
+ // missing voterListMember
+ assertErrorKeyFound(e, "voterList[0].name", "voterList[0].weight", "voterList[0].member");
+ }
+
+ voterList.setName("voterList1");
+ voterList.setWeight(1);
+
+ VoterListMember voterListMember1 = new VoterListMember();
+ voterList.addVoterListMember(voterListMember1);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // missing member name
+ // missing member email
+ assertErrorKeyFound(e, "voterList[0].member[0].name", "voterList[0].member[0].email", "voterList[0].member[0].weight");
+ }
+
+ voterListMember1.setName("voter1");
+ voterListMember1.setWeight(0.3);
+ voterListMember1.setEmail("voter1_pollen.org");
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // invalid member email
+ assertErrorKeyFound(e, "voterList[0].member[0].email");
+ }
+
+ voterListMember1.setEmail("voter1(a)pollen.org");
+
+ VoterListMember voterListMember2 = new VoterListMember();
+ voterListMember2.setName("voter1");
+ voterListMember2.setWeight(0.7);
+ voterListMember2.setEmail("voter1(a)pollen.org");
+ voterList.addVoterListMember(voterListMember2);
+
+ try {
+ service.createPoll(null, poll);
+ } catch (InvalidPollFormException e) {
+ // same name
+ // same email
+ assertErrorKeyFound(e, "voterList[0].member[1].name", "voterList[0].member[1].email");
+ }
+
+ voterListMember2.setName("voter2");
+ voterListMember2.setEmail("voter2(a)pollen.org");
+
+
+ Poll createdPoll = service.createPoll(null, poll);
+ Assert.assertNotNull(createdPoll);
+ Assert.assertNotNull(createdPoll.getId());
+
+ Poll reloadedPoll = service.getPoll(createdPoll.getId());
+ Assert.assertEquals(createdPoll, reloadedPoll);
+
+ Assert.assertEquals(serviceContext.getNow(), createdPoll.getBeginDate());
+
+ Assert.assertNotNull(createdPoll.getCreator());
+ Assert.assertNotNull(createdPoll.getCreator().getId());
+ Assert.assertNotNull(createdPoll.getCreator().getToken());
+ Assert.assertNull(createdPoll.getCreator().getName());
+ Assert.assertNull(createdPoll.getCreator().getEmail());
+ Assert.assertNull(createdPoll.getComment());
+ Assert.assertNull(createdPoll.getVote());
+
+ Assert.assertNotNull(createdPoll.getChoice());
+ Assert.assertEquals(2, createdPoll.sizeChoice());
+
+ Choice createdChoice1 = createdPoll.getChoice(0);
+ Assert.assertNotNull(createdChoice1);
+ Assert.assertNotNull(createdChoice1.getId());
+
+ Choice reloadedChoice1 = serviceContext.getChoiceService().getChoice(createdPoll.getId(), createdChoice1.getId());
+ Assert.assertEquals(createdChoice1, reloadedChoice1);
+
+ Assert.assertEquals(choice1.getName(), createdChoice1.getName());
+ Assert.assertEquals(choice1.getDescription(), createdChoice1.getDescription());
+ Assert.assertEquals(createdPoll.getCreator(), createdChoice1.getCreator());
+
+ Choice createdChoice2 = createdPoll.getChoice(1);
+ Assert.assertNotNull(createdChoice2);
+ Assert.assertNotNull(createdChoice2.getId());
+
+ Choice reloadedChoice2 = serviceContext.getChoiceService().getChoice(createdPoll.getId(), createdChoice2.getId());
+ Assert.assertEquals(createdChoice2, reloadedChoice2);
+
+ Assert.assertEquals(choice2.getName(), createdChoice2.getName());
+ Assert.assertEquals(choice2.getDescription(), createdChoice2.getDescription());
+ Assert.assertEquals(createdPoll.getCreator(), createdChoice2.getCreator());
+
+ Assert.assertNotNull(createdPoll.getVoterList());
+ Assert.assertEquals(1, createdPoll.sizeVoterList());
+ VoterList createdVoterList = createdPoll.getVoterList(0);
+ Assert.assertNotNull(createdVoterList);
+ Assert.assertNotNull(createdVoterList.getId());
+
+ VoterList reloadedVoterList = serviceContext.getVoterListService().getVoterList(createdPoll.getId(), createdVoterList.getId());
+ Assert.assertEquals(createdVoterList, reloadedVoterList);
+
+ Assert.assertEquals(voterList.getName(), createdVoterList.getName());
+ Assert.assertEquals(voterList.getWeight(), createdVoterList.getWeight(), 0);
+
+ Assert.assertNotNull(createdVoterList.getVoterListMember());
+ Assert.assertEquals(2, createdVoterList.sizeVoterListMember());
+
+ VoterListMember createdVoterListMember1 = createdVoterList.getVoterListMember(0);
+
+ Assert.assertNotNull(createdVoterListMember1);
+ Assert.assertNotNull(createdVoterListMember1.getId());
+ VoterListMember reloadedVoterListMember1 = serviceContext.getVoterListService().getVoterListMember(createdPoll.getId(), createdVoterList.getId(), createdVoterListMember1.getId());
+ Assert.assertEquals(createdVoterListMember1, reloadedVoterListMember1);
+
+ Assert.assertEquals(voterListMember1.getName(), createdVoterListMember1.getName());
+ Assert.assertEquals(voterListMember1.getEmail(), createdVoterListMember1.getEmail());
+ Assert.assertEquals(voterListMember1.getWeight(), createdVoterListMember1.getWeight(), 0);
+
+ VoterListMember createdVoterListMember2 = createdVoterList.getVoterListMember(1);
+
+ Assert.assertNotNull(createdVoterListMember2);
+ Assert.assertNotNull(createdVoterListMember2.getId());
+
+ VoterListMember reloadedVoterListMember2 = serviceContext.getVoterListService().getVoterListMember(createdPoll.getId(), createdVoterList.getId(), createdVoterListMember2.getId());
+ Assert.assertEquals(createdVoterListMember2, reloadedVoterListMember2);
+
+ Assert.assertEquals(voterListMember2.getName(), createdVoterListMember2.getName());
+ Assert.assertEquals(voterListMember2.getEmail(), createdVoterListMember2.getEmail());
+ Assert.assertEquals(voterListMember2.getWeight(), createdVoterListMember2.getWeight(), 0);
+
+ }
+
+}
Property changes on: trunk/pollen-services/src/test/java/org/chorem/pollen/service/PollServiceTest.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Property changes on: trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Property changes on: trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
1
0
Author: tchemit
Date: 2013-06-15 12:58:03 +0200 (Sat, 15 Jun 2013)
New Revision: 3830
Url: http://chorem.org/projects/pollen/repository/revisions/3830
Log:
- use version in REST api (v1)
- normalize rest api (need all the data path)
- implements poll create - edit service
- implements choice create - edit service
- implements voterList create - edit service
Added:
trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenApplicationContext.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenJpaTransactionFilter.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServices.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteCountingService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidChoiceFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollFormException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/package-info.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/package-info.java
Removed:
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenApplicationContext.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenJpaTransactionFilter.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenRender.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenSecurityFilter.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceContextFilter.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceListener.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServices.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/AuthService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/CommentService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/ErrorAction.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/FavoriteListService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/UserService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteCountingService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteService.java
trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoterListService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/service/
Modified:
trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenEntityIdFactory.java
trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenPersistenceContext.java
trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenUser.java
trunk/pollen-persistence/src/main/xmi/pollen.properties
trunk/pollen-persistence/src/main/xmi/pollen.zargo
trunk/pollen-rest-api/src/it/pom/pom.xml
trunk/pollen-rest-api/src/it/user/README.txt
trunk/pollen-rest-api/src/main/resources/mapping
trunk/pollen-rest-api/src/main/webapp/WEB-INF/web.xml
trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java
trunk/pollen-rest-api/src/test/resources/pollen.properties
trunk/pollen-services/pom.xml
trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityContext.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/package-info.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
trunk/pollen-ui-js/src/main/webapp/img/glyphicons_050_link.png
trunk/pollen-ui-js/src/main/webapp/js/libs/date.js
trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.scrollto.js
Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenEntityIdFactory.java
===================================================================
--- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenEntityIdFactory.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenEntityIdFactory.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.persistence;
+/*
+ * #%L
+ * Pollen :: Persistence
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
import com.google.common.base.Preconditions;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
Property changes on: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenEntityIdFactory.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenPersistenceContext.java
===================================================================
--- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenPersistenceContext.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/PollenPersistenceContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -28,6 +28,7 @@
import org.chorem.pollen.persistence.dao.FavoriteListJpaDao;
import org.chorem.pollen.persistence.dao.FavoriteListMemberJpaDao;
import org.chorem.pollen.persistence.dao.PollJpaDao;
+import org.chorem.pollen.persistence.dao.PollenPrincipalJpaDao;
import org.chorem.pollen.persistence.dao.PollenUserJpaDao;
import org.chorem.pollen.persistence.dao.SessionTokenJpaDao;
import org.chorem.pollen.persistence.dao.VoteJpaDao;
@@ -63,6 +64,8 @@
PollJpaDao getPollDao();
+ PollenPrincipalJpaDao getPollenPrincipalDao();
+
PollenUserJpaDao getPollenUserDao();
SessionTokenJpaDao getSessionTokenDao();
Added: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java
===================================================================
--- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java (rev 0)
+++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,51 @@
+package org.chorem.pollen.persistence.entity;
+
+/*
+ * #%L
+ * Pollen :: Persistence
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import javax.persistence.Entity;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+@Entity
+public class Poll extends AbstractJpaPoll {
+
+ private static final long serialVersionUID = 1L;
+
+ public boolean isFreePoll() {
+ return PollType.FREE == pollType;
+ }
+
+ public boolean isRestrictedPoll() {
+ return PollType.RESTRICTED == pollType;
+ }
+
+ public boolean isGroupPoll() {
+ return PollType.GROUP == pollType;
+ }
+
+} //Poll
Property changes on: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/Poll.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenUser.java
===================================================================
--- trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenUser.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-persistence/src/main/java/org/chorem/pollen/persistence/entity/PollenUser.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -25,6 +25,12 @@
import javax.persistence.Entity;
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
@Entity
public class PollenUser extends AbstractJpaPollenUser {
Modified: trunk/pollen-persistence/src/main/xmi/pollen.properties
===================================================================
--- trunk/pollen-persistence/src/main/xmi/pollen.properties 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-persistence/src/main/xmi/pollen.properties 2013-06-15 10:58:03 UTC (rev 3830)
@@ -21,7 +21,6 @@
# #L%
###m
model.tagValue.idFactory=true
-model.tagValue.generatePropertyChangeListeners=true
model.tagValue.generateVisitors=true
model.tagvalue.version=2.0
#model.tagvalue.entitySuperClass=org.chorem.pollen.persistence.entity.AbstractJpaPollenEntity
Modified: trunk/pollen-persistence/src/main/xmi/pollen.zargo
===================================================================
(Binary files differ)
Modified: trunk/pollen-rest-api/src/it/pom/pom.xml
===================================================================
--- trunk/pollen-rest-api/src/it/pom/pom.xml 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/it/pom/pom.xml 2013-06-15 10:58:03 UTC (rev 3830)
@@ -3,7 +3,7 @@
#%L
Pollen :: UI (struts2)
$Id$
- $HeadURL: http://svn.chorem.org/svn/pollen/branches/pollen-2.0/pollen-ui-struts2/src/… $
+ $HeadURL$
%%
Copyright (C) 2009 - 2012 CodeLutin
%%
Property changes on: trunk/pollen-rest-api/src/it/pom/pom.xml
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Property changes on: trunk/pollen-rest-api/src/it/user/README.txt
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenApplicationContext.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenApplicationContext.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenApplicationContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,125 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.chorem.pollen.persistence.JpaPollenPersistenceContext;
-import org.chorem.pollen.services.DefaultPollenServiceContext;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.config.PollenServiceConfig;
-
-import javax.persistence.EntityManager;
-import javax.persistence.EntityManagerFactory;
-import javax.persistence.Persistence;
-import javax.persistence.PersistenceException;
-import java.io.Closeable;
-import java.util.Map;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenApplicationContext implements Closeable {
-
- private static final Log log = LogFactory.getLog(PollenApplicationContext.class);
-
- protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext";
-
- protected PollenServiceConfig applicationConfig;
-
- protected EntityManagerFactory entityManagerFactory;
-
- public PollenServiceConfig getPollenServiceConfig() {
- if (applicationConfig == null) {
- applicationConfig = new PollenServiceConfig();
- }
- return applicationConfig;
- }
-
- public EntityManager newEntityManager() {
-
- if (entityManagerFactory == null) {
-
- PollenServiceConfig applicationConfig = getPollenServiceConfig();
-
- Map<String, String> jpaParameters = applicationConfig.getJpaParameters();
-
- if (log.isInfoEnabled()) {
- log.info("creating entity manager factory");
- }
-
- try {
-
- entityManagerFactory = Persistence.createEntityManagerFactory("pollenPersistenceUnit", jpaParameters);
-
- } catch (PersistenceException e) {
-
- if (log.isErrorEnabled()) {
- log.error("unable to create entity manager factory", e);
- }
-
- throw e;
-
- }
-
- }
-
- EntityManager entityManager = entityManagerFactory.createEntityManager();
-
- return entityManager;
-
- }
-
- public void close() {
-
- if (entityManagerFactory != null && entityManagerFactory.isOpen()) {
-
- if (log.isInfoEnabled()) {
- log.info("stopping magalie, will close entity manager factory");
- }
-
- entityManagerFactory.close();
-
- }
-
- }
-
- public PollenServiceContext newServiceContext(EntityManager entityManager) {
-
- DefaultPollenServiceContext serviceContext = new DefaultPollenServiceContext();
-
- JpaPollenPersistenceContext jpaMagaliePersistenceContext =
- new JpaPollenPersistenceContext(entityManager);
-
- serviceContext.setPersistenceContext(jpaMagaliePersistenceContext);
-
- serviceContext.setPollenServiceConfig(applicationConfig);
-
- return serviceContext;
-
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenJpaTransactionFilter.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenJpaTransactionFilter.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenJpaTransactionFilter.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,87 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import com.google.common.base.Preconditions;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.nuiton.web.filter.JpaTransactionFilter;
-
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceException;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-
-public class PollenJpaTransactionFilter extends JpaTransactionFilter {
-
- private static final Log log =
- LogFactory.getLog(PollenJpaTransactionFilter.class);
-
- protected PollenApplicationContext applicationContext;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
-
- super.init(filterConfig);
-
- if (log.isInfoEnabled()) {
- log.info("Init JPA Filter");
- }
-
-// applicationContext = PollenServices.getApplicationContext(
-// filterConfig.getServletContext());
-//
-// Preconditions.checkNotNull(applicationContext, "Could not find application context at ServletContext#pollen_PollenApplicationContext");
- }
-
- protected PollenApplicationContext getApplicationContext(ServletRequest request) {
- if (applicationContext == null) {
- applicationContext = PollenServices.getApplicationContext(
- request.getServletContext());
-
- Preconditions.checkNotNull(applicationContext, "Could not find application context at ServletContext#pollen_PollenApplicationContext");
- }
- return applicationContext;
- }
-
- @Override
- protected EntityManager createEntityManager(ServletRequest request) {
-
- EntityManager entityManager;
-
- try {
-
- entityManager = getApplicationContext(request).newEntityManager();
-
- } catch (PersistenceException e) {
-
- if (log.isErrorEnabled()) {
- log.error("unable to create entity manager", e);
- }
- throw e;
- }
- return entityManager;
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenRender.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenRender.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenRender.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,234 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.gson.Gson;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.debux.webmotion.server.call.Call;
-import org.debux.webmotion.server.call.HttpContext;
-import org.debux.webmotion.server.mapping.Mapping;
-import org.debux.webmotion.server.render.Render;
-import org.nuiton.jpa.api.JpaEntity;
-import org.nuiton.util.ObjectUtil;
-import org.nuiton.util.beans.Binder;
-import org.nuiton.util.beans.BinderFactory;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * To render any entities.
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenRender<T> extends Render {
-
- /**
- * To specify entity collections to include in binded entities.
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- public @interface ExposeCollection {
-
- public String[] values() default {};
- }
-
- protected T model;
-
- public PollenRender(T model) {
- this.model = model;
- }
-
- @Override
- public void create(Mapping mapping, Call call) throws IOException, ServletException {
-
- HttpContext context = call.getContext();
- HttpServletResponse response = context.getResponse();
- response.setContentType("application/json");
-
- String[] includeCollection = null;
- ExposeCollection annotation = call.getCurrent().getMethod().getAnnotation(ExposeCollection.class);
- if (annotation != null) {
- includeCollection = annotation.values();
- }
- Object map = toMap(model, includeCollection);
-
- Gson gson = new Gson();
- String json = gson.toJson(map);
- PrintWriter out = context.getOut();
- out.print(json);
- }
-
- protected <M> Object toMap(M model, String... includeCollection) {
- if (model instanceof Iterable<?>) {
-
- // collection of objects
- Iterable<?> objects = (Iterable<?>) model;
- List<Object> result = Lists.newArrayList();
- for (Object object : objects) {
- Object objectMap = toMap(object, includeCollection);
- result.add(objectMap);
- }
- return result;
- }
-
- // single object
-
- if (model instanceof JpaEntity) {
-
- // entity need to transform it
-
- JpaEntity jpaEntity = (JpaEntity) model;
-
- PollenEntityBinder<JpaEntity> binder = BinderFactory.newBinder(jpaEntity.getClass(), jpaEntity.getClass(), null, PollenEntityBinder.class);
- Map<String, Object> map = binder.obtainProperties(jpaEntity);
- Map<String, Object> result = Maps.newTreeMap();
-
- for (Map.Entry<String, Object> entry : map.entrySet()) {
- String propertyName = entry.getKey();
- Object propertyValue = entry.getValue();
- if (propertyValue instanceof JpaEntity) {
- result.put(propertyName, toMap(propertyValue));
- continue;
- }
-
- result.put(propertyName, propertyValue);
- }
-
- // treat collections
-
- if (includeCollection != null) {
- for (String propertyName : includeCollection) {
- Iterable<?> collectionValue = binder.getCollectionValue(jpaEntity, propertyName);
- result.put(propertyName, toMap(collectionValue));
-
- }
- }
- return result;
- }
-
- return model;
- }
-
- protected static class PollenEntityBinder<E extends JpaEntity> extends Binder<E, E> {
-
- /** Logger. */
- private static final Log log =
- LogFactory.getLog(PollenEntityBinder.class);
-
- private static final long serialVersionUID = 1L;
-
- protected List<String> simpleProperties;
-
- public PollenEntityBinder() {
- }
-
- @Override
- protected void setModel(BinderModel<E, E> model) {
- super.setModel(model);
- this.simpleProperties = Lists.newArrayList();
- for (String property : model.getSourceDescriptors()) {
- if (model.getCollectionType(property) == null) {
- simpleProperties.add(property);
- }
- }
- }
-
- /**
- * Obtain from the given object all properties registered in the binder
- * model.
- *
- * @param source the bean to read
- * @return the map of properties obtained indexed by their property name,
- * or an empty map is the given {@code from} is {@code null}.
- * @since 2.3
- */
- public Map<String, Object> obtainProperties(E source) {
- if (source == null) {
- // special limit case
- return Collections.emptyMap();
- }
-
- Map<String, Object> result = Maps.newTreeMap();
- for (String sourceProperty : simpleProperties) {
-
-
- try {
- Object read;
- Method readMethod = model.getSourceReadMethod(sourceProperty);
- read = readMethod.invoke(source);
- if (log.isDebugEnabled()) {
- log.debug("property " + sourceProperty + ", type : " +
- readMethod.getReturnType() + ", value = " + read);
- }
- if (readMethod.getReturnType().isPrimitive() &&
- ObjectUtil.getNullValue(
- readMethod.getReturnType()).equals(read)) {
- // for primitive type case, force nullity
- read = null;
- }
-
- if (read != null) {
- result.put(sourceProperty, read);
- }
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- return result;
- }
-
- public Iterable<?> getCollectionValue(E source, String sourceProperty) {
- try {
- Method readMethod = model.getSourceReadMethod(sourceProperty);
- Object result = readMethod.invoke(source);
- return (Iterable<?>) result;
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- }
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenSecurityFilter.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenSecurityFilter.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenSecurityFilter.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,47 +0,0 @@
-package org.chorem.pollen.rest;
-
-import org.apache.commons.lang3.StringUtils;
-import org.chorem.pollen.persistence.entity.SessionToken;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.InvalidSessionTokenException;
-import org.debux.webmotion.server.WebMotionFilter;
-import org.debux.webmotion.server.call.HttpContext;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenSecurityFilter extends WebMotionFilter {
-
- public static final String REQUEST_AUTH_PARAMETER = "auth";
-
- void injectConnectedUser(HttpContext context) throws InvalidSessionTokenException {
-
- String[] strings = context.getParameters().get(REQUEST_AUTH_PARAMETER);
-
- String authParam = strings == null || strings.length < 1 ? null : strings[1];
-
- if (StringUtils.isNotBlank(authParam)) {
-
- // find out the userId from this auth
-
- HttpServletRequest request = context.getRequest();
-
- PollenServiceContext serviceContext =
- PollenServices.getServiceContext(request);
-
- SessionToken sessionToken =
- serviceContext.getAuthService().getUserByAuth(authParam);
-
- if (sessionToken != null) {
-
- // reinject it in request
- PollenServices.setSessionToken(request, sessionToken);
- }
- }
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceContextFilter.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceContextFilter.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceContextFilter.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,55 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.services.PollenServiceContext;
-import org.debux.webmotion.server.WebMotionFilter;
-import org.debux.webmotion.server.call.HttpContext;
-
-import javax.persistence.EntityManager;
-
-/**
- * Inject le service context dans les controlleurs.
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenServiceContextFilter extends WebMotionFilter {
-
- public void inject(HttpContext context) {
-
- PollenApplicationContext applicationContext =
- PollenServices.getApplicationContext(context.getServletContext());
-
- EntityManager entityManager =
- PollenServices.getEntityManager(context.getRequest());
-
- PollenServiceContext serviceContext =
- applicationContext.newServiceContext(entityManager);
-
- PollenServices.setServiceContext(context.getRequest(), serviceContext);
-
- doProcess();
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceListener.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceListener.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceListener.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,124 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
-import org.debux.webmotion.server.WebMotionServerListener;
-import org.debux.webmotion.server.call.Call;
-import org.debux.webmotion.server.call.HttpContext;
-import org.debux.webmotion.server.call.ServerContext;
-import org.debux.webmotion.server.handler.ExecutorParametersInjectorHandler;
-import org.debux.webmotion.server.mapping.Mapping;
-
-import javax.persistence.EntityManager;
-import javax.servlet.http.HttpServletRequest;
-import java.lang.reflect.Type;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenServiceListener implements WebMotionServerListener {
-
- /** Logger. */
- private static final Log log =
- LogFactory.getLog(PollenServiceListener.class);
-
- @Override
- public void onStart(Mapping mapping, ServerContext serverContext) {
-
- serverContext.addInjector(new PollenServiceContextInjector());
- serverContext.addInjector(new SessionTokenInjector());
-
- // Create application context
- PollenApplicationContext applicationContext =
- new PollenApplicationContext();
-
- // push it in context
- PollenServices.setApplicationContext(
- serverContext.getServletContext(), applicationContext);
-
- EntityManager entityManager = applicationContext.newEntityManager();
-
- try {
- PollenServiceContext serviceContext =
- applicationContext.newServiceContext(entityManager);
- serviceContext.getUserService().createDefaultUsers();
- } catch (UserEmailAlreadyUsedException e) {
- //Can't happen
- } catch (UserLoginAlreadyUsedException e) {
- //Can't happen
- } finally {
- entityManager.close();
- }
- }
-
- @Override
- public void onStop(ServerContext serverContext) {
-
- // Get application context
- PollenApplicationContext applicationContext =
- PollenServices.getApplicationContext(
- serverContext.getServletContext());
-
- // close it (and all underlined resources)
- if (applicationContext != null) {
- applicationContext.close();
- }
- }
-
- protected static class PollenServiceContextInjector implements ExecutorParametersInjectorHandler.Injector {
- @Override
- public Object getValue(Mapping mapping, Call call, String name, Class<?> type, Type generic) {
- PollenServiceContext result = null;
- if (PollenServiceContext.class.isAssignableFrom(type)) {
- HttpContext httpContext = call.getContext();
- HttpServletRequest request = httpContext.getRequest();
-
- result = PollenServices.getServiceContext(request);
- }
- return result;
- }
- }
-
- protected static class SessionTokenInjector implements ExecutorParametersInjectorHandler.Injector {
- @Override
- public Object getValue(Mapping mapping, Call call, String name, Class<?> type, Type generic) {
- PollenServiceContext result = null;
- if (PollenServiceContext.class.isAssignableFrom(type)) {
- HttpContext httpContext = call.getContext();
- HttpServletRequest request = httpContext.getRequest();
-
- result = PollenServices.getServiceContext(request);
- }
- return result;
- }
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServices.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServices.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServices.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,89 +0,0 @@
-package org.chorem.pollen.rest;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.SessionToken;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.nuiton.web.filter.JpaTransactionFilter;
-
-import javax.persistence.EntityManager;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollenServices {
-
- protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext";
-
- protected static final String REQUEST_POLLEN_SERVICE_CONTEXT = "pollen_PollenServiceContext";
-
- protected static final String REQUEST_POLLEN_CONNECTED_USER = "pollen_PollenConnectedUser";
-
- protected static final String REQUEST_ENTITY_MANAGER = JpaTransactionFilter.JPA_TRANSACTION_REQUEST_ATTRIBUTE;
-
- public static PollenApplicationContext getApplicationContext(ServletContext servletContext) {
- PollenApplicationContext result = (PollenApplicationContext)
- servletContext.getAttribute(APPLICATION_CONTEXT_PARAMETER);
- return result;
- }
-
- public static void setApplicationContext(ServletContext servletContext,
- PollenApplicationContext applicationContext) {
- servletContext.setAttribute(APPLICATION_CONTEXT_PARAMETER, applicationContext);
- }
-
-
- public static PollenServiceContext getServiceContext(HttpServletRequest request) {
- PollenServiceContext result = (PollenServiceContext)
- request.getAttribute(REQUEST_POLLEN_SERVICE_CONTEXT);
- return result;
- }
-
- public static void setServiceContext(HttpServletRequest request,
- PollenServiceContext serviceContext) {
- request.setAttribute(REQUEST_POLLEN_SERVICE_CONTEXT, serviceContext);
- }
-
- public static EntityManager getEntityManager(HttpServletRequest request) {
- EntityManager result = (EntityManager)
- request.getAttribute(REQUEST_ENTITY_MANAGER);
- return result;
- }
-
- public static SessionToken getSessionToken(HttpServletRequest request) {
- SessionToken result = (SessionToken)
- request.getAttribute(REQUEST_POLLEN_CONNECTED_USER);
- return result;
- }
-
- public static void setSessionToken(HttpServletRequest request,
- SessionToken sessionToken) {
- request.setAttribute(REQUEST_POLLEN_CONNECTED_USER, sessionToken);
- }
-}
\ No newline at end of file
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/AuthService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/AuthService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/AuthService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,50 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.UserInvalidPasswordException;
-import org.debux.webmotion.server.WebMotionController;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class AuthService extends WebMotionController {
-
- public String login(PollenServiceContext context, String login, String password) throws UserInvalidPasswordException, EntityNotFoundException {
- return context.getAuthService().login(login, password);
- }
-
- public void lostPassword(PollenServiceContext context, String login) throws EntityNotFoundException {
- context.getAuthService().lostPassword(login);
- }
-
- public void logout(PollenServiceContext context, String login, String token) throws EntityNotFoundException {
- context.getAuthService().logout(login, token);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/CommentService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/CommentService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/CommentService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,61 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.Comment;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class CommentService extends WebMotionController {
-
- public List<Comment> getComments(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- List<Comment> comments = context.getCommentService().getComments(pollId);
- return comments;
- }
-
- public Comment getComment(PollenServiceContext context, String commentId) throws EntityNotFoundException {
- return context.getCommentService().getComment(commentId);
- }
-
- public Comment addComment(PollenServiceContext context, String pollId, Comment comment) throws EntityNotFoundException {
- return context.getCommentService().addComment(pollId, comment);
- }
-
- public Comment editComment(PollenServiceContext context,Comment comment) throws EntityNotFoundException {
- return context.getCommentService().editComment(comment);
- }
-
- public void deleteComment(PollenServiceContext context, String pollId, String commentId) throws EntityNotFoundException {
- context.getCommentService().deleteComment(pollId, commentId);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/ErrorAction.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/ErrorAction.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/ErrorAction.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,44 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.debux.webmotion.server.WebMotionController;
-import org.debux.webmotion.server.render.Render;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class ErrorAction extends WebMotionController {
-
- public Render on404(Exception e) {
- return renderError(404, e.getMessage());
- }
-
- public Render on500(Exception e) {
- return renderError(500, e.getMessage());
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/FavoriteListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/FavoriteListService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/FavoriteListService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,99 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.FavoriteList;
-import org.chorem.pollen.persistence.entity.FavoriteListMember;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.FavoriteListImportException;
-import org.chorem.pollen.services.exception.FavoriteListMemberEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNameAlreadyUsedException;
-import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
-import org.chorem.pollen.services.exception.FavoriteListNameAlreadyUsedException;
-import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * TODO
- * TODO All method needs a userId connected
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class FavoriteListService extends WebMotionController {
-
- public List<FavoriteList> getFavoriteLists(PollenServiceContext context, String userId) throws EntityNotFoundException {
- List<FavoriteList> favoriteLists = context.getFavoriteListService().getFavoriteLists(userId);
- return favoriteLists;
- }
-
- public FavoriteList getFavoriteList(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
- return context.getFavoriteListService().getFavoriteList(favoriteListId);
- }
-
- public FavoriteList createFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException {
- return context.getFavoriteListService().createFavoriteList(userId, favoriteList);
- }
-
- public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException, FavoriteListNotOwnedByUserException {
- return context.getFavoriteListService().editFavoriteList(userId, favoriteList);
- }
-
- public void deleteFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
- context.getFavoriteListService().deleteFavoriteList(userId, favoriteListId);
- }
-
- public int importFavoriteListMembersFromCsv(PollenServiceContext context, String userId, String favoriteListId, File csvFile) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
- return context.getFavoriteListService().importFavoriteListMembersFromCsv(userId, favoriteListId, csvFile);
- }
-
- public int importFavoriteListMembersFromLdap(PollenServiceContext context, String userId, String favoriteListId, String ldap) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
- return context.getFavoriteListService().importFavoriteListMembersFromLdap(userId, favoriteListId, ldap);
- }
-
- public List<FavoriteListMember> getMembers(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
- List<FavoriteListMember> members = context.getFavoriteListService().getFavoriteListMembers(favoriteListId);
- return members;
- }
-
- public FavoriteListMember getMember(PollenServiceContext context, String memberId) throws EntityNotFoundException {
- return context.getFavoriteListService().getFavoriteListMember(memberId);
- }
-
- public FavoriteListMember addMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException {
- return context.getFavoriteListService().addFavoriteListMember(favoriteListId, member);
- }
-
- public FavoriteListMember editMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException, FavoriteListMemberNotOwnedByFavoriteListException {
- return context.getFavoriteListService().editFavoriteListMember(favoriteListId, member);
- }
-
- public void removeMember(PollenServiceContext context, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
- context.getFavoriteListService().removeFavoriteListMember(favoriteListId, memberId);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,112 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.Choice;
-import org.chorem.pollen.persistence.entity.Poll;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.io.File;
-import java.util.List;
-import java.util.Set;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class PollService extends WebMotionController {
-
- public Set<Poll> getPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
- Set<Poll> polls = context.getPollService().getPolls(userId);
- return polls;
- }
-
- public Set<Poll> getCreatedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
- Set<Poll> polls = context.getPollService().getCreatedPolls(userId);
- return polls;
- }
-
- public Set<Poll> getInvitedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
- Set<Poll> polls = context.getPollService().getInvitedPolls(userId);
- return polls;
- }
-
- public Set<Poll> getParticipatedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
- Set<Poll> polls = context.getPollService().getParticipatedPolls(userId);
- return polls;
- }
-
- public Poll getPoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- return context.getPollService().getPoll(pollId);
- }
-
- public Poll createPoll(PollenServiceContext context, String userId, Poll poll) throws EntityNotFoundException {
- return context.getPollService().createPoll(userId, poll);
- }
-
- public Poll editPoll(PollenServiceContext context, Poll poll) throws EntityNotFoundException {
- return context.getPollService().editPoll(poll);
- }
-
- public void deletePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- context.getPollService().deletePoll(pollId);
- }
-
- public Poll clonePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- return context.getPollService().clonePoll(pollId);
- }
-
- public File closePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- return context.getPollService().closePoll(pollId);
- }
-
- public File exportPoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- return context.getPollService().exportPoll(pollId);
- }
-
- public List<Choice> getChoices(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- List<Choice> choices = context.getPollService().getChoices(pollId);
- return choices;
- }
-
- public Choice getChoice(PollenServiceContext context, String choiceId) throws EntityNotFoundException {
- return context.getPollService().getChoice(choiceId);
- }
-
- public Choice addChoice(PollenServiceContext context, String pollId, Choice choice) throws EntityNotFoundException {
- return context.getPollService().addChoice(pollId, choice);
- }
-
- public Choice editChoice(PollenServiceContext context, Choice choice) throws EntityNotFoundException {
- return context.getPollService().editChoice(choice);
- }
-
- public void deleteChoice(PollenServiceContext context, String pollId, String choiceId) throws EntityNotFoundException {
- context.getPollService().deleteChoice(pollId, choiceId);
- }
-}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenApplicationContext.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenApplicationContext.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenApplicationContext.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenApplicationContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,125 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.pollen.persistence.JpaPollenPersistenceContext;
+import org.chorem.pollen.services.DefaultPollenServiceContext;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.config.PollenServiceConfig;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.Persistence;
+import javax.persistence.PersistenceException;
+import java.io.Closeable;
+import java.util.Map;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenApplicationContext implements Closeable {
+
+ private static final Log log = LogFactory.getLog(PollenApplicationContext.class);
+
+ protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext";
+
+ protected PollenServiceConfig applicationConfig;
+
+ protected EntityManagerFactory entityManagerFactory;
+
+ public PollenServiceConfig getPollenServiceConfig() {
+ if (applicationConfig == null) {
+ applicationConfig = new PollenServiceConfig();
+ }
+ return applicationConfig;
+ }
+
+ public EntityManager newEntityManager() {
+
+ if (entityManagerFactory == null) {
+
+ PollenServiceConfig applicationConfig = getPollenServiceConfig();
+
+ Map<String, String> jpaParameters = applicationConfig.getJpaParameters();
+
+ if (log.isInfoEnabled()) {
+ log.info("creating entity manager factory");
+ }
+
+ try {
+
+ entityManagerFactory = Persistence.createEntityManagerFactory("pollenPersistenceUnit", jpaParameters);
+
+ } catch (PersistenceException e) {
+
+ if (log.isErrorEnabled()) {
+ log.error("unable to create entity manager factory", e);
+ }
+
+ throw e;
+
+ }
+
+ }
+
+ EntityManager entityManager = entityManagerFactory.createEntityManager();
+
+ return entityManager;
+
+ }
+
+ public void close() {
+
+ if (entityManagerFactory != null && entityManagerFactory.isOpen()) {
+
+ if (log.isInfoEnabled()) {
+ log.info("stopping magalie, will close entity manager factory");
+ }
+
+ entityManagerFactory.close();
+
+ }
+
+ }
+
+ public PollenServiceContext newServiceContext(EntityManager entityManager) {
+
+ DefaultPollenServiceContext serviceContext = new DefaultPollenServiceContext();
+
+ JpaPollenPersistenceContext jpaMagaliePersistenceContext =
+ new JpaPollenPersistenceContext(entityManager);
+
+ serviceContext.setPersistenceContext(jpaMagaliePersistenceContext);
+
+ serviceContext.setPollenServiceConfig(applicationConfig);
+
+ return serviceContext;
+
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenJpaTransactionFilter.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenJpaTransactionFilter.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenJpaTransactionFilter.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenJpaTransactionFilter.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,87 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.nuiton.web.filter.JpaTransactionFilter;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceException;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+
+public class PollenJpaTransactionFilter extends JpaTransactionFilter {
+
+ private static final Log log =
+ LogFactory.getLog(PollenJpaTransactionFilter.class);
+
+ protected PollenApplicationContext applicationContext;
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+
+ super.init(filterConfig);
+
+ if (log.isInfoEnabled()) {
+ log.info("Init JPA Filter");
+ }
+
+// applicationContext = PollenServices.getApplicationContext(
+// filterConfig.getServletContext());
+//
+// Preconditions.checkNotNull(applicationContext, "Could not find application context at ServletContext#pollen_PollenApplicationContext");
+ }
+
+ protected PollenApplicationContext getApplicationContext(ServletRequest request) {
+ if (applicationContext == null) {
+ applicationContext = PollenServices.getApplicationContext(
+ request.getServletContext());
+
+ Preconditions.checkNotNull(applicationContext, "Could not find application context at ServletContext#pollen_PollenApplicationContext");
+ }
+ return applicationContext;
+ }
+
+ @Override
+ protected EntityManager createEntityManager(ServletRequest request) {
+
+ EntityManager entityManager;
+
+ try {
+
+ entityManager = getApplicationContext(request).newEntityManager();
+
+ } catch (PersistenceException e) {
+
+ if (log.isErrorEnabled()) {
+ log.error("unable to create entity manager", e);
+ }
+ throw e;
+ }
+ return entityManager;
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenRender.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenRender.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,234 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.gson.Gson;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.debux.webmotion.server.call.Call;
+import org.debux.webmotion.server.call.HttpContext;
+import org.debux.webmotion.server.mapping.Mapping;
+import org.debux.webmotion.server.render.Render;
+import org.nuiton.jpa.api.JpaEntity;
+import org.nuiton.util.ObjectUtil;
+import org.nuiton.util.beans.Binder;
+import org.nuiton.util.beans.BinderFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * To render any entities.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenRender<T> extends Render {
+
+ /**
+ * To specify entity collections to include in binded entities.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public @interface ExposeCollection {
+
+ public String[] values() default {};
+ }
+
+ protected T model;
+
+ public PollenRender(T model) {
+ this.model = model;
+ }
+
+ @Override
+ public void create(Mapping mapping, Call call) throws IOException, ServletException {
+
+ HttpContext context = call.getContext();
+ HttpServletResponse response = context.getResponse();
+ response.setContentType("application/json");
+
+ String[] includeCollection = null;
+ ExposeCollection annotation = call.getCurrent().getMethod().getAnnotation(ExposeCollection.class);
+ if (annotation != null) {
+ includeCollection = annotation.values();
+ }
+ Object map = toMap(model, includeCollection);
+
+ Gson gson = new Gson();
+ String json = gson.toJson(map);
+ PrintWriter out = context.getOut();
+ out.print(json);
+ }
+
+ protected <M> Object toMap(M model, String... includeCollection) {
+ if (model instanceof Iterable<?>) {
+
+ // collection of objects
+ Iterable<?> objects = (Iterable<?>) model;
+ List<Object> result = Lists.newArrayList();
+ for (Object object : objects) {
+ Object objectMap = toMap(object, includeCollection);
+ result.add(objectMap);
+ }
+ return result;
+ }
+
+ // single object
+
+ if (model instanceof JpaEntity) {
+
+ // entity need to transform it
+
+ JpaEntity jpaEntity = (JpaEntity) model;
+
+ PollenEntityBinder<JpaEntity> binder = BinderFactory.newBinder(jpaEntity.getClass(), jpaEntity.getClass(), null, PollenEntityBinder.class);
+ Map<String, Object> map = binder.obtainProperties(jpaEntity);
+ Map<String, Object> result = Maps.newTreeMap();
+
+ for (Map.Entry<String, Object> entry : map.entrySet()) {
+ String propertyName = entry.getKey();
+ Object propertyValue = entry.getValue();
+ if (propertyValue instanceof JpaEntity) {
+ result.put(propertyName, toMap(propertyValue));
+ continue;
+ }
+
+ result.put(propertyName, propertyValue);
+ }
+
+ // treat collections
+
+ if (includeCollection != null) {
+ for (String propertyName : includeCollection) {
+ Iterable<?> collectionValue = binder.getCollectionValue(jpaEntity, propertyName);
+ result.put(propertyName, toMap(collectionValue));
+
+ }
+ }
+ return result;
+ }
+
+ return model;
+ }
+
+ protected static class PollenEntityBinder<E extends JpaEntity> extends Binder<E, E> {
+
+ /** Logger. */
+ private static final Log log =
+ LogFactory.getLog(PollenEntityBinder.class);
+
+ private static final long serialVersionUID = 1L;
+
+ protected List<String> simpleProperties;
+
+ public PollenEntityBinder() {
+ }
+
+ @Override
+ protected void setModel(BinderModel<E, E> model) {
+ super.setModel(model);
+ this.simpleProperties = Lists.newArrayList();
+ for (String property : model.getSourceDescriptors()) {
+ if (model.getCollectionType(property) == null) {
+ simpleProperties.add(property);
+ }
+ }
+ }
+
+ /**
+ * Obtain from the given object all properties registered in the binder
+ * model.
+ *
+ * @param source the bean to read
+ * @return the map of properties obtained indexed by their property name,
+ * or an empty map is the given {@code from} is {@code null}.
+ * @since 2.3
+ */
+ public Map<String, Object> obtainProperties(E source) {
+ if (source == null) {
+ // special limit case
+ return Collections.emptyMap();
+ }
+
+ Map<String, Object> result = Maps.newTreeMap();
+ for (String sourceProperty : simpleProperties) {
+
+
+ try {
+ Object read;
+ Method readMethod = model.getSourceReadMethod(sourceProperty);
+ read = readMethod.invoke(source);
+ if (log.isDebugEnabled()) {
+ log.debug("property " + sourceProperty + ", type : " +
+ readMethod.getReturnType() + ", value = " + read);
+ }
+ if (readMethod.getReturnType().isPrimitive() &&
+ ObjectUtil.getNullValue(
+ readMethod.getReturnType()).equals(read)) {
+ // for primitive type case, force nullity
+ read = null;
+ }
+
+ if (read != null) {
+ result.put(sourceProperty, read);
+ }
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ return result;
+ }
+
+ public Iterable<?> getCollectionValue(E source, String sourceProperty) {
+ try {
+ Method readMethod = model.getSourceReadMethod(sourceProperty);
+ Object result = readMethod.invoke(source);
+ return (Iterable<?>) result;
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceContextFilter.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceContextFilter.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,84 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.commons.lang3.StringUtils;
+import org.chorem.pollen.persistence.entity.SessionToken;
+import org.chorem.pollen.services.PollenSecurityContext;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.InvalidSessionTokenException;
+import org.debux.webmotion.server.WebMotionFilter;
+import org.debux.webmotion.server.call.HttpContext;
+
+import javax.persistence.EntityManager;
+
+/**
+ * Inject le service context dans les controlleurs.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenServiceContextFilter extends WebMotionFilter {
+
+ public static final String REQUEST_AUTH_PARAMETER = "auth";
+
+ public void inject(HttpContext context) throws InvalidSessionTokenException {
+
+ PollenApplicationContext applicationContext =
+ PollenServices.getApplicationContext(context.getServletContext());
+
+ EntityManager entityManager =
+ PollenServices.getEntityManager(context.getRequest());
+
+ PollenServiceContext serviceContext =
+ applicationContext.newServiceContext(entityManager);
+ PollenServices.setServiceContext(context.getRequest(), serviceContext);
+
+ addSecurityContext(context, serviceContext);
+
+ doProcess();
+ }
+
+ protected void addSecurityContext(HttpContext context,
+ PollenServiceContext serviceContext) throws InvalidSessionTokenException {
+
+ String[] strings = context.getParameters().get(REQUEST_AUTH_PARAMETER);
+
+ String authParam = strings == null || strings.length < 1 ? null : strings[1];
+
+ SessionToken sessionToken = null;
+
+ if (StringUtils.isNotBlank(authParam)) {
+
+ // find out the userId from this auth
+
+ sessionToken = serviceContext.getAuthService().getUserByAuth(authParam);
+ }
+ PollenSecurityContext securityContext;
+ securityContext = PollenSecurityContext.newContext(
+ sessionToken == null ? null : sessionToken.getPollenUser()
+ );
+ serviceContext.setSecurityContext(securityContext);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServiceListener.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServiceListener.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,124 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
+import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
+import org.debux.webmotion.server.WebMotionServerListener;
+import org.debux.webmotion.server.call.Call;
+import org.debux.webmotion.server.call.HttpContext;
+import org.debux.webmotion.server.call.ServerContext;
+import org.debux.webmotion.server.handler.ExecutorParametersInjectorHandler;
+import org.debux.webmotion.server.mapping.Mapping;
+
+import javax.persistence.EntityManager;
+import javax.servlet.http.HttpServletRequest;
+import java.lang.reflect.Type;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenServiceListener implements WebMotionServerListener {
+
+ /** Logger. */
+ private static final Log log =
+ LogFactory.getLog(PollenServiceListener.class);
+
+ @Override
+ public void onStart(Mapping mapping, ServerContext serverContext) {
+
+ serverContext.addInjector(new PollenServiceContextInjector());
+ serverContext.addInjector(new SessionTokenInjector());
+
+ // Create application context
+ PollenApplicationContext applicationContext =
+ new PollenApplicationContext();
+
+ // push it in context
+ PollenServices.setApplicationContext(
+ serverContext.getServletContext(), applicationContext);
+
+ EntityManager entityManager = applicationContext.newEntityManager();
+
+ try {
+ PollenServiceContext serviceContext =
+ applicationContext.newServiceContext(entityManager);
+ serviceContext.getUserService().createDefaultUsers();
+ } catch (UserEmailAlreadyUsedException e) {
+ //Can't happen
+ } catch (UserLoginAlreadyUsedException e) {
+ //Can't happen
+ } finally {
+ entityManager.close();
+ }
+ }
+
+ @Override
+ public void onStop(ServerContext serverContext) {
+
+ // Get application context
+ PollenApplicationContext applicationContext =
+ PollenServices.getApplicationContext(
+ serverContext.getServletContext());
+
+ // close it (and all underlined resources)
+ if (applicationContext != null) {
+ applicationContext.close();
+ }
+ }
+
+ protected static class PollenServiceContextInjector implements ExecutorParametersInjectorHandler.Injector {
+ @Override
+ public Object getValue(Mapping mapping, Call call, String name, Class<?> type, Type generic) {
+ PollenServiceContext result = null;
+ if (PollenServiceContext.class.isAssignableFrom(type)) {
+ HttpContext httpContext = call.getContext();
+ HttpServletRequest request = httpContext.getRequest();
+
+ result = PollenServices.getServiceContext(request);
+ }
+ return result;
+ }
+ }
+
+ protected static class SessionTokenInjector implements ExecutorParametersInjectorHandler.Injector {
+ @Override
+ public Object getValue(Mapping mapping, Call call, String name, Class<?> type, Type generic) {
+ PollenServiceContext result = null;
+ if (PollenServiceContext.class.isAssignableFrom(type)) {
+ HttpContext httpContext = call.getContext();
+ HttpServletRequest request = httpContext.getRequest();
+
+ result = PollenServices.getServiceContext(request);
+ }
+ return result;
+ }
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServices.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/PollenServices.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServices.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollenServices.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,89 @@
+package org.chorem.pollen.rest.api;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.SessionToken;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.nuiton.web.filter.JpaTransactionFilter;
+
+import javax.persistence.EntityManager;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenServices {
+
+ protected static final String APPLICATION_CONTEXT_PARAMETER = "pollen_PollenApplicationContext";
+
+ protected static final String REQUEST_POLLEN_SERVICE_CONTEXT = "pollen_PollenServiceContext";
+
+ protected static final String REQUEST_POLLEN_CONNECTED_USER = "pollen_PollenConnectedUser";
+
+ protected static final String REQUEST_ENTITY_MANAGER = JpaTransactionFilter.JPA_TRANSACTION_REQUEST_ATTRIBUTE;
+
+ public static PollenApplicationContext getApplicationContext(ServletContext servletContext) {
+ PollenApplicationContext result = (PollenApplicationContext)
+ servletContext.getAttribute(APPLICATION_CONTEXT_PARAMETER);
+ return result;
+ }
+
+ public static void setApplicationContext(ServletContext servletContext,
+ PollenApplicationContext applicationContext) {
+ servletContext.setAttribute(APPLICATION_CONTEXT_PARAMETER, applicationContext);
+ }
+
+
+ public static PollenServiceContext getServiceContext(HttpServletRequest request) {
+ PollenServiceContext result = (PollenServiceContext)
+ request.getAttribute(REQUEST_POLLEN_SERVICE_CONTEXT);
+ return result;
+ }
+
+ public static void setServiceContext(HttpServletRequest request,
+ PollenServiceContext serviceContext) {
+ request.setAttribute(REQUEST_POLLEN_SERVICE_CONTEXT, serviceContext);
+ }
+
+ public static EntityManager getEntityManager(HttpServletRequest request) {
+ EntityManager result = (EntityManager)
+ request.getAttribute(REQUEST_ENTITY_MANAGER);
+ return result;
+ }
+
+ public static SessionToken getSessionToken(HttpServletRequest request) {
+ SessionToken result = (SessionToken)
+ request.getAttribute(REQUEST_POLLEN_CONNECTED_USER);
+ return result;
+ }
+
+ public static void setSessionToken(HttpServletRequest request,
+ SessionToken sessionToken) {
+ request.setAttribute(REQUEST_POLLEN_CONNECTED_USER, sessionToken);
+ }
+}
\ No newline at end of file
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/UserService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/UserService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/UserService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,79 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.PollenUser;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
-import org.chorem.pollen.services.exception.UserInvalidEmailActiviationTokenException;
-import org.chorem.pollen.services.exception.UserInvalidPasswordException;
-import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class UserService extends WebMotionController {
-
- public List<PollenUser> getUsers(PollenServiceContext context) {
- List<PollenUser> users = context.getUserService().getUsers();
- return users;
- }
-
- public PollenUser getUser(PollenServiceContext context,
- String userId) throws EntityNotFoundException {
- return context.getUserService().getUser(userId);
- }
-
- public PollenUser createUser(PollenServiceContext context,
- PollenUser user,
- boolean generatePassword) throws UserEmailAlreadyUsedException, UserLoginAlreadyUsedException {
- return context.getUserService().createUser(user, generatePassword);
-
- }
-
- public PollenUser editUser(PollenServiceContext context,
- PollenUser user) throws UserInvalidPasswordException, UserEmailAlreadyUsedException, EntityNotFoundException {
- return context.getUserService().editUser(user);
- }
-
- public void validateUserEmail(PollenServiceContext context,
- String userId,
- String token) throws EntityNotFoundException, UserInvalidEmailActiviationTokenException {
- context.getUserService().validateUserEmail(userId, token);
- }
-
- public void changePassword(PollenServiceContext context,
- String userId,
- String oldPassword,
- String newPassword) throws UserInvalidPasswordException, EntityNotFoundException {
- context.getUserService().changePassword(userId, oldPassword, newPassword);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteCountingService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteCountingService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteCountingService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,42 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.services.PollResult;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.debux.webmotion.server.WebMotionController;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class VoteCountingService extends WebMotionController {
-
- public PollResult getResult(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- return context.getVoteCountingService().getResult(pollId);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,61 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.Vote;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.util.List;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class VoteService extends WebMotionController {
-
- public List<Vote> getVotes(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- List<Vote> votes = context.getVoteService().getVotes(pollId);
- return votes;
- }
-
- public Vote getVote(PollenServiceContext context, String voteId) throws EntityNotFoundException {
- return context.getVoteService().getVote(voteId);
- }
-
- public Vote addVote(PollenServiceContext context, String pollId, Vote vote) throws EntityNotFoundException {
- return context.getVoteService().addVote(pollId, vote);
- }
-
- public Vote editVote(PollenServiceContext context, Vote vote) throws EntityNotFoundException {
- return context.getVoteService().editVote(vote);
- }
-
- public void deleteVote(PollenServiceContext context, String pollId, String voteId) throws EntityNotFoundException {
- context.getVoteService().deleteVote(pollId, voteId);
- }
-}
Deleted: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoterListService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoterListService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoterListService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,88 +0,0 @@
-package org.chorem.pollen.rest.api;
-
-/*
- * #%L
- * Pollen :: Rest Api
- * $Id$
- * $HeadURL$
- * %%
- * Copyright (C) 2009 - 2013 CodeLutin
- * %%
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- * #L%
- */
-
-import org.chorem.pollen.persistence.entity.VoterList;
-import org.chorem.pollen.persistence.entity.VoterListMember;
-import org.chorem.pollen.services.PollenServiceContext;
-import org.chorem.pollen.services.exception.EntityNotFoundException;
-import org.debux.webmotion.server.WebMotionController;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * TODO
- *
- * @author tchemit <chemit(a)codelutin.com>
- * @since 2.0
- */
-public class VoterListService extends WebMotionController {
-
- public VoterList importFavoriteList(PollenServiceContext context, String pollId, String favoriteListId) throws EntityNotFoundException {
- return context.getVoterListService().importFavoriteList(pollId, favoriteListId);
- }
-
- public List<VoterList> getVoterLists(PollenServiceContext context, String pollId) throws EntityNotFoundException {
- List<VoterList> voterLists = context.getVoterListService().getVoterLists(pollId);
- return voterLists;
- }
-
- public VoterList getVoterList(PollenServiceContext context, String voterListId) throws EntityNotFoundException {
- return context.getVoterListService().getVoterList(voterListId);
- }
-
- public VoterList addVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException {
- return context.getVoterListService().addVoterList(pollId, voterList);
- }
-
- public VoterList editVoterList(PollenServiceContext context, VoterList voterList) throws EntityNotFoundException {
- return context.getVoterListService().editVoterList(voterList);
- }
-
- public void deleteVoterList(PollenServiceContext context, String pollId, String voterListId) throws EntityNotFoundException {
- context.getVoterListService().deleteVoterList(pollId, voterListId);
- }
-
- public Set<VoterListMember> getMembers(PollenServiceContext context, String voterListId) throws EntityNotFoundException {
- Set<VoterListMember> members = context.getVoterListService().getMembers(voterListId);
- return members;
- }
-
- public VoterListMember getMember(PollenServiceContext context, String memberId) throws EntityNotFoundException {
- return context.getVoterListService().getMember(memberId);
- }
-
- public VoterListMember addMember(PollenServiceContext context, String voterListId, VoterListMember member) throws EntityNotFoundException {
- return context.getVoterListService().addMember(voterListId, member);
- }
-
- public VoterListMember editMember(PollenServiceContext context, VoterListMember member) throws EntityNotFoundException {
- return context.getVoterListService().editMember(member);
- }
-
- public void deleteMember(PollenServiceContext context, String voterListId, String memberId) throws EntityNotFoundException {
- context.getVoterListService().deleteMember(voterListId, memberId);
- }
-}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/AuthService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/AuthService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,50 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.UserInvalidPasswordException;
+import org.debux.webmotion.server.WebMotionController;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class AuthService extends WebMotionController {
+
+ public String login(PollenServiceContext context, String login, String password) throws UserInvalidPasswordException, EntityNotFoundException {
+ return context.getAuthService().login(login, password);
+ }
+
+ public void lostPassword(PollenServiceContext context, String login) throws EntityNotFoundException {
+ context.getAuthService().lostPassword(login);
+ }
+
+ public void logout(PollenServiceContext context, String login, String token) throws EntityNotFoundException {
+ context.getAuthService().logout(login, token);
+ }
+}
Added: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,62 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.Choice;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidChoiceFormException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class ChoiceService extends WebMotionController {
+
+ public List<Choice> getChoices(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ List<Choice> choices = context.getChoiceService().getChoices(pollId);
+ return choices;
+ }
+
+ public Choice getChoice(PollenServiceContext context, String pollId, String choiceId) throws EntityNotFoundException {
+ return context.getChoiceService().getChoice(pollId, choiceId);
+ }
+
+ public Choice addChoice(PollenServiceContext context, String pollId, Choice choice) throws EntityNotFoundException, InvalidChoiceFormException {
+ return context.getChoiceService().addChoice(pollId, choice);
+ }
+
+ public Choice editChoice(PollenServiceContext context, String pollId, Choice choice) throws EntityNotFoundException, InvalidChoiceFormException {
+ return context.getChoiceService().editChoice(pollId, choice);
+ }
+
+ public void deleteChoice(PollenServiceContext context, String pollId, String choiceId) throws EntityNotFoundException {
+ context.getChoiceService().deleteChoice(pollId, choiceId);
+ }
+}
\ No newline at end of file
Property changes on: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ChoiceService.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/CommentService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/CommentService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,61 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.Comment;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class CommentService extends WebMotionController {
+
+ public List<Comment> getComments(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ List<Comment> comments = context.getCommentService().getComments(pollId);
+ return comments;
+ }
+
+ public Comment getComment(PollenServiceContext context, String commentId) throws EntityNotFoundException {
+ return context.getCommentService().getComment(commentId);
+ }
+
+ public Comment addComment(PollenServiceContext context, String pollId, Comment comment) throws EntityNotFoundException {
+ return context.getCommentService().addComment(pollId, comment);
+ }
+
+ public Comment editComment(PollenServiceContext context,Comment comment) throws EntityNotFoundException {
+ return context.getCommentService().editComment(comment);
+ }
+
+ public void deleteComment(PollenServiceContext context, String pollId, String commentId) throws EntityNotFoundException {
+ context.getCommentService().deleteComment(pollId, commentId);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/ErrorAction.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/ErrorAction.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,55 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+import org.chorem.pollen.services.exception.AbstractInvalidFormException;
+import org.debux.webmotion.server.WebMotionController;
+import org.debux.webmotion.server.render.Render;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class ErrorAction extends WebMotionController {
+
+ public Render on404(Exception e) {
+ return renderError(404, e.getMessage());
+ }
+
+ public Render on500(Exception e) {
+ return renderError(500, e.getMessage());
+ }
+
+ public Render on500Form(Exception e) {
+ AbstractInvalidFormException ex = (AbstractInvalidFormException) e;
+
+ //TODO Send back this
+ Multimap<String, String> errors = ex.getErrors();
+
+ return renderError(500, e.getMessage());
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/FavoriteListService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/FavoriteListService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,99 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.FavoriteList;
+import org.chorem.pollen.persistence.entity.FavoriteListMember;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.FavoriteListImportException;
+import org.chorem.pollen.services.exception.FavoriteListMemberEmailAlreadyUsedException;
+import org.chorem.pollen.services.exception.FavoriteListMemberNameAlreadyUsedException;
+import org.chorem.pollen.services.exception.FavoriteListMemberNotOwnedByFavoriteListException;
+import org.chorem.pollen.services.exception.FavoriteListNameAlreadyUsedException;
+import org.chorem.pollen.services.exception.FavoriteListNotOwnedByUserException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * TODO
+ * TODO All method needs a userId connected
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class FavoriteListService extends WebMotionController {
+
+ public List<FavoriteList> getFavoriteLists(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ List<FavoriteList> favoriteLists = context.getFavoriteListService().getFavoriteLists(userId);
+ return favoriteLists;
+ }
+
+ public FavoriteList getFavoriteList(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
+ return context.getFavoriteListService().getFavoriteList(favoriteListId);
+ }
+
+ public FavoriteList createFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException {
+ return context.getFavoriteListService().createFavoriteList(userId, favoriteList);
+ }
+
+ public FavoriteList editFavoriteList(PollenServiceContext context, String userId, FavoriteList favoriteList) throws EntityNotFoundException, FavoriteListNameAlreadyUsedException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().editFavoriteList(userId, favoriteList);
+ }
+
+ public void deleteFavoriteList(PollenServiceContext context, String userId, String favoriteListId) throws EntityNotFoundException, FavoriteListNotOwnedByUserException {
+ context.getFavoriteListService().deleteFavoriteList(userId, favoriteListId);
+ }
+
+ public int importFavoriteListMembersFromCsv(PollenServiceContext context, String userId, String favoriteListId, File csvFile) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().importFavoriteListMembersFromCsv(userId, favoriteListId, csvFile);
+ }
+
+ public int importFavoriteListMembersFromLdap(PollenServiceContext context, String userId, String favoriteListId, String ldap) throws EntityNotFoundException, FavoriteListImportException, FavoriteListNotOwnedByUserException {
+ return context.getFavoriteListService().importFavoriteListMembersFromLdap(userId, favoriteListId, ldap);
+ }
+
+ public List<FavoriteListMember> getMembers(PollenServiceContext context, String favoriteListId) throws EntityNotFoundException {
+ List<FavoriteListMember> members = context.getFavoriteListService().getFavoriteListMembers(favoriteListId);
+ return members;
+ }
+
+ public FavoriteListMember getMember(PollenServiceContext context, String memberId) throws EntityNotFoundException {
+ return context.getFavoriteListService().getFavoriteListMember(memberId);
+ }
+
+ public FavoriteListMember addMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException {
+ return context.getFavoriteListService().addFavoriteListMember(favoriteListId, member);
+ }
+
+ public FavoriteListMember editMember(PollenServiceContext context, String favoriteListId, FavoriteListMember member) throws EntityNotFoundException, FavoriteListMemberEmailAlreadyUsedException, FavoriteListMemberNameAlreadyUsedException, FavoriteListMemberNotOwnedByFavoriteListException {
+ return context.getFavoriteListService().editFavoriteListMember(favoriteListId, member);
+ }
+
+ public void removeMember(PollenServiceContext context, String favoriteListId, String memberId) throws EntityNotFoundException, FavoriteListMemberNotOwnedByFavoriteListException {
+ context.getFavoriteListService().removeFavoriteListMember(favoriteListId, memberId);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/PollService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/PollService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,95 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.ChoiceType;
+import org.chorem.pollen.persistence.entity.Poll;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollFormException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollService extends WebMotionController {
+
+ public Poll getNewPoll(PollenServiceContext context, String userId, ChoiceType choiceType) throws EntityNotFoundException {
+ return context.getPollService().getNewPoll(userId, choiceType);
+ }
+
+ public Set<Poll> getPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ Set<Poll> polls = context.getPollService().getPolls(userId);
+ return polls;
+ }
+
+ public Set<Poll> getCreatedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ Set<Poll> polls = context.getPollService().getCreatedPolls(userId);
+ return polls;
+ }
+
+ public Set<Poll> getInvitedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ Set<Poll> polls = context.getPollService().getInvitedPolls(userId);
+ return polls;
+ }
+
+ public Set<Poll> getParticipatedPolls(PollenServiceContext context, String userId) throws EntityNotFoundException {
+ Set<Poll> polls = context.getPollService().getParticipatedPolls(userId);
+ return polls;
+ }
+
+ public Poll getPoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ return context.getPollService().getPoll(pollId);
+ }
+
+ public Poll createPoll(PollenServiceContext context, String userId, Poll poll) throws EntityNotFoundException, InvalidPollFormException {
+ return context.getPollService().createPoll(userId, poll);
+ }
+
+ public Poll editPoll(PollenServiceContext context, Poll poll) throws EntityNotFoundException, InvalidPollFormException {
+ return context.getPollService().editPoll(poll);
+ }
+
+ public void deletePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ context.getPollService().deletePoll(pollId);
+ }
+
+ public Poll clonePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ return context.getPollService().clonePoll(pollId);
+ }
+
+ public File closePoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ return context.getPollService().closePoll(pollId);
+ }
+
+ public File exportPoll(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ return context.getPollService().exportPoll(pollId);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/UserService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/UserService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,79 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.PollenUser;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.UserEmailAlreadyUsedException;
+import org.chorem.pollen.services.exception.UserInvalidEmailActiviationTokenException;
+import org.chorem.pollen.services.exception.UserInvalidPasswordException;
+import org.chorem.pollen.services.exception.UserLoginAlreadyUsedException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class UserService extends WebMotionController {
+
+ public List<PollenUser> getUsers(PollenServiceContext context) {
+ List<PollenUser> users = context.getUserService().getUsers();
+ return users;
+ }
+
+ public PollenUser getUser(PollenServiceContext context,
+ String userId) throws EntityNotFoundException {
+ return context.getUserService().getUser(userId);
+ }
+
+ public PollenUser createUser(PollenServiceContext context,
+ PollenUser user,
+ boolean generatePassword) throws UserEmailAlreadyUsedException, UserLoginAlreadyUsedException {
+ return context.getUserService().createUser(user, generatePassword);
+
+ }
+
+ public PollenUser editUser(PollenServiceContext context,
+ PollenUser user) throws UserInvalidPasswordException, UserEmailAlreadyUsedException, EntityNotFoundException {
+ return context.getUserService().editUser(user);
+ }
+
+ public void validateUserEmail(PollenServiceContext context,
+ String userId,
+ String token) throws EntityNotFoundException, UserInvalidEmailActiviationTokenException {
+ context.getUserService().validateUserEmail(userId, token);
+ }
+
+ public void changePassword(PollenServiceContext context,
+ String userId,
+ String oldPassword,
+ String newPassword) throws UserInvalidPasswordException, EntityNotFoundException {
+ context.getUserService().changePassword(userId, oldPassword, newPassword);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteCountingService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteCountingService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteCountingService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteCountingService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,42 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.services.PollResult;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.debux.webmotion.server.WebMotionController;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class VoteCountingService extends WebMotionController {
+
+ public PollResult getResult(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ return context.getVoteCountingService().getResult(pollId);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoteService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoteService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,61 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.Vote;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class VoteService extends WebMotionController {
+
+ public List<Vote> getVotes(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ List<Vote> votes = context.getVoteService().getVotes(pollId);
+ return votes;
+ }
+
+ public Vote getVote(PollenServiceContext context, String voteId) throws EntityNotFoundException {
+ return context.getVoteService().getVote(voteId);
+ }
+
+ public Vote addVote(PollenServiceContext context, String pollId, Vote vote) throws EntityNotFoundException {
+ return context.getVoteService().addVote(pollId, vote);
+ }
+
+ public Vote editVote(PollenServiceContext context, Vote vote) throws EntityNotFoundException {
+ return context.getVoteService().editVote(vote);
+ }
+
+ public void deleteVote(PollenServiceContext context, String pollId, String voteId) throws EntityNotFoundException {
+ context.getVoteService().deleteVote(pollId, voteId);
+ }
+}
Copied: trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java (from rev 3825, trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/VoterListService.java)
===================================================================
--- trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java (rev 0)
+++ trunk/pollen-rest-api/src/main/java/org/chorem/pollen/rest/api/v1/VoterListService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,88 @@
+package org.chorem.pollen.rest.api.v1;
+
+/*
+ * #%L
+ * Pollen :: Rest Api
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.entity.VoterList;
+import org.chorem.pollen.persistence.entity.VoterListMember;
+import org.chorem.pollen.services.PollenServiceContext;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.debux.webmotion.server.WebMotionController;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class VoterListService extends WebMotionController {
+
+ public VoterList importFavoriteList(PollenServiceContext context, String pollId, String favoriteListId) throws EntityNotFoundException {
+ return context.getVoterListService().importFavoriteList(pollId, favoriteListId);
+ }
+
+ public List<VoterList> getVoterLists(PollenServiceContext context, String pollId) throws EntityNotFoundException {
+ List<VoterList> voterLists = context.getVoterListService().getVoterLists(pollId);
+ return voterLists;
+ }
+
+ public VoterList getVoterList(PollenServiceContext context, String pollId, String voterListId) throws EntityNotFoundException {
+ return context.getVoterListService().getVoterList(pollId, voterListId);
+ }
+
+ public VoterList addVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException {
+ return context.getVoterListService().addVoterList(pollId, voterList);
+ }
+
+ public VoterList editVoterList(PollenServiceContext context, String pollId, VoterList voterList) throws EntityNotFoundException {
+ return context.getVoterListService().editVoterList(pollId, voterList);
+ }
+
+ public void deleteVoterList(PollenServiceContext context, String pollId, String voterListId) throws EntityNotFoundException {
+ context.getVoterListService().deleteVoterList(pollId, voterListId);
+ }
+
+ public Set<VoterListMember> getMembers(PollenServiceContext context, String pollId, String voterListId) throws EntityNotFoundException {
+ Set<VoterListMember> members = context.getVoterListService().getMembers(pollId, voterListId);
+ return members;
+ }
+
+ public VoterListMember getMember(PollenServiceContext context, String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ return context.getVoterListService().getMember(pollId, voterListId, memberId);
+ }
+
+ public VoterListMember addMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ return context.getVoterListService().addMember(pollId, voterListId, member);
+ }
+
+ public VoterListMember editMember(PollenServiceContext context, String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ return context.getVoterListService().editMember(pollId, voterListId, member);
+ }
+
+ public void deleteMember(PollenServiceContext context, String pollId, String voterListId, String memberId) throws EntityNotFoundException {
+ context.getVoterListService().deleteMember(pollId, voterListId, memberId);
+ }
+}
Modified: trunk/pollen-rest-api/src/main/resources/mapping
===================================================================
--- trunk/pollen-rest-api/src/main/resources/mapping 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/resources/mapping 2013-06-15 10:58:03 UTC (rev 3830)
@@ -7,8 +7,6 @@
[filters]
* /* PollenServiceContextFilter.inject
-#* /* PollenIdOrTokenInjector.inject
-#* /* PollenSecurityFilter.inject (prend le param auth pour retrouver le PollenUser)
#- une fois un object lié à PollenUser, c'est immuable.
@@ -19,89 +17,93 @@
org.chorem.pollen.service.exception.UserLoginAlreadyUsedException ErrorAction.on500
org.chorem.pollen.service.exception.UserInvalidPasswordException ErrorAction.on500
org.chorem.pollen.service.exception.UserInvalidEmailActiviationTokenException ErrorAction.on500
+org.chorem.pollen.service.exception.AbstractInvalidFormException ErrorAction.on500Form
[actions]
# AuthService
-PUT /login AuthService.login
-GET /lostpassword/{token} AuthService.lostPassword
-GET /logout AuthService.logout
+PUT /v1/login AuthService.login
+GET /v1/lostpassword/{token} AuthService.lostPassword
+GET /v1/logout AuthService.logout
+# ChoiceService
+
+GET /v1/polls/{pollId}/choices ChoiceService.getChoices
+POST /v1/polls/{pollId}/choices ChoiceService.addChoice
+GET /v1/polls/{pollId}/choices/{choiceId} ChoiceService.getChoice
+PUT /v1/polls/{pollId}/choices/{choiceId} ChoiceService.editChoice
+DELETE /v1/polls/{pollId}/choices/{choiceId} ChoiceService.deleteChoice
+
# CommentService
-GET /polls/{pollId}/comments CommentService.getComments
-POST /polls/{pollId}/comments CommentService.addComment
-GET /comments/{commentId} CommentService.getComment
-PUT /comments/{commentId} CommentService.editComment
-DELETE /polls/{pollId}/comments/{commentId} CommentService.deleteComment
+GET /v1/polls/{pollId}/comments CommentService.getComments
+POST /v1/polls/{pollId}/comments CommentService.addComment
+GET /v1/polls/{pollId}/comments/{commentId} CommentService.getComment
+PUT /v1/polls/{pollId}/comments/{commentId} CommentService.editComment
+DELETE /v1/polls/{pollId}/comments/{commentId} CommentService.deleteComment
# FavoriteListService
-GET /favoriteLists FavoriteListService.getFavoriteLists
-GET /favoriteLists/{flId} FavoriteListService.getFavoriteList
-POST /favoriteLists/{flId}/importCsv FavoriteListService.importFavoriteListMemberFromCsv
-POST /favoriteLists/{flId}/importLdap FavoriteListService.importFavoriteListMemberFromLdap
-POST /favoriteLists FavoriteListService.createFavoriteList
-PUT /favoriteLists/{flId} FavoriteListService.editFavoriteList
-DELETE /favoriteLists/{flId} FavoriteListService.deleteFavoriteList
-GET /favoriteLists/{flId}/members FavoriteListService.getMembers
-GET /favoriteListMembers/{mId} FavoriteListService.getMember
-POST /favoriteLists/{flId}/members FavoriteListService.addMember
-PUT /favoriteLists/{flId}/members/{mId} FavoriteListService.editMember
-DELETE /favoriteLists/{flId}/members/{mId} FavoriteListService.removeMember
+GET /v1/favoriteLists FavoriteListService.getFavoriteLists
+GET /v1/favoriteLists/{flId} FavoriteListService.getFavoriteList
+POST /v1/favoriteLists/{flId}/importCsv FavoriteListService.importFavoriteListMemberFromCsv
+POST /v1/favoriteLists/{flId}/importLdap FavoriteListService.importFavoriteListMemberFromLdap
+POST /v1/favoriteLists FavoriteListService.createFavoriteList
+PUT /v1/favoriteLists/{flId} FavoriteListService.editFavoriteList
+DELETE /v1/favoriteLists/{flId} FavoriteListService.deleteFavoriteList
+GET /v1/favoriteLists/{flId}/members FavoriteListService.getMembers
+GET /v1/favoriteLists/{flId}/members/{mId} FavoriteListService.getMember
+POST /v1/favoriteLists/{flId}/members FavoriteListService.addMember
+PUT /v1/favoriteLists/{flId}/members/{mId} FavoriteListService.editMember
+DELETE /v1/favoriteLists/{flId}/members/{mId} FavoriteListService.removeMember
# PollService
-GET /polls PollService.getPolls
-GET /polls/created PollService.getCreatedPolls
-GET /polls/invited PollService.getInvitedPolls
-GET /polls/participated PollService.getParticipatedPolls
-POST /polls PollService.createPoll
-PUT /polls/{pollId} PollService.editPoll
-GET /polls/{pollId} PollService.getPoll
-DELETE /polls/{pollId} PollService.deletePoll
-POST /polls/{pollId} PollService.clonePoll
-GET /polls/{pollId}/export PollService.exportPoll
-PUT /polls/{pollId}/close PollService.closePoll
+GET /v1/polls/new PollService.getNewPoll
+GET /v1/polls PollService.getPolls
+GET /v1/polls/created PollService.getCreatedPolls
+GET /v1/polls/invited PollService.getInvitedPolls
+GET /v1/polls/participated PollService.getParticipatedPolls
+POST /v1/polls PollService.createPoll
+PUT /v1/polls/{pollId} PollService.editPoll
+GET /v1/polls/{pollId} PollService.getPoll
+DELETE /v1/polls/{pollId} PollService.deletePoll
+POST /v1/polls/{pollId} PollService.clonePoll
+GET /v1/polls/{pollId}/export PollService.exportPoll
+PUT /v1/polls/{pollId}/close PollService.closePoll
-GET /polls/{pollId}/choices PollService.getChoices
-POST /polls/{pollId}/choices PollService.addChoice
-GET /choices/{choiceId} PollService.getChoice
-PUT /choices/{choiceId} PollService.editChoice
-DELETE /polls/{pollId}/choices/{choiceId} PollService.deleteChoice
-
# UserService
-GET /users UserService.getUsers
-GET /users/{userId} UserService.getUser
-POST /users UserService.createUser
-PUT /users/{userId} UserService.editUser
-PUT /users/{userId}?token={} UserService.validateUserEmail
+GET /v1/users UserService.getUsers
+GET /v1/users/{userId} UserService.getUser
+POST /v1/users UserService.createUser
+PUT /v1/users/{userId} UserService.editUser
+PUT /v1/users/{userId}?token={} UserService.validateUserEmail
# VoteCountingService
-GET /polls/{pollId}/results VoteCountingService.getResult
+GET /v1/polls/{pollId}/results VoteCountingService.getResult
# VoterListService
-PUT /polls/{pollId}/favoriteLists/{flId} VoterListService.importFavoriteList
-GET /polls/{pollId}/voterLists VoterListService.getVoterLists
-GET /voterLists/{vlId} VoterListService.getVoterList
-POST /voterLists VoterListService.createVoterList
-PUT /voterLists/{vlId} VoterListService.editVoterList
-DELETE /polls/{pollId}/voterLists/{vlId} VoterListService.deleteVoterList
+PUT /v1/polls/{pollId}/favoriteLists/{flId} VoterListService.importFavoriteList
+GET /v1/polls/{pollId}/voterLists VoterListService.getVoterLists
+GET /v1/polls/{pollId}/voterLists/{vlId} VoterListService.getVoterList
+POST /v1/polls/{pollId}/voterLists VoterListService.createVoterList
+PUT /v1/polls/{pollId}/voterLists/{vlId} VoterListService.editVoterList
+DELETE /v1/polls/{pollId}/voterLists/{vlId} VoterListService.deleteVoterList
-GET /voterLists/{vlId}/members VoterListService.getMembers
-GET /voterListMembers/{mId} VoterListService.getMember
-POST /voterLists/{vlId}/members VoterListService.addMember
-PUT /voterListMembers/{mId} VoterListService.editMember
-DELETE /voterLists/{vlId}/members/{mId} VoterListService.deleteMember
+GET /v1/polls/{pollId}/voterLists/{vlId}/members VoterListService.getMembers
+GET /v1/polls/{pollId}/voterLists/{vlId}/members/{mId} VoterListService.getMember
+POST /v1/polls/{pollId}/voterLists/{vlId}/members VoterListService.addMember
+PUT /v1/polls/{pollId}/voterLists/{vlId}/members/{mId} VoterListService.editMember
+DELETE /v1/polls/{pollId}/voterLists/{vlId}/members/{mId} VoterListService.deleteMember
# VoteService
-GET /polls/{pollId}/votes VoteService.getVotes
-PUT /polls/{pollId}/votes VoteService.addVote
-GET /votes/{voteId} VoteService.getVote
-PUT /votes/{voteId} VoteService.editVote
-DELETE /polls/{pollId}/votes/{voteId} VoteService.deleteVote
+GET /v1/polls/{pollId}/votes VoteService.getVotes
+PUT /v1/polls/{pollId}/votes VoteService.addVote
+GET /v1/polls/{pollId}/votes/{voteId} VoteService.getVote
+PUT /v1/polls/{pollId}/votes/{voteId} VoteService.editVote
+DELETE /v1/polls/{pollId}/votes/{voteId} VoteService.deleteVote
Modified: trunk/pollen-rest-api/src/main/webapp/WEB-INF/web.xml
===================================================================
--- trunk/pollen-rest-api/src/main/webapp/WEB-INF/web.xml 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/main/webapp/WEB-INF/web.xml 2013-06-15 10:58:03 UTC (rev 3830)
@@ -33,7 +33,7 @@
<filter>
<filter-name>jpaTransaction</filter-name>
<filter-class>
- org.chorem.pollen.rest.PollenJpaTransactionFilter
+ org.chorem.pollen.rest.api.PollenJpaTransactionFilter
</filter-class>
</filter>
Modified: trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java
===================================================================
--- trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/test/java/org/chorem/pollen/rest/api/AbstractPollenRestApiTest.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -24,7 +24,6 @@
*/
import org.chorem.pollen.persistence.JpaPollenPersistenceContext;
-import org.chorem.pollen.rest.PollenApplicationContext;
import org.chorem.pollen.services.service.FixturesService;
import org.chorem.pollen.services.PollenFixtures;
import org.chorem.pollen.services.PollenServiceContext;
Modified: trunk/pollen-rest-api/src/test/resources/pollen.properties
===================================================================
--- trunk/pollen-rest-api/src/test/resources/pollen.properties 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-rest-api/src/test/resources/pollen.properties 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,3 +1,25 @@
+###
+# #%L
+# Pollen :: Rest Api
+# $Id$
+# $HeadURL$
+# %%
+# Copyright (C) 2009 - 2013 CodeLutin
+# %%
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# #L%
+###
javax.persistence.jdbc.driver=org.h2.Driver
javax.persistence.jdbc.url=jdbc:h2:file:target/pollen/h2data
javax.persistence.jdbc.user=sa
Modified: trunk/pollen-services/pom.xml
===================================================================
--- trunk/pollen-services/pom.xml 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/pom.xml 2013-06-15 10:58:03 UTC (rev 3830)
@@ -99,6 +99,11 @@
</dependency>
<dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-core</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/DefaultPollenServiceContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -28,11 +28,13 @@
import org.chorem.pollen.persistence.PollenPersistenceContext;
import org.chorem.pollen.services.config.PollenServiceConfig;
import org.chorem.pollen.services.service.AuthService;
+import org.chorem.pollen.services.service.ChoiceService;
import org.chorem.pollen.services.service.CommentService;
import org.chorem.pollen.services.service.EmailService;
import org.chorem.pollen.services.service.FavoriteListService;
import org.chorem.pollen.services.service.FixturesService;
import org.chorem.pollen.services.service.PollService;
+import org.chorem.pollen.services.service.SecurityService;
import org.chorem.pollen.services.service.UserService;
import org.chorem.pollen.services.service.VoteCountingService;
import org.chorem.pollen.services.service.VoteService;
@@ -50,6 +52,8 @@
protected PollenPersistenceContext persistenceContext;
+ protected PollenSecurityContext securityContext;
+
protected Locale locale;
public void setPollenServiceConfig(PollenServiceConfig pollenServiceConfig) {
@@ -60,6 +64,10 @@
this.persistenceContext = persistenceContext;
}
+ public void setSecurityContext(PollenSecurityContext securityContext) {
+ this.securityContext = securityContext;
+ }
+
public void setLocale(Locale locale) {
this.locale = locale;
}
@@ -80,6 +88,11 @@
return now;
}
+ @Override
+ public PollenSecurityContext getSecurityContext() {
+ return securityContext;
+ }
+
public String generatePassword() {
return RandomStringUtils.randomAlphanumeric(8);
}
@@ -95,6 +108,11 @@
}
@Override
+ public ChoiceService getChoiceService() {
+ return newService(ChoiceService.class);
+ }
+
+ @Override
public CommentService getCommentService() {
return newService(CommentService.class);
}
@@ -140,6 +158,11 @@
}
@Override
+ public SecurityService getSecurityService() {
+ return newService(SecurityService.class);
+ }
+
+ @Override
public String encodePassword(String password) {
return StringUtil.encodeMD5(password);
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityContext.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityContext.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,10 +1,178 @@
package org.chorem.pollen.services;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.collections.CollectionUtils;
+import org.chorem.pollen.persistence.entity.PollenUser;
+import org.nuiton.jpa.api.JpaEntity;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
+
/**
* TODO
*
* @author tchemit <chemit(a)codelutin.com>
* @since 2.0
*/
-public class PollenSecurityContext {
+public class PollenSecurityContext implements Serializable {
+
+ private static final long serialVersionUID = 5348851531764083245L;
+
+ /**
+ * Connected user account.
+ * <p/>
+ * Can be {@code null} if user is not connected.
+ *
+ * @since 2.0
+ */
+ protected final PollenUser connectedUser;
+
+ /**
+ * Resource to edit/delete (can be null for some creation contexts).
+ *
+ * @since 2.0
+ */
+ protected ObjectSecurityContext<?> resource;
+
+ /**
+ * User roles on the poll.
+ *
+ * @since 2.0
+ */
+ protected Set<PollenUserSecurityRole> userRoles;
+
+ public static PollenSecurityContext newContext(PollenUser userAccount) {
+ PollenSecurityContext result = new PollenSecurityContext(
+ userAccount);
+ return result;
+ }
+
+ public static <E extends JpaEntity> ObjectSecurityContext<E> ObjectSecurityContext(Class<E> type,
+ String id,
+ String token) {
+ return new ObjectSecurityContext<E>(type, id, token);
+ }
+
+ public void setResource(ObjectSecurityContext<?> resource) {
+ this.resource = resource;
+ }
+
+ public void setUserRoles(Set<PollenUserSecurityRole> userRoles) {
+ this.userRoles = userRoles == null ? null : ImmutableSet.copyOf(userRoles);
+ }
+
+ public boolean isAdministrator() {
+ return userRoles != null && userRoles.contains(PollenUserSecurityRole.ADMINISTRATOR);
+ }
+
+ public boolean isCreator() {
+ return userRoles != null && userRoles.contains(PollenUserSecurityRole.CREATOR);
+ }
+
+ public boolean isVoter() {
+ return userRoles != null && userRoles.contains(PollenUserSecurityRole.VOTER);
+ }
+
+ public boolean isRestrictedVoter() {
+ return userRoles != null && userRoles.contains(PollenUserSecurityRole.RESTRICTED_VOTER);
+ }
+
+ public boolean hasNoRole() {
+ return CollectionUtils.isEmpty(userRoles);
+ }
+
+ public Set<PollenUserSecurityRole> getUserRoles() {
+ return userRoles == null ?
+ Collections.<PollenUserSecurityRole>emptySet() :
+ userRoles;
+ }
+
+ public PollenUser getPollenUser() {
+ return connectedUser;
+ }
+
+ protected PollenSecurityContext(PollenUser connectedUser) {
+ this.connectedUser = connectedUser;
+ }
+
+ public boolean isConnected() {
+ return connectedUser != null;
+ }
+
+ /**
+ * To define a security role for a given pollen user which can be
+ * identified by his user account or a accountId.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+ public enum PollenUserSecurityRole {
+
+ /**
+ * Connected user with administration rights.
+ * <p/>
+ * This role can access to everything, but can not vote.
+ */
+ ADMINISTRATOR,
+
+ /**
+ * Creator of the poll.
+ * <p/>
+ * This role can access to everything, but can not vote.
+ */
+ CREATOR,
+
+ /** A user that has voted on a poll. */
+ VOTER,
+ /**
+ * A user that was invited to a restricted poll.
+ * <p/>
+ * It might have alreay voted or not.
+ */
+ RESTRICTED_VOTER
+
+ }
+
+ public static class ObjectSecurityContext<E extends JpaEntity> implements Serializable {
+
+ private static final long serialVersionUID = 8554648867841712974L;
+
+ protected final Class<E> type;
+
+ protected final String id;
+
+ protected final String token;
+
+ public ObjectSecurityContext(Class<E> type,
+ String id,
+ String token) {
+ this.type = type;
+ this.id = id;
+ this.token = token;
+ }
+ }
}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityContext.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,82 @@
+package org.chorem.pollen.services;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.UserInvalidPasswordException;
+import org.chorem.pollen.services.service.AuthService;
+
+/**
+ * TODO
+ *
+ * http://www.slideshare.net/chunsaker/securing-rest-apis ?
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class PollenSecurityRealm extends AuthorizingRealm implements PollenServiceSupport {
+
+ protected PollenServiceContext serviceContext;
+
+ @Override
+ public void setServiceContext(PollenServiceContext serviceContext) {
+ this.serviceContext = serviceContext;
+ }
+
+ @Override
+ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+
+ principals.getPrimaryPrincipal();
+
+ return null;
+ }
+
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+
+ UsernamePasswordToken upToken = (UsernamePasswordToken) token;
+ String username = upToken.getUsername();
+ char[] password = upToken.getPassword();
+
+ AuthService authService = serviceContext.getAuthService();
+ try {
+ authService.login(username, new String(password));
+ } catch (EntityNotFoundException e) {
+ throw new AuthenticationException(e);
+ } catch (UserInvalidPasswordException e) {
+ throw new AuthenticationException(e);
+ }
+ SimpleAuthenticationInfo result =
+ new SimpleAuthenticationInfo(username, password, getName());
+ return result;
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenSecurityRealm.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/PollenServiceContext.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -26,11 +26,13 @@
import org.chorem.pollen.persistence.PollenPersistenceContext;
import org.chorem.pollen.services.config.PollenServiceConfig;
import org.chorem.pollen.services.service.AuthService;
+import org.chorem.pollen.services.service.ChoiceService;
import org.chorem.pollen.services.service.CommentService;
import org.chorem.pollen.services.service.EmailService;
import org.chorem.pollen.services.service.FavoriteListService;
import org.chorem.pollen.services.service.FixturesService;
import org.chorem.pollen.services.service.PollService;
+import org.chorem.pollen.services.service.SecurityService;
import org.chorem.pollen.services.service.UserService;
import org.chorem.pollen.services.service.VoteCountingService;
import org.chorem.pollen.services.service.VoteService;
@@ -49,12 +51,18 @@
Date getNow();
+ PollenSecurityContext getSecurityContext();
+
+ void setSecurityContext(PollenSecurityContext securityContext);
+
PollenPersistenceContext getPersistenceContext();
PollenServiceConfig getPollenServiceConfig();
AuthService getAuthService();
+ ChoiceService getChoiceService();
+
CommentService getCommentService();
FavoriteListService getFavoriteListService();
@@ -68,11 +76,12 @@
VoterListService getVoterListService();
VoteService getVoteService();
-
EmailService getEmailService();
FixturesService getFixturesService();
+ SecurityService getSecurityService();
+
String generatePassword();
String encodePassword(String password);
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfig.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -27,6 +27,9 @@
import com.google.common.collect.Maps;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.chorem.pollen.persistence.entity.CommentVisibility;
+import org.chorem.pollen.persistence.entity.PollType;
+import org.chorem.pollen.persistence.entity.VoteVisibility;
import org.chorem.pollen.services.PollenTechnicalException;
import org.nuiton.util.config.ApplicationConfig;
import org.nuiton.util.config.ArgumentsParserException;
@@ -81,4 +84,31 @@
boolean isDevMode = applicationConfig.getOptionAsBoolean(PollenServiceConfigOption.DEV_MODE.key);
return isDevMode;
}
+
+ public int getDefaultVoteCountingType() {
+ int result = applicationConfig.getOptionAsInt(
+ PollenServiceConfigOption.DEFAULT_VOTE_COUNTING_TYPE.key);
+ return result;
+ }
+
+ public PollType getDefaultPollType() {
+ PollType result = applicationConfig.getOption(
+ PollType.class,
+ PollenServiceConfigOption.DEFAULT_POLL_TYPE.key);
+ return result;
+ }
+
+ public VoteVisibility getDefaultVoteVisibility() {
+ VoteVisibility result = applicationConfig.getOption(
+ VoteVisibility.class,
+ PollenServiceConfigOption.DEFAULT_VOTE_VISIBILITY.key);
+ return result;
+ }
+
+ public CommentVisibility getDefaultCommentVisibility() {
+ CommentVisibility result = applicationConfig.getOption(
+ CommentVisibility.class,
+ PollenServiceConfigOption.DEFAULT_COMMENT_VISIBILITY.key);
+ return result;
+ }
}
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/config/PollenServiceConfigOption.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -23,9 +23,14 @@
* #L%
*/
+import org.chorem.pollen.persistence.entity.CommentVisibility;
+import org.chorem.pollen.persistence.entity.PollType;
+import org.chorem.pollen.persistence.entity.VoteVisibility;
import org.nuiton.util.config.ConfigOptionDef;
+import static org.nuiton.i18n.I18n.n_;
+
/**
* TODO
*
@@ -34,23 +39,67 @@
*/
public enum PollenServiceConfigOption implements ConfigOptionDef {
+ /**
+ * Default poll type to use at a new poll creation.
+ *
+ * @since 2.0
+ */
+ DEFAULT_POLL_TYPE(
+ "pollen.default.pollType",
+ n_("pollen.configuration.defaultPollType"),
+ PollType.FREE.name(),
+ PollType.class),
+
+ /**
+ * Default vote counting type to use at a new poll creation.
+ *
+ * @since 2.0
+ */
+ DEFAULT_VOTE_COUNTING_TYPE(
+ "pollen.default.voteCountingType",
+ n_("pollen.configuration.defaultVoteCountingType"),
+ "0",
+ Integer.class),
+
+ /**
+ * Default poll vote visibility to use at a new poll creation.
+ *
+ * @since 2.0
+ */
+ DEFAULT_VOTE_VISIBILITY(
+ "pollen.default.pollVoteVisibility",
+ n_("pollen.configuration.defaultPollVoteVisibility"),
+ VoteVisibility.EVERYBODY.name(),
+ VoteVisibility.class),
+
+ /**
+ * Default poll comment visibility to use at a new poll creation.
+ *
+ * @since 2.0
+ */
+ DEFAULT_COMMENT_VISIBILITY(
+ "pollen.default.pollCommentVisibility",
+ n_("pollen.configuration.defaultPollCommentVisibility"),
+ CommentVisibility.EVERYBODY.name(),
+ CommentVisibility.class),
+
SMTP_HOST(
- "smtp.host",
+ "pollen.smtp.host",
"Nom d'hôte du serveur SMTP",
"", String.class),
SMTP_PORT(
- "smtp.port",
+ "pollen.smtp.port",
"Le port du serveur SMTP",
"25", Integer.class),
SMTP_FROM(
- "smtp.from",
+ "pollen.smtp.from",
"L'adresse d'expéditeur pour les mails de notifications",
"", String.class),
DEV_MODE(
- "devMode",
+ "pollen.devMode",
"Mode développement, court-circuite l'envoi de mail",
"true", Boolean.class),;
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,47 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public abstract class AbstractInvalidFormException extends Exception{
+ private static final long serialVersionUID = 1L;
+
+ protected final Multimap<String, String> errors;
+
+
+ public AbstractInvalidFormException(Multimap<String, String> errors) {
+ this.errors = errors;
+ }
+
+ public Multimap<String, String> getErrors() {
+ return errors;
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/AbstractInvalidFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListImportException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberEmailAlreadyUsedException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNameAlreadyUsedException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListMemberNotOwnedByFavoriteListException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNameAlreadyUsedException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/FavoriteListNotOwnedByUserException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidChoiceFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidChoiceFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidChoiceFormException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,43 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidChoiceFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+
+ public InvalidChoiceFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidChoiceFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollFormException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollFormException.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollFormException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,42 @@
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.collect.Multimap;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class InvalidPollFormException extends AbstractInvalidFormException {
+
+ private static final long serialVersionUID = 1L;
+
+ public InvalidPollFormException(Multimap<String, String> errors) {
+ super(errors);
+ }
+
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidPollFormException.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,28 @@
package org.chorem.pollen.services.exception;
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
/**
* TODO
*
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/InvalidSessionTokenException.java
___________________________________________________________________
Modified: svn:keywords
- Author Date Id Revision
+ Author Date Id Revision HeadURL
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/package-info.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/package-info.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/package-info.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,30 @@
+/**
+ * Package where to find all services exception.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+package org.chorem.pollen.services.exception;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/exception/package-info.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/package-info.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/package-info.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/package-info.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -1,5 +1,5 @@
/**
- * Base Package for the pollen business service.
+ * Base package of the service layer.
*
* @author tchemit <chemit(a)codelutin.com>
* @since 2.0
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/AbstractPollenService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -24,6 +24,8 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.Multimap;
+import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.PollenPersistenceContext;
import org.chorem.pollen.services.PollenServiceContext;
import org.chorem.pollen.services.PollenServiceSupport;
@@ -31,6 +33,7 @@
import org.chorem.pollen.services.exception.EntityNotFoundException;
import org.nuiton.jpa.api.JpaEntities;
import org.nuiton.jpa.api.JpaEntity;
+import org.nuiton.util.StringUtil;
import java.util.Date;
@@ -77,6 +80,10 @@
return serviceContext.getAuthService();
}
+ public ChoiceService getChoiceService() {
+ return serviceContext.getChoiceService();
+ }
+
protected CommentService getCommentService() {
return serviceContext.getCommentService();
}
@@ -89,6 +96,10 @@
return serviceContext.getPollService();
}
+ protected SecurityService getSecurityService() {
+ return serviceContext.getSecurityService();
+ }
+
protected UserService getUserService() {
return serviceContext.getUserService();
}
@@ -116,4 +127,27 @@
throw new EntityNotFoundException(type, entityId);
}
}
+
+ protected boolean check(Multimap<String, String> errors, String field, boolean condition, String error) {
+ boolean valid = condition;
+ if (!valid) {
+ errors.put(field, error);
+ }
+ return valid;
+ }
+
+ protected boolean checkNotNull(Multimap<String, String> errors, String field, Object value, String error) {
+ boolean valid = check(errors, field, value != null, error);
+ return valid;
+ }
+
+ protected boolean checkNotBlank(Multimap<String, String> errors, String field, String value, String error) {
+ boolean valid = check(errors, field, StringUtils.isNotBlank(value), error);
+ return valid;
+ }
+
+ protected boolean checkValidEmail(Multimap<String, String> errors, String field, String value, String error) {
+ boolean valid = check(errors, field, StringUtil.isEmail(value), error);
+ return valid;
+ }
}
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,202 @@
+package org.chorem.pollen.services.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.chorem.pollen.persistence.dao.ChoiceJpaDao;
+import org.chorem.pollen.persistence.entity.Choice;
+import org.chorem.pollen.persistence.entity.ChoiceType;
+import org.chorem.pollen.persistence.entity.Poll;
+import org.chorem.pollen.persistence.entity.PollenPrincipal;
+import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidChoiceFormException;
+import org.nuiton.jpa.api.JpaEntities;
+
+import java.util.List;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class ChoiceService extends AbstractPollenService {
+
+ public List<Choice> getChoices(String pollId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
+
+ Poll poll = getPollService().getPoll(pollId);
+
+ return poll.getChoice();
+ }
+
+ public Choice getChoice(String pollId, String choiceId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(choiceId);
+ Poll poll = getPollService().getPoll(pollId);
+
+ Choice result = getChoice(poll, choiceId);
+ return result;
+ }
+
+ public Choice addChoice(String pollId, Choice choice) throws EntityNotFoundException, InvalidChoiceFormException {
+ Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(choice);
+ checkHasNoId(choice);
+
+ Poll poll = getPollService().getPoll(pollId);
+
+ checkChoiceForm(poll.getChoiceType(), choice);
+
+ Choice result = saveChoice(poll, choice, null);
+
+ getPersistenceContext().getPollDao().merge(poll);
+ getPersistenceContext().commit();
+ return result;
+ }
+
+ public Choice editChoice(String pollId, Choice choice) throws EntityNotFoundException, InvalidChoiceFormException {
+ Preconditions.checkNotNull(choice);
+ checkHasId(choice);
+
+ Poll poll = getPollService().getPoll(pollId);
+
+ checkChoiceForm(poll.getChoiceType(), choice);
+
+ Choice result = saveChoice(poll, choice, null);
+
+ getPersistenceContext().getChoiceDao().merge(choice);
+ getPersistenceContext().commit();
+ return result;
+ }
+
+ public void deleteChoice(String pollId, String choiceId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
+ Preconditions.checkNotNull(choiceId);
+
+ Poll poll = getPollService().getPoll(pollId);
+ Choice choice = getChoice(poll, choiceId);
+
+ poll.removeChoice(choice);
+
+ getPersistenceContext().getPollDao().merge(poll);
+ getPersistenceContext().commit();
+ }
+
+ protected Choice getChoice(Poll poll, String choiceId) throws EntityNotFoundException {
+
+ Choice result = poll.getChoiceById(choiceId);
+ checkEntityExists(Choice.class, result, choiceId);
+ return result;
+ }
+
+ protected Choice saveChoice(Poll poll,
+ Choice choice,
+ PollenPrincipal principal) throws EntityNotFoundException {
+
+ ChoiceJpaDao choiceDao = getPersistenceContext().getChoiceDao();
+
+ boolean choiceExists = JpaEntities.isEntityHasId(choice);
+
+ Choice choiceToPersist;
+ if (choiceExists) {
+
+ // get existing choice
+
+ choiceToPersist = getChoice(poll, choice.getId());
+ } else {
+
+ // create a new choice
+ choiceToPersist = choiceDao.newInstance();
+
+ if (principal == null) {
+
+ // create a new principal
+
+ principal = getSecurityService().generatePrincipal();
+
+ if (choice.getCreator() == null) {
+
+ //TODO Should we use the poll creator ?
+
+ } else {
+
+ principal.setName(choice.getCreator().getName());
+ principal.setEmail(choice.getCreator().getEmail());
+ }
+ }
+ choiceToPersist.setCreator(principal);
+ poll.addChoice(choiceToPersist);
+ }
+
+ switch (poll.getChoiceType()) {
+
+ case TEXT:
+ choiceToPersist.setName(choice.getName());
+ choiceToPersist.setDescription(choice.getDescription());
+ choiceToPersist.setCreator(poll.getCreator());
+
+ break;
+
+ case DATE:
+ throw new IllegalStateException("Not implemented");
+
+ case IMAGE:
+ throw new IllegalStateException("Not implemented");
+ }
+ return choiceToPersist;
+ }
+
+ protected void checkChoiceForm(ChoiceType choiceType, Choice choice) throws InvalidChoiceFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ switch (choiceType) {
+
+ case TEXT:
+
+ //TODO Should check unique choice name ?
+
+ checkNotBlank(errors,
+ "name",
+ choice.getName(),
+ "choice name can not be empty");
+
+ break;
+ case DATE:
+ throw new IllegalStateException("Not implemented");
+
+ case IMAGE:
+ throw new IllegalStateException("Not implemented");
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidChoiceFormException(errors);
+ }
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/PollService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -24,14 +24,23 @@
*/
import com.google.common.base.Preconditions;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
+import org.apache.commons.lang3.StringUtils;
+import org.chorem.pollen.persistence.dao.PollJpaDao;
import org.chorem.pollen.persistence.entity.Choice;
+import org.chorem.pollen.persistence.entity.ChoiceType;
import org.chorem.pollen.persistence.entity.Poll;
+import org.chorem.pollen.persistence.entity.PollenPrincipal;
import org.chorem.pollen.persistence.entity.PollenUser;
+import org.chorem.pollen.persistence.entity.VoterList;
+import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.chorem.pollen.services.exception.InvalidPollFormException;
+import org.nuiton.jpa.api.JpaEntities;
import java.io.File;
-import java.util.List;
import java.util.Set;
/**
@@ -42,6 +51,10 @@
*/
public class PollService extends AbstractPollenService {
+ public Set<Poll> getPolls(String userId) throws EntityNotFoundException {
+ return Sets.newHashSet(getPersistenceContext().getPollDao().findAll());
+ }
+
public Set<Poll> getCreatedPolls(String userId) throws EntityNotFoundException {
Preconditions.checkNotNull(userId);
@@ -73,39 +86,63 @@
return result;
}
- public Poll createPoll(String userId, Poll poll) throws EntityNotFoundException {
- Preconditions.checkNotNull(userId);
- Preconditions.checkNotNull(poll);
- checkHasNoId(poll);
+ public Poll getNewPoll(String userId, ChoiceType choiceType) throws EntityNotFoundException {
+ Poll result = getPersistenceContext().getPollDao().newInstance();
+
+ result.setChoiceType(choiceType);
+
+ // -- default values -- //
+
+ result.setVoteCountingType(getPollenServiceConfig().getDefaultVoteCountingType());
+ result.setPollType(getPollenServiceConfig().getDefaultPollType());
+ result.setVoteVisibility(getPollenServiceConfig().getDefaultVoteVisibility());
+ result.setCommentVisibility(getPollenServiceConfig().getDefaultCommentVisibility());
+ result.setBeginDate(serviceContext.getNow());
+
+ // -- creator -- //
+
+ PollenPrincipal creator = getPersistenceContext().getPollenPrincipalDao().newInstance();
+ result.setCreator(creator);
+
if (userId != null) {
-
- // get user
PollenUser user = getUserService().getUser(userId);
- // link it to creator
-
+ creator.setName(user.getName());
+ creator.setEmail(user.getEmail());
}
+ return result;
+ }
- getPersistenceContext().getPollDao().persist(poll);
+ public Poll createPoll(String userId, Poll poll) throws EntityNotFoundException, InvalidPollFormException {
+ Preconditions.checkNotNull(poll);
+ checkHasNoId(poll);
+
+ checkPollForm(poll);
+
+ Poll pollToPersist = savePoll(userId, poll);
+
+ getPersistenceContext().getPollDao().persist(pollToPersist);
getPersistenceContext().commit();
- return poll;
+ return pollToPersist;
}
- public Poll editPoll(Poll poll) throws EntityNotFoundException {
+ public Poll editPoll(Poll poll) throws EntityNotFoundException, InvalidPollFormException {
Preconditions.checkNotNull(poll);
checkHasId(poll);
- getPoll(poll.getId());
+ checkPollForm(poll);
- getPersistenceContext().getPollDao().merge(poll);
+ Poll toSave = savePoll(null, poll);
+
+ getPersistenceContext().getPollDao().merge(toSave);
getPersistenceContext().commit();
- Poll result = getPoll(poll.getId());
- return result;
+ return toSave;
}
+
public void deletePoll(String pollId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
@@ -113,6 +150,11 @@
getPersistenceContext().getPollDao().remove(poll);
getPersistenceContext().commit();
+
+ if (poll.getCreator().getEmail() != null) {
+
+ //TODO Notify ?
+ }
}
public Poll clonePoll(String pollId) throws EntityNotFoundException {
@@ -140,66 +182,183 @@
return null;
}
- public List<Choice> getChoices(String pollId) throws EntityNotFoundException {
- Preconditions.checkNotNull(pollId);
+ protected Poll savePoll(String userId, Poll poll) throws EntityNotFoundException {
- Poll poll = getPoll(pollId);
+ boolean pollExists = JpaEntities.isEntityHasId(poll);
- return poll.getChoice();
- }
+ Poll toSave;
- public Choice getChoice(String choiceId) throws EntityNotFoundException {
- Preconditions.checkNotNull(choiceId);
+ if (pollExists) {
+ toSave = getPoll(poll.getId());
- Choice result = getPersistenceContext().getChoiceDao().findById(choiceId);
- checkEntityExists(Choice.class, result, choiceId);
- return result;
- }
+ } else {
+ PollJpaDao dao = getPersistenceContext().getPollDao();
- public Choice addChoice(String pollId, Choice choice) throws EntityNotFoundException {
- Preconditions.checkNotNull(pollId);
- Preconditions.checkNotNull(choice);
- checkHasNoId(choice);
+ toSave = dao.newInstance();
- Poll poll = getPoll(pollId);
+ PollenPrincipal creatorToPersist =
+ getSecurityService().generatePrincipal();
- poll.addChoice(choice);
+ toSave.setCreator(creatorToPersist);
+ }
- getPersistenceContext().getPollDao().merge(poll);
+ // -- creator -- //
- getPersistenceContext().commit();
- Choice result = getChoice(choice.getId());
- return result;
- }
+ if (userId != null) {
- public Choice editChoice(Choice choice) throws EntityNotFoundException {
- Preconditions.checkNotNull(choice);
- checkHasId(choice);
+ // link to connected user
+ PollenUser user = getUserService().getUser(userId);
+ toSave.getCreator().setPollenUser(user);
+ }
- getChoice(choice.getId());
+ toSave.getCreator().setName(poll.getCreator().getName());
+ toSave.getCreator().setEmail(poll.getCreator().getEmail());
- getPersistenceContext().getChoiceDao().merge(choice);
- getPersistenceContext().commit();
+ // -- simple properties -- //
- Choice result = getChoice(choice.getId());
- return result;
- }
+ toSave.setVoteCountingType(poll.getVoteCountingType());
+ toSave.setVoteVisibility(poll.getVoteVisibility());
+ toSave.setCommentVisibility(poll.getCommentVisibility());
+ toSave.setChoiceType(poll.getChoiceType());
- public void deleteChoice(String pollId, String choiceId) throws EntityNotFoundException {
- Preconditions.checkNotNull(pollId);
- Preconditions.checkNotNull(choiceId);
+ toSave.setAnonymousVoteAllowed(poll.isAnonymousVoteAllowed());
+ toSave.setChoiceAddAllowed(poll.isChoiceAddAllowed());
+ toSave.setBeginChoiceDate(poll.getBeginChoiceDate());
+ toSave.setBeginDate(poll.getBeginDate());
- Poll poll = getPoll(pollId);
- Choice choice = getChoice(choiceId);
+ toSave.setContinuousResults(poll.isContinuousResults());
+ toSave.setDescription(poll.getDescription());
+ toSave.setEndDate(poll.getEndDate());
+ toSave.setEndChoiceDate(poll.getEndChoiceDate());
+ toSave.setPollType(poll.getPollType());
+ toSave.setMaxChoiceNumber(poll.getMaxChoiceNumber());
+ toSave.setTitle(poll.getTitle());
- poll.removeChoice(choice);
+ // -- choice -- //
- getPersistenceContext().getPollDao().merge(poll);
+ for (Choice choice : poll.getChoice()) {
- getPersistenceContext().commit();
+ getChoiceService().saveChoice(toSave, choice, toSave.getCreator());
+ }
+
+ // -- voting list -- //
+
+ if (!poll.isVoterListEmpty()) {
+
+ for (VoterList voterList : poll.getVoterList()) {
+
+ getVoterListService().saveVoterList(toSave, voterList);
+ }
+ }
+
+ return toSave;
}
- public Set<Poll> getPolls(String userId) throws EntityNotFoundException {
- return Sets.newHashSet(getPersistenceContext().getPollDao().findAll());
+ protected void checkPollForm(Poll poll) throws InvalidPollFormException {
+
+ //TODO use nuiton validator ?
+ Multimap<String, String> errors = ArrayListMultimap.create();
+
+ checkNotNull(errors, "pollType", poll.getPollType(), "pollType can not be null");
+ checkNotNull(errors, "choiceType", poll.getChoiceType(), "choiceType can not be null");
+ checkNotNull(errors, "commentVisibility", poll.getCommentVisibility(), "commentVisibility can not be null");
+ checkNotNull(errors, "voteVisibility", poll.getVoteVisibility(), "voteVisibility can not be null");
+ checkNotNull(errors, "voteCountingType", poll.getVoteCountingType(), "voteCountingType can not be null");
+
+ checkNotBlank(errors, "title", poll.getTitle(), "title can not be empty");
+ check(errors, "choice", poll.isChoiceEmpty(), "need at least one choice");
+
+ if (poll.isFreePoll()) {
+ check(errors, "pollType", poll.isVoterListEmpty(), "can't have voterList with free poll");
+ } else {
+ check(errors, "pollType", !poll.isVoterListEmpty(), "must have voterList with not free poll");
+ }
+
+ if (!poll.isChoiceEmpty()) {
+
+ // validate choices
+
+ int choiceIndex = 0;
+
+ for (Choice choice : poll.getChoice()) {
+
+ String choiceField = "choice[" + (choiceIndex++) + "]";
+
+ switch (poll.getChoiceType()) {
+
+ case TEXT:
+
+ checkNotBlank(errors,
+ choiceField + ".name",
+ choice.getName(),
+ "choice name can not be empty");
+
+ break;
+ case DATE:
+ throw new IllegalStateException("Not implemented");
+
+ case IMAGE:
+ throw new IllegalStateException("Not implemented");
+ }
+ }
+ }
+
+ if (!poll.isVoterListEmpty()) {
+
+ Set<String> voterListNames = Sets.newHashSet();
+
+ // validate voter lists
+
+ int voterListIndex = 0;
+
+ for (VoterList voterList : poll.getVoterList()) {
+
+ String voterListField = "voterList[" + (voterListIndex++) + "]";
+
+ checkNotBlank(errors, voterListField + ".name", voterList.getName(), "voterList name can not be empty");
+ check(errors, voterListField + ".weight", voterList.getWeight() > 0, "voterList weight must be greater than 0");
+ check(errors, voterListField + ".member", !voterList.isVoterListMemberEmpty(), "voterList must contains at least one member");
+
+ boolean added = voterListNames.add(voterList.getName());
+
+ check(errors, voterListField, added, "voterList name already used");
+
+ Set<String> voterListMemberNames = Sets.newHashSet();
+ Set<String> voterListMemberEmails = Sets.newHashSet();
+
+ int voterListMemberIndex = 0;
+
+ for (VoterListMember voterListMember : voterList.getVoterListMember()) {
+
+ String voterListMemberField = voterListField + ".member[" + (voterListMemberIndex++) + "]";
+
+ String voterListMemberName = voterListMember.getName();
+ boolean nameNotNull = checkNotBlank(errors, voterListMemberField + ".name", voterListMemberName, "member name can not be empty");
+
+ if (nameNotNull) {
+ boolean nameAdded = voterListMemberNames.add(voterListMemberName);
+ check(errors, voterListMemberField + ".name", nameAdded, "member name already used in this list");
+ }
+
+ String voterListMemberEmail = voterListMember.getEmail();
+
+ boolean emailNotNull = checkNotBlank(errors, voterListMemberField + ".email", voterListMemberEmail, "member email can not be empty");
+
+ if (emailNotNull) {
+
+ voterListMemberEmail = StringUtils.lowerCase(voterListMemberEmail);
+
+ checkValidEmail(errors, voterListMemberField + ".email", voterListMemberEmail, "member email is not valid");
+ boolean emailAdded = voterListMemberEmails.add(voterListMemberEmail);
+ check(errors, voterListMemberField + ".email", emailAdded, "member email already used in this list");
+ }
+ }
+ }
+ }
+
+ if (!errors.isEmpty()) {
+
+ throw new InvalidPollFormException(errors);
+ }
}
}
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,45 @@
+package org.chorem.pollen.services.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
+
+import org.chorem.pollen.persistence.dao.PollenPrincipalJpaDao;
+import org.chorem.pollen.persistence.entity.PollenPrincipal;
+
+/**
+ * TODO
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+public class SecurityService extends AbstractPollenService {
+
+ public PollenPrincipal generatePrincipal() {
+ PollenPrincipalJpaDao pollenPrincipalDao = getPersistenceContext().getPollenPrincipalDao();
+ PollenPrincipal principal = pollenPrincipalDao.newInstance();
+ principal.setToken(serviceContext.generateToken());
+ principal.setCreationDate(serviceContext.getNow());
+ return principal;
+
+ }
+}
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/SecurityService.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Modified: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-14 15:12:49 UTC (rev 3829)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/VoterListService.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -24,6 +24,7 @@
*/
import com.google.common.base.Preconditions;
+import org.apache.commons.lang3.StringUtils;
import org.chorem.pollen.persistence.dao.VoterListJpaDao;
import org.chorem.pollen.persistence.dao.VoterListMemberJpaDao;
import org.chorem.pollen.persistence.entity.FavoriteList;
@@ -32,6 +33,7 @@
import org.chorem.pollen.persistence.entity.VoterList;
import org.chorem.pollen.persistence.entity.VoterListMember;
import org.chorem.pollen.services.exception.EntityNotFoundException;
+import org.nuiton.jpa.api.JpaEntities;
import java.util.List;
import java.util.Set;
@@ -78,7 +80,7 @@
return result;
}
- public List<VoterList> getVoterLists(String pollId) throws EntityNotFoundException{
+ public List<VoterList> getVoterLists(String pollId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Poll poll = getPollService().getPoll(pollId);
@@ -87,7 +89,7 @@
return result;
}
- public VoterList getVoterList(String voterListId) throws EntityNotFoundException{
+ public VoterList getVoterList(String pollId, String voterListId) throws EntityNotFoundException {
Preconditions.checkNotNull(voterListId);
VoterList result = getPersistenceContext().getVoterListDao().findById(voterListId);
@@ -96,40 +98,39 @@
return result;
}
- public VoterList addVoterList(String pollId, VoterList voterList) throws EntityNotFoundException{
+ public VoterList addVoterList(String pollId, VoterList voterList) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterList);
checkHasNoId(voterList);
Poll poll = getPollService().getPoll(pollId);
+ VoterList result = saveVoterList(poll, voterList);
- poll.addVoterList(voterList);
-
getPersistenceContext().getPollDao().merge(poll);
getPersistenceContext().commit();
- VoterList result = getVoterList(voterList.getId());
return result;
}
- public VoterList editVoterList(VoterList voterList) throws EntityNotFoundException{
+ public VoterList editVoterList(String pollId, VoterList voterList) throws EntityNotFoundException {
+ Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterList);
checkHasId(voterList);
- getVoterList(voterList.getId());
+ Poll poll = getPollService().getPoll(pollId);
+ VoterList result = saveVoterList(poll, voterList);
getPersistenceContext().getVoterListDao().merge(voterList);
getPersistenceContext().commit();
- VoterList result = getVoterList(voterList.getId());
return result;
}
- public void deleteVoterList(String pollId, String voterListId) throws EntityNotFoundException{
+ public void deleteVoterList(String pollId, String voterListId) throws EntityNotFoundException {
Preconditions.checkNotNull(pollId);
Preconditions.checkNotNull(voterListId);
Poll poll = getPollService().getPoll(pollId);
- VoterList voterList = getVoterList(voterListId);
+ VoterList voterList = getVoterList(pollId, voterListId);
poll.removeVoterList(voterList);
@@ -138,58 +139,69 @@
getPersistenceContext().commit();
}
- public Set<VoterListMember> getMembers(String voterListId) throws EntityNotFoundException{
+ public Set<VoterListMember> getMembers(String pollId, String voterListId) throws EntityNotFoundException {
Preconditions.checkNotNull(voterListId);
- VoterList voterList = getVoterList(voterListId);
+ VoterList voterList = getVoterList(pollId, voterListId);
Set<VoterListMember> result = voterList.getVoterListMember();
return result;
}
- public VoterListMember getMember(String memberId) throws EntityNotFoundException{
+ public VoterListMember getMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
Preconditions.checkNotNull(memberId);
- VoterListMember result = getPersistenceContext().getVoterListMemberDao().findById(memberId);
+ VoterList voterList = getVoterList(pollId, voterListId);
+
+ VoterListMember result = getMember(voterList, memberId);
checkEntityExists(VoterListMember.class, result, memberId);
return result;
}
- public VoterListMember addMember(String voterListId, VoterListMember member)throws EntityNotFoundException {
+
+ public VoterListMember getMember(VoterList voterList, String memberId) throws EntityNotFoundException {
+ Preconditions.checkNotNull(memberId);
+
+ VoterListMember result = voterList.getVoterListMemberById(memberId);
+ checkEntityExists(VoterListMember.class, result, memberId);
+ return result;
+ }
+
+ public VoterListMember addMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
checkHasNoId(member);
- VoterList voterList = getVoterList(voterListId);
+ VoterList voterList = getVoterList(pollId, voterListId);
- voterList.addVoterListMember(member);
+ VoterListMember result = saveVoterListMember(voterList, member);
+
getPersistenceContext().getVoterListDao().merge(voterList);
-
getPersistenceContext().commit();
- VoterListMember result = getMember(member.getId());
return result;
}
- public VoterListMember editMember(VoterListMember member) throws EntityNotFoundException{
+ public VoterListMember editMember(String pollId, String voterListId, VoterListMember member) throws EntityNotFoundException {
+ Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(member);
checkHasId(member);
- getMember(member.getId());
+ VoterList voterList = getVoterList(pollId, voterListId);
+ VoterListMember result = saveVoterListMember(voterList, member);
+
getPersistenceContext().getVoterListMemberDao().merge(member);
-
getPersistenceContext().commit();
- VoterListMember result = getMember(member.getId());
return result;
}
- public void deleteMember(String voterListId, String memberId) throws EntityNotFoundException{
+ public void deleteMember(String pollId, String voterListId, String memberId) throws EntityNotFoundException {
Preconditions.checkNotNull(voterListId);
Preconditions.checkNotNull(memberId);
- VoterList voterList = getVoterList(voterListId);
+ VoterList voterList = getVoterList(pollId, voterListId);
- VoterListMember member = getMember(memberId);
+ VoterListMember member = getMember(voterList, memberId);
voterList.removeVoterListMember(member);
getPersistenceContext().getVoterListDao().merge(voterList);
@@ -197,4 +209,62 @@
getPersistenceContext().commit();
}
+ protected VoterList saveVoterList(Poll poll, VoterList voterList) throws EntityNotFoundException {
+
+
+ boolean voterListExists = JpaEntities.isEntityHasId(voterList);
+
+ VoterList voterListToPersist;
+
+ if (voterListExists) {
+
+ voterListToPersist =
+ getVoterListService().getVoterList(poll.getId(), voterList.getId());
+ } else {
+ VoterListJpaDao voterListDao =
+ getPersistenceContext().getVoterListDao();
+ voterListToPersist = voterListDao.newInstance();
+
+ poll.addVoterList(voterListToPersist);
+ }
+
+ voterListToPersist.setName(voterList.getName());
+ voterListToPersist.setWeight(voterList.getWeight());
+
+ for (VoterListMember voterListMember : voterList.getVoterListMember()) {
+
+ saveVoterListMember(voterListToPersist, voterListMember);
+ }
+
+ return voterListToPersist;
+ }
+
+ protected VoterListMember saveVoterListMember(VoterList voterList,
+ VoterListMember voterListMember) throws EntityNotFoundException {
+
+ boolean voterListMemberExists =
+ JpaEntities.isEntityHasId(voterListMember);
+
+ VoterListMember voterListMemberToPersist;
+
+ if (voterListMemberExists) {
+
+ voterListMemberToPersist =
+ getMember(voterList, voterListMember.getId());
+ } else {
+
+ VoterListMemberJpaDao voterListMemberDao =
+ getPersistenceContext().getVoterListMemberDao();
+
+ voterListMemberToPersist = voterListMemberDao.newInstance();
+
+ voterList.addVoterListMember(voterListMemberToPersist);
+ }
+
+ voterListMemberToPersist.setName(voterListMember.getName());
+ voterListMemberToPersist.setEmail(StringUtils.lowerCase(voterListMember.getEmail()));
+ voterListMemberToPersist.setWeight(voterListMember.getWeight());
+
+ return voterListMemberToPersist;
+ }
}
Added: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/package-info.java
===================================================================
--- trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/package-info.java (rev 0)
+++ trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/package-info.java 2013-06-15 10:58:03 UTC (rev 3830)
@@ -0,0 +1,30 @@
+/**
+ * Package where to find all services.
+ *
+ * @author tchemit <chemit(a)codelutin.com>
+ * @since 2.0
+ */
+package org.chorem.pollen.services.service;
+
+/*
+ * #%L
+ * Pollen :: Service
+ * $Id$
+ * $HeadURL$
+ * %%
+ * Copyright (C) 2009 - 2013 CodeLutin
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * #L%
+ */
Property changes on: trunk/pollen-services/src/main/java/org/chorem/pollen/services/service/package-info.java
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
Property changes on: trunk/pollen-ui-js/src/main/webapp/img/glyphicons_050_link.png
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Property changes on: trunk/pollen-ui-js/src/main/webapp/js/libs/date.js
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Property changes on: trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.scrollto.js
___________________________________________________________________
Added: svn:keywords
+ Author Date Id Revision HeadURL
Added: svn:eol-style
+ native
1
0
r3829 - in trunk/pollen-ui-js/src/main/webapp: . bundle css js/controls js/libs views
by kmorin@users.chorem.org 14 Jun '13
by kmorin@users.chorem.org 14 Jun '13
14 Jun '13
Author: kmorin
Date: 2013-06-14 17:12:49 +0200 (Fri, 14 Jun 2013)
New Revision: 3829
Url: http://chorem.org/projects/pollen/repository/revisions/3829
Log:
i18n + layout + start adding results in the table
Added:
trunk/pollen-ui-js/src/main/webapp/bundle/
trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
Modified:
trunk/pollen-ui-js/src/main/webapp/css/style.css
trunk/pollen-ui-js/src/main/webapp/index.html
trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js
trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js
trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs
trunk/pollen-ui-js/src/main/webapp/views/summary.ejs
trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
Added: trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties (rev 0)
+++ trunk/pollen-ui-js/src/main/webapp/bundle/Messages.properties 2013-06-14 15:12:49 UTC (rev 3829)
@@ -0,0 +1,61 @@
+#common
+pollen.common.cancel=Annuler
+pollen.common.validate=Valider
+pollen.common.format.date=dd/MM/yyyy
+pollen.common.format.dateTime=dd/MM/yyyy HH:mm
+pollen.common.format.time=HH:mm
+pollen.common.date.from=à partir du {0}
+pollen.common.date.fromTo=du {0} au {1}
+pollen.common.date.to=jusqu'au {0}
+
+#poll attributes
+pollen.poll.description.label=Description
+pollen.poll.description.placeholder=Description
+pollen.poll.title.label=Titre
+pollen.poll.title.placeholder=Titre
+
+#choice attributes
+pollen.choice.description.label=Description
+pollen.choice.description.placeholder=Description
+pollen.choice.name.label=Titre
+pollen.choice.name.placeholder=Titre
+
+#menu
+pollen.menu.home=Accueil
+pollen.menu.polls=Sondages
+
+#poll creation form
+pollen.poll.form.create.button.save=Créer le sondage
+pollen.poll.form.create.field.title.label=Titre
+pollen.poll.form.create.field.title.placeholder=Titre
+pollen.poll.form.create.title=Création de sondage
+
+#poll summary
+pollen.poll.summary.title=Sondage \'{0}\'
+pollen.poll.summary.linkToVote=Lien pour participer :
+pollen.poll.summary.part.export.title=Export
+pollen.poll.summary.part.export.item.export=Exporter
+pollen.poll.summary.part.poll.title=Sondage
+pollen.poll.summary.part.poll.item.close=Clore
+pollen.poll.summary.part.poll.item.delete=Supprimer
+pollen.poll.summary.part.poll.item.duplicate=Dupliquer
+pollen.poll.summary.part.poll.item.edit=Modifier
+pollen.poll.summary.part.poll.item.history=Historique
+pollen.poll.summary.part.poll.item.notification=Notification
+pollen.poll.summary.part.voters.title=Participants
+pollen.poll.summary.part.voters.item.invite=Inviter des participants
+pollen.poll.summary.part.voters.item.contact=Contacter les invités
+
+#vote
+pollen.vote.poll.author=Sondage lancé par {0}
+pollen.vote.poll.closed.alert=<strong>Ce sondage est clos.</strong> Vous ne pouvez plus voter.
+pollen.vote.choices.list.title=Propositions
+pollen.vote.choices.list.button.addChoice=Ajouter un choix
+pollen.vote.votes.list.title=Votes
+pollen.vote.votes.list.header.voter=Votant
+pollen.vote.form.add.field.userName.placeholder=Votre nom
+pollen.vote.form.add.button.vote=Voter
+pollen.vote.comments.list.title=Commentaires
+pollen.vote.comments.list.button.addComment=Ajouter un commentaire
+pollen.vote.comments.add.field.userName.placeholder=Votre nom
+pollen.vote.comments.add.field.message.placeholder=Votre commentaire
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/css/style.css
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/css/style.css 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/css/style.css 2013-06-14 15:12:49 UTC (rev 3829)
@@ -31,17 +31,22 @@
background-position: -313px -119px;
}
-#content >div {
- display: none;
+.list.alternate-colors > div {
+ padding: 10px 20px;
}
-#choicesSummary {
- padding: 20px;
- margin-bottom: 30px;
- background-color: rgb(238, 238, 238);
- border-radius: 6px 6px 6px 6px;
+.list.alternate-colors > .even {
+ background-color: rgb(245, 245, 245);
}
+.list.alternate-colors .footer {
+ color: rgb(150, 150, 150);
+}
+
+#content > div {
+ display: none;
+}
+
#voteForm .choice {
background-position: center;
background-repeat: no-repeat;
Modified: trunk/pollen-ui-js/src/main/webapp/index.html
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/index.html 2013-06-14 15:12:49 UTC (rev 3829)
@@ -28,7 +28,6 @@
</div>
-
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.js"></script>
<script src="js/libs/bootstrap.min.js"></script>
<script src="js/libs/can.jquery.js"></script>
@@ -38,6 +37,7 @@
<script src="js/libs/can.observe.delegate.js"></script>
<script src="js/libs/jquery.scrollto.js"></script>
<script src="js/libs/date.js"></script>
+ <script src="js/libs/jquery.i18n.properties-min-1.0.9.js"></script>
<script src="js/models/polls.js"></script>
<script src="js/models/comments.js"></script>
@@ -50,15 +50,30 @@
<script type="text/javascript">
- var menu = new Menu('#menu');
+ // This will initialize the plugin
+ // and show two dialog boxes: one with the text "Olá World"
+ // and other with the text "Good morning John!"
+ $.i18n.properties({
+ name:'Messages',
+ path:'bundle/',
+ mode:'both',
+ language:'fr_FR',
+ callback: function() {
- var pf = new PollForm('#pollForm');
- var summary = new PollSummary('#pollSummary');
- var vote = new PollVote('#vote');
+ var menu = new Menu('#menu');
- can.route(':type/:action');
- can.route(':type/:id/:action');
+ var pf = new PollForm('#pollForm');
+ var summary = new PollSummary('#pollSummary');
+ var vote = new PollVote('#vote');
+ can.route(':type/:action');
+ can.route(':type/:id/:action');
+
+ }
+ });
+
+
+
</script>
</body>
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_form.js 2013-06-14 15:12:49 UTC (rev 3829)
@@ -13,18 +13,6 @@
},
- '{can.route} change': function(data, ev, prop, how, newVal, oldVal ) {
- if (prop === "type" && (how === "set" || how === "add")) {
- if (newVal != "poll") {
- this.element.hide();
- }
- } else if (prop === "action" && (how === "set" || how === "add")) {
- if (newVal != "edit") {
- this.element.hide();
- }
- }
- },
-
':type/:action route': function(data) {
if (data.type === "poll" && data.action === "edit") {
this.editPoll(new Poll());
@@ -74,10 +62,10 @@
},
editPoll: function(poll) {
- console.log("edit poll " + poll.id + " : " + poll.description);
this.options.poll = poll;
this.on();
this.refreshForm();
+ this.element.siblings().hide();
this.element.show();
},
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/poll_summary.js 2013-06-14 15:12:49 UTC (rev 3829)
@@ -1,17 +1,5 @@
var PollSummary = can.Control({
- '{can.route} change': function(data, ev, prop, how, newVal, oldVal ) {
- if (prop === "type" && (how === "set" || how === "add")) {
- if (newVal != "poll") {
- this.element.hide();
- }
- } else if (prop === "action" && (how === "set" || how === "add")) {
- if (newVal != "summary") {
- this.element.hide();
- }
- }
- },
-
':type/:id/:action route': function(data) {
if (data.type === "poll" && data.action === "summary") {
var self = this;
@@ -27,6 +15,7 @@
this.element.html(can.view('views/summary.ejs', {
poll: poll
}));
+ this.element.siblings().hide();
this.element.show();
}
Modified: trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/js/controls/vote.js 2013-06-14 15:12:49 UTC (rev 3829)
@@ -2,18 +2,6 @@
// route
- '{can.route} change': function(data, ev, prop, how, newVal, oldVal ) {
- if (prop === "type" && (how === "set" || how === "add")) {
- if (newVal != "poll") {
- this.element.hide();
- }
- } else if (prop === "action" && (how === "set" || how === "add")) {
- if (newVal != "vote") {
- this.element.hide();
- }
- }
- },
-
':type/:id/:action route': function(data) {
if (data.type === "poll" && data.action === "vote") {
var self = this;
@@ -80,7 +68,11 @@
var author = form.find("[name='author']").val();
var message = form.find("[name='message']").val();
- var comment = new Comment({ author: author, text: message });
+ var comment = new Comment({
+ author: author,
+ text: message,
+ postDate: new Date().getTime()
+ });
var self = this;
comment.save({ pollId: this.options.poll.id },
function(data) {
@@ -116,6 +108,7 @@
comments: comments,
votes: votes
}));
+ this.element.siblings().hide();
this.element.show();
},
Added: trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js (rev 0)
+++ trunk/pollen-ui-js/src/main/webapp/js/libs/jquery.i18n.properties-min-1.0.9.js 2013-06-14 15:12:49 UTC (rev 3829)
@@ -0,0 +1,9 @@
+(function(k){function n(c,a){k.ajax({url:c,async:!1,cache:a.cache,contentType:"text/plain;charset="+a.encoding,dataType:"text",success:function(b){r(b,a.mode)}})}function r(c,a){for(var b="",e=c.split(/\n/),d=/(\{\d+\})/g,q=/\{(\d+)\}/g,m=/(\\u.{4})/ig,f=0;f<e.length;f++)if(e[f]=e[f].replace(/^\s\s*/,"").replace(/\s\s*$/,""),e[f].length>0&&e[f].match("^#")!="#"){var g=e[f].split("=");if(g.length>0){for(var o=unescape(g[0]).replace(/^\s\s*/,"").replace(/\s\s*$/,""),h=g.length==1?"":g[1];h.match(/\\$/)==
+"\\";)h=h.substring(0,h.length-1),h+=e[++f].replace(/\s\s*$/,"");for(var l=2;l<g.length;l++)h+="="+g[l];h=h.replace(/^\s\s*/,"").replace(/\s\s*$/,"");if(a=="map"||a=="both"){if(g=h.match(m))for(l=0;l<g.length;l++)h=h.replace(g[l],s(g[l]));k.i18n.map[o]=h}if(a=="vars"||a=="both")if(h=h.replace(/"/g,'\\"'),t(o),d.test(h)){for(var g=h.split(d),l=!0,j="",n=[],p=0;p<g.length;p++)if(d.test(g[p])&&(n.length==0||n.indexOf(g[p])==-1))l||(j+=","),j+=g[p].replace(q,"v$1"),n.push(g[p]),l=!1;b+=o+"=function("+
+j+"){";o='"'+h.replace(q,'"+v$1+"')+'"';b+="return "+o+";};"}else b+=o+'="'+h+'";'}}eval(b)}function t(c){if(/\./.test(c))for(var a="",c=c.split(/\./),b=0;b<c.length;b++)b>0&&(a+="."),a+=c[b],eval("typeof "+a+' == "undefined"')&&eval(a+"={};")}function s(c){var a=[],c=parseInt(c.substr(2),16);c>=0&&c<Math.pow(2,16)&&a.push(c);for(var c="",b=0;b<a.length;++b)c+=String.fromCharCode(a[b]);return c}k.i18n={};k.i18n.map={};k.i18n.properties=function(c){c=k.extend({name:"Messages",language:"",path:"",mode:"vars",
+cache:!1,encoding:"UTF-8",callback:null},c);if(c.language===null||c.language=="")c.language=k.i18n.browserLang();if(c.language===null)c.language="";var a=c.name&&c.name.constructor==Array?c.name:[c.name];for(i=0;i<a.length;i++)n(c.path+a[i]+".properties",c),c.language.length>=2&&n(c.path+a[i]+"_"+c.language.substring(0,2)+".properties",c),c.language.length>=5&&n(c.path+a[i]+"_"+c.language.substring(0,5)+".properties",c);c.callback&&c.callback()};k.i18n.prop=function(c){var a=k.i18n.map[c];if(a==null)return"["+
+c+"]";var b;if(typeof a=="string"){for(b=0;(b=a.indexOf("\\",b))!=-1;)a=a[b+1]=="t"?a.substring(0,b)+"\t"+a.substring(b++ +2):a[b+1]=="r"?a.substring(0,b)+"\r"+a.substring(b++ +2):a[b+1]=="n"?a.substring(0,b)+"\n"+a.substring(b++ +2):a[b+1]=="f"?a.substring(0,b)+"\u000c"+a.substring(b++ +2):a[b+1]=="\\"?a.substring(0,b)+"\\"+a.substring(b++ +2):a.substring(0,b)+a.substring(b+1);var e=[],d,j;for(b=0;b<a.length;)if(a[b]=="'")if(b==a.length-1)a=a.substring(0,b);else if(a[b+1]=="'")a=a.substring(0,b)+
+a.substring(++b);else{for(d=b+2;(d=a.indexOf("'",d))!=-1;)if(d==a.length-1||a[d+1]!="'"){a=a.substring(0,b)+a.substring(b+1,d)+a.substring(d+1);b=d-1;break}else a=a.substring(0,d)+a.substring(++d);d==-1&&(a=a.substring(0,b)+a.substring(b+1))}else if(a[b]=="{")if(d=a.indexOf("}",b+1),d==-1)b++;else if(j=parseInt(a.substring(b+1,d)),!isNaN(j)&&j>=0){var m=a.substring(0,b);m!=""&&e.push(m);e.push(j);b=0;a=a.substring(d+1)}else b=d+1;else b++;a!=""&&e.push(a);a=e;k.i18n.map[c]=e}if(a.length==0)return"";
+if(a.lengh==1&&typeof a[0]=="string")return a[0];m="";for(b=0;b<a.length;b++)m+=typeof a[b]=="string"?a[b]:a[b]+1<arguments.length?arguments[a[b]+1]:"{"+a[b]+"}";return m};k.i18n.browserLang=function(){var c=navigator.language||navigator.userLanguage,c=c.toLowerCase();c.length>3&&(c=c.substring(0,3)+c.substring(3).toUpperCase());return c};var j;if(!j)j=function(c,a,b){if(Object.prototype.toString.call(a)!=="[object RegExp]")return typeof j._nativeSplit=="undefined"?c.split(a,b):j._nativeSplit.call(c,
+a,b);var e=[],d=0,k=(a.ignoreCase?"i":"")+(a.multiline?"m":"")+(a.sticky?"y":""),a=RegExp(a.source,k+"g"),m,f,g;c+="";j._compliantExecNpcg||(m=RegExp("^"+a.source+"$(?!\\s)",k));if(b===void 0||+b<0)b=Infinity;else if(b=Math.floor(+b),!b)return[];for(;f=a.exec(c);){k=f.index+f[0].length;if(k>d&&(e.push(c.slice(d,f.index)),!j._compliantExecNpcg&&f.length>1&&f[0].replace(m,function(){for(var a=1;a<arguments.length-2;a++)arguments[a]===void 0&&(f[a]=void 0)}),f.length>1&&f.index<c.length&&Array.prototype.push.apply(e,
+f.slice(1)),g=f[0].length,d=k,e.length>=b))break;a.lastIndex===f.index&&a.lastIndex++}d===c.length?(g||!a.test(""))&&e.push(""):e.push(c.slice(d));return e.length>b?e.slice(0,b):e},j._compliantExecNpcg=/()??/.exec("")[1]===void 0,j._nativeSplit=String.prototype.split;String.prototype.split=function(c,a){return j(this,c,a)}})(jQuery);
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/menu.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/views/menu.ejs 2013-06-14 15:12:49 UTC (rev 3829)
@@ -1,2 +1,2 @@
-<li><%== can.route.link('Sondage', { type: 'poll', action: 'edit' }) %></li>
-<li><%== can.route.link('Autre', { type: 'other', action: 'donothing' }) %></li>
\ No newline at end of file
+<li><%== can.route.link(pollen.menu.home, {}) %></li>
+<li><%== can.route.link(pollen.menu.polls, { type: 'poll', action: 'edit' }) %></li>
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/views/poll_form.ejs 2013-06-14 15:12:49 UTC (rev 3829)
@@ -1,19 +1,19 @@
-<h1>Création de sondage</h1>
+<h1><%= pollen.poll.form.create.title %></h1>
<form id='pollCreationForm' class="form-horizontal">
<div class="control-group">
- <label class="control-label" for="pollCreationFormTitle">Title</label>
+ <label class="control-label" for="pollCreationFormTitle"><%= pollen.poll.title.label %></label>
<div class="controls">
- <input type='text' name='title' id='pollCreationFormTitle' placeholder='title'
+ <input type='text' name='title' id='pollCreationFormTitle' placeholder='<%= pollen.poll.title.placeholder %>'
<%= poll.attr("title") ? "value='" + poll.attr("title") + "'" : "class='empty'" %>/>
</div>
</div>
<div class="control-group">
- <label class="control-label" for='pollCreationFormDescription'>Description</label>
+ <label class="control-label" for='pollCreationFormDescription'><%= pollen.poll.description.label %></label>
<div class="controls">
- <textarea id='pollCreationFormDescription' name='description'
+ <textarea id='pollCreationFormDescription' name='description' placeholder="<%= pollen.poll.description.placeholder %>"
<% if (!poll.attr("description")) {%>
class='empty'
<% } %>><%= poll.attr('description') %></textarea>
@@ -21,7 +21,7 @@
</div>
<div class="form-actions">
- <a href="javascript://" class="btn btn-primary save">Save</a>
+ <a href="javascript://" class="btn btn-primary save"><%= pollen.poll.form.create.button.save %></a>
<a href="javascript://" class="btn btn-primary create">New poll</a>
<a href="javascript://" data-id="1" class="btn btn">Edit poll 1</a>
<a href="javascript://" data-id="2" class="btn btn">Edit poll 2</a>
Modified: trunk/pollen-ui-js/src/main/webapp/views/summary.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/summary.ejs 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/views/summary.ejs 2013-06-14 15:12:49 UTC (rev 3829)
@@ -1,36 +1,36 @@
-<h1>Sondage <%= poll.title %></h1>
+<h1><%= pollen.poll.summary.title(poll.title) %></h1>
<div class="control-group">
- <label class="control-label" for='pollSummaryLink'>Lien pour participer</label>
+ <label class="control-label" for='pollSummaryLink'><%= pollen.poll.summary.linkToVote %></label>
<input type='url' id='pollSummaryLink' value="<%== window.location.href.split('#')[0] + can.route.url({ type: 'poll', action: 'vote', id: poll.id }) %>"/>
<%== can.route.link('<i class="icon-link bigger link"></i>', {type: 'poll', action: 'vote', id: poll.id}) %>
</div>
<div class='row-fluid'>
<div class='span4'>
- <h2>Sondage</h2>
+ <h2><%= pollen.poll.summary.part.poll.title %></h2>
<ul class='noListStyle'>
- <li><%== can.route.link('<i class="icon-ok"></i>Clore', {}) %></li>
- <li><%== can.route.link('<i class="icon-pencil"></i>Modifer', {type: 'poll', action: 'edit', id: poll.id}) %></li>
- <li><%== can.route.link('<i class="icon-envelope"></i>Notification', {}) %></li>
- <li><%== can.route.link('<i class="icon-time"></i>Historique', {}) %></li>
- <li><%== can.route.link('<i class="icon-clone"></i>Créer un duplicata', {}) %></li>
- <li><%== can.route.link('<i class="icon-trash"></i>Effacer', {}) %></li>
+ <li><%== can.route.link('<i class="icon-ok"></i>' + pollen.poll.summary.part.poll.item.close, {}) %></li>
+ <li><%== can.route.link('<i class="icon-pencil"></i>' + pollen.poll.summary.part.poll.item.edit, {type: 'poll', action: 'edit', id: poll.id}) %></li>
+ <li><%== can.route.link('<i class="icon-envelope"></i>' + pollen.poll.summary.part.poll.item.notification, {}) %></li>
+ <li><%== can.route.link('<i class="icon-time"></i>' + pollen.poll.summary.part.poll.item.history, {}) %></li>
+ <li><%== can.route.link('<i class="icon-clone"></i>' + pollen.poll.summary.part.poll.item.duplicate, {}) %></li>
+ <li><%== can.route.link('<i class="icon-trash"></i>' + pollen.poll.summary.part.poll.item.delete, {}) %></li>
</ul>
</div>
<div class='span4'>
- <h2>Participants</h2>
+ <h2><%= pollen.poll.summary.part.voters.title %></h2>
<ul class='noListStyle'>
- <li><%== can.route.link('<i class="icon-user"></i>Inviter des participants', {}) %></li>
- <li><%== can.route.link('<i class="icon-envelope"></i>Contacter les invités', {}) %></li>
+ <li><%== can.route.link('<i class="icon-user"></i>' + pollen.poll.summary.part.voters.item.invite, {}) %></li>
+ <li><%== can.route.link('<i class="icon-envelope"></i>' + pollen.poll.summary.part.voters.item.contact, {}) %></li>
</ul>
</div>
<div class='span4'>
- <h2>Export</h2>
+ <h2><%= pollen.poll.summary.part.export.title %></h2>
<ul class='noListStyle'>
- <li><i class="icon-upload"></i>clore</li>
+ <li><%== can.route.link('<i class="icon-upload"></i>'+ pollen.poll.summary.part.export.item.export, {}) %></li>
</ul>
</div>
</div>
\ No newline at end of file
Modified: trunk/pollen-ui-js/src/main/webapp/views/vote.ejs
===================================================================
--- trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-14 13:10:08 UTC (rev 3828)
+++ trunk/pollen-ui-js/src/main/webapp/views/vote.ejs 2013-06-14 15:12:49 UTC (rev 3829)
@@ -3,18 +3,18 @@
<h1><%= poll.attr('title') %></h1>
<p>
- Sondage lancé par <%= poll.attr('creatorName') %>
+ <%= pollen.vote.poll.author(poll.attr('creatorName')) %>
<!-- number of votes -->
| <a id="voteSummary" class='link'><i class='icon-user'></i> <%= votes.attr('length') %></a>
<!-- number of comments-->
| <a id="commentSummary" class='link'><i class='icon-comment'></i> <%= comments.attr('length') %></a>
<!-- poll dates -->
<% if (poll.attr('beginDate') && poll.attr('endDate')) { %>
- | <i class='icon-time'></i> du <%= new Date(poll.attr('beginDate')).toString("dd/MM/yyyy") %> au <%= new Date(poll.attr('endDate')).toString("dd/MM/yyyy") %>
+ | <i class='icon-time'></i> <%= pollen.common.date.fromTo(new Date(poll.attr('beginDate')).toString(pollen.common.format.date), new Date(poll.attr('endDate')).toString(pollen.common.format.date)) %>
<% } else if (poll.attr('beginDate')) { %>
- | <i class='icon-time'></i> à partir du <%= new Date(poll.attr('beginDate')).toString("dd/MM/yyyy") %>
+ | <i class='icon-time'></i> <%= pollen.common.date.from(new Date(poll.attr('beginDate')).toString(pollen.common.format.date)) %>
<% } else if (poll.attr('endDate')) { %>
- | <i class='icon-time'></i> jusqu'au <%= new Date(poll.attr('endDate')).toString("dd/MM/yyyy") %>
+ | <i class='icon-time'></i> <%= pollen.common.date.to(new Date(poll.attr('endDate')).toString(pollen.common.format.date)) %>
<% } %>
</p>
@@ -26,14 +26,14 @@
<% if (poll.attr('closed')) { %>
<div class="alert fade in">
<button type="button" class="close" data-dismiss="alert">×</button>
- <strong>Ce sondage est clos.</strong> Vous ne pouvez plus voter.
+ <%== pollen.vote.poll.closed.alert %>
</div>
<% } %>
<!-- list of the choices -->
-<div id='choicesSummary'>
+<div class='well'>
- <h3>Propositions</h3>
+ <h3><%= pollen.vote.choices.list.title %></h3>
<ol>
<% poll.choices.each(function(choice) { %>
@@ -45,14 +45,14 @@
<!-- link to show/hide the new choice form -->
<button class="collapsed btn btn-link" data-toggle="collapse" data-target="#addChoiceForm">
- Ajouter un choix <i class="icon-collapse"></i>
+ <%= pollen.vote.choices.list.button.addChoice %> <i class="icon-collapse"></i>
</button>
<!-- form to add a new choice to the poll -->
<form id="addChoiceForm" class="collapse">
- <input type="text" name="name" placeholder="Nom"/>
- <textarea name="description" placeholder="Description"></textarea>
- <button type="submit" class="btn btn-primary">Valider</button>
+ <input type="text" name="name" placeholder="<%= pollen.choice.name.placeholder %>"/>
+ <textarea name="description" placeholder="<%= pollen.choice.description.placeholder %>"></textarea>
+ <button type="submit" class="btn btn-primary"><%= pollen.common.validate %></button>
</form>
<% } %>
</div>
@@ -60,14 +60,17 @@
<!-- table of the votes -->
<form id="voteForm">
+ <h2><%= pollen.vote.votes.list.title %></h2>
+
<table id="voteTable" class="table table-bordered table-striped">
- <caption>Votes</caption>
+ <% var results = new can.Observe.List(new Array(poll.attr('choices.length'))); %>
<thead>
<tr>
- <th>Votant</th>
- <% poll.choices.each(function(choice) { %>
+ <th><%= pollen.vote.votes.list.header.voter %></th>
+ <% poll.choices.each(function(choice, i) { %>
<th data-container='body' data-placement='top' title='<%= choice.attr("description") %>'>
<%= choice.attr('name') %>
+ <% results[i] = 0 %>
</th>
<% }); %>
</tr>
@@ -81,22 +84,34 @@
var voteChoice = vote.voteToChoices.attr(i);
if (voteChoice == null) {
%>
- <td class='choice voteBeforeChoice'></td>
+ <td class='choice voteBeforeChoice'></td>
<% } else { %>
- <td class='choice <%= voteChoice.attr("voteValue") ? "selected" : "notSelected" %>'>
- <%= voteChoice.attr("voteValue") ? "OK" : "" %>
- </td>
- <%
+ <td class='choice <%= voteChoice.attr("voteValue") ? "selected" : "notSelected" %>'>
+ <%= voteChoice.attr("voteValue") ? "OK" : "" %>
+ </td>
+ <%
+ if (voteChoice.attr("voteValue")) {
+ // todo 20130614 kmorin check why if we do a results.attr(i, results[i] +1) ==> too much recursion
+ results[i] = results[i] + 1
+ }
}
});
%>
</tr>
- <%
- });
- if (!poll.attr('closed')) {
- %>
+ <% }); %>
+
+ <tr>
+ <td>Resultats</td>
+ <% poll.choices.each(function(choice, i) { %>
+ <td class='result'>
+ <%= results.attr(i) %>
+ </td>
+ <% }); %>
+ </tr>
+
+ <% if (!poll.attr('closed')) { %>
<tr>
- <td><input name="userName" type='text'/></td>
+ <td><input name="userName" type='text' placeholder='<%= pollen.vote.form.add.field.userName.placeholder %>'/></td>
<%poll.choices.each(function(choice, i) { %>
<td><input name="<%= i %>" type='checkbox'/></td>
<% }); %>
@@ -107,7 +122,7 @@
<% if (!poll.attr('closed')) { %>
<div class="form-actions">
- <button type="submit" id="voteButton" class="btn btn-primary">Voter</button>
+ <button type="submit" id="voteButton" class="btn btn-primary"><%= pollen.vote.form.add.button.vote %></button>
</div>
<% } %>
@@ -115,27 +130,30 @@
<!-- Comments -->
<div id="comments">
- <h2>Commentaires</h2>
+ <h2><%= pollen.vote.comments.list.title %></h2>
<button class="collapsed btn btn-link" data-toggle="collapse" data-target="#addCommentForm">
- Ajouter un commentaire <i class="icon-collapse"></i>
+ <%= pollen.vote.comments.list.button.addComment %> <i class="icon-collapse"></i>
</button>
<form id="addCommentForm" class="collapse">
- <input type="text" name="author" placeholder="Votre nom"/>
- <textarea name="message" placeholder="Entrez votre message"></textarea>
+ <input type="text" name="author" placeholder="<%= pollen.vote.comments.add.field.userName.placeholder %>"/>
+ <textarea name="message" placeholder="<%= pollen.vote.comments.add.field.message.placeholder %>"></textarea>
<button type="submit" class="btn btn-primary">Valider</button>
</form>
- <dl>
- <% comments.each(function(comment) { %>
+ <div class='list alternate-colors'>
+ <% comments.each(function(comment, i) { %>
- <dt><%= comment.attr('author') %> - <em><%= new Date(comment.attr('postDate')).toString("dd/MM/yyyy hh:mm") %></em></dt>
- <dd>
- <%= comment.attr('text') %>
- </dd>
- </div>
+ <div class="<%= i % 2 ? 'odd' : 'even' %>">
+ <p>
+ <%= comment.attr('text') %>
+ </p>
+ <div class='footer'>
+ <small><%= comment.attr('author') %> | <%= new Date(comment.attr('postDate')).toString(pollen.common.format.dateTime) %></small>
+ </div>
+ </div>
<% }); %>
- </dl>
+ </div>
</div>
\ No newline at end of file
1
0
Author: tchemit
Date: 2013-06-14 15:10:08 +0200 (Fri, 14 Jun 2013)
New Revision: 3828
Url: http://chorem.org/projects/pollen/repository/revisions/3828
Log:
go back to zargo model
Modified:
branches/pollen-1.5.x/pom.xml
Modified: branches/pollen-1.5.x/pom.xml
===================================================================
--- branches/pollen-1.5.x/pom.xml 2013-06-14 09:24:20 UTC (rev 3827)
+++ branches/pollen-1.5.x/pom.xml 2013-06-14 13:10:08 UTC (rev 3828)
@@ -495,8 +495,8 @@
<artifactId>eugene-maven-plugin</artifactId>
<version>${eugenePluginVersion}</version>
<configuration>
- <!--<inputs>zargo</inputs>-->
- <inputs>yamlmodel</inputs>
+ <inputs>zargo</inputs>
+ <!--inputs>yamlmodel</inputs-->
<resolver>org.nuiton.util.FasterCachedResourceResolver</resolver>
</configuration>
<dependencies>
1
0
Author: tchemit
Date: 2013-06-14 11:24:20 +0200 (Fri, 14 Jun 2013)
New Revision: 3827
Url: http://chorem.org/projects/pollen/repository/revisions/3827
Log:
remove old branches
Removed:
branches/pollen-1.2.3-1.2.x/
branches/pollen-1.2.5-1.2.x/
branches/pollen-2.0-beta-1/
1
0