//
// Copyright 2009 Robin Komiwes, Bruno Verachten, Christophe Cordenier
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package com.wooki.pages.book;
import java.util.List;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventConstants;
import org.apache.tapestry5.PersistenceConstants;
import org.apache.tapestry5.annotations.AfterRender;
import org.apache.tapestry5.annotations.Import;
import org.apache.tapestry5.annotations.InjectComponent;
import org.apache.tapestry5.annotations.OnEvent;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.RequestParameter;
import org.apache.tapestry5.annotations.SetupRender;
import org.apache.tapestry5.corelib.components.Zone;
import org.apache.tapestry5.ioc.Messages;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.Request;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;
import org.slf4j.Logger;
import com.wooki.base.BookBase;
import com.wooki.domain.biz.BookManager;
import com.wooki.domain.biz.ChapterManager;
import com.wooki.domain.model.Chapter;
import com.wooki.domain.model.Publication;
import com.wooki.domain.model.User;
import com.wooki.links.PageLink;
import com.wooki.links.impl.NavLink;
import com.wooki.services.security.WookiSecurityContext;
/**
* This page displays a book with its table of contents.
*/
@Import(library =
{ "context:static/js/jquery-ui-1.7.3.custom.min.js" })
public class Index extends BookBase
{
@Inject
private Messages messages;
@Inject
private BookManager bookManager;
@Inject
private ChapterManager chapterManager;
@Inject
private WookiSecurityContext securityCtx;
@Inject
private JavaScriptSupport jsSupport;
@Inject
private ComponentResources resources;
@Inject
private Request request;
@Inject
private Logger logger;
@InjectComponent
private Zone tableOfContents;
@Property
private User currentUser;
@Property
private int loopIdx;
@Property
private List<User> authors;
@Property
private List<Chapter> chaptersInfo;
@Property
@Persist(PersistenceConstants.FLASH)
private String flashMessage;
@Property
@Persist(PersistenceConstants.FLASH)
private String[] errors;
private Chapter currentChapter;
/**
* Will be set if the author tries to add a new chapter
*/
@Property
private String chapterName;
@Property
private PageLink right;
private Long firstChapterId;
private String firstChapterTitle;
private boolean bookAuthor;
/**
* Prepare book display.
*/
@SetupRender
public void setupBookDisplay()
{
this.authors = this.getBook().getAuthors();
this.bookAuthor = this.securityCtx.canWrite(this.getBook());
// List chapter infos
chaptersInfo = chapterManager.listChaptersInfo(this.getBookId());
for (Chapter c : chaptersInfo)
{
if (isPublished(c.getId()))
{
this.firstChapterId = c.getId();
this.firstChapterTitle = c.getTitle();
break;
}
}
}
@SetupRender
public void setupNav()
{
selectMenuItem(0);
if ((firstChapterId != null) && (firstChapterTitle != null))
{
right = new NavLink("chapter/index", "nav-right", firstChapterTitle, getBookId(),
firstChapterId);
}
}
@AfterRender
public void setupChapterSort()
{
if (securityCtx.canWrite(getBook()))
{
JSONObject params = new JSONObject();
params.put("url", resources.createEventLink("reorder").toURI());
jsSupport.addInitializerCall("initAddChapterFocus", new JSONObject());
jsSupport.addInitializerCall("initSortChapters", params);
jsSupport.addInitializerCall("initTocRows", new JSONObject());
jsSupport.addInitializerCall("listenTocUpdate", new JSONObject());
}
}
@OnEvent(value = EventConstants.SUCCESS, component = "addChapterForm")
public Object addNewChapter()
{
try
{
bookManager.addChapter(this.getBook(), chapterName);
flashMessage = messages.format("chapter-add-success", chapterName);
return tocRefresh();
}
catch (Exception ex)
{
errors = new String[]
{ messages.get("chapter-add-failure") };
logger.error("An Error has occured while creating new chapter", ex);
return this;
}
}
@OnEvent(value = "reorder")
public void reorder(@RequestParameter(value = "chapterId") Long chapterId,
@RequestParameter(value = "newPos") int newPos)
{
bookManager.updateChapterIndex(getBookId(), chapterId, newPos);
}
@OnEvent(value = "publish")
public Object publish(Long chapterId)
{
try
{
Chapter toPublish = chapterManager.publishChapter(chapterId);
flashMessage = messages.format("chapter-publish-success", toPublish.getTitle());
return tocRefresh();
}
catch (Exception ex)
{
logger.error("An unexpected exception has occured during publish action", ex);
errors = new String[]
{ messages.get("chapter-publish-failure") };
return this;
}
}
@OnEvent(value = "delete")
public Object delete(Long chapterId)
{
try
{
Chapter toRemove = chapterManager.remove(chapterId);
flashMessage = messages.format("chapter-delete-success", toRemove.getTitle());
return tocRefresh();
}
catch (Exception ex)
{
logger.error("An unexpected exception has occured during delete action", ex);
errors = new String[]
{ messages.get("chapter-delete-failure") };
return this;
}
}
@OnEvent(value = EventConstants.PASSIVATE)
public Long retrieveBookId()
{
return this.getBookId();
}
public boolean isPublished(Long chapterId)
{
Publication publication = this.chapterManager.getLastPublishedPublication(chapterId);
return publication != null;
}
public boolean isPublished()
{
long chapterId = currentChapter.getId();
return isPublished(chapterId);
}
public boolean isShowWorkingCopyLink()
{
long chapterId = currentChapter.getId();
return hasWorkingCopy(chapterId);
}
private final boolean hasWorkingCopy(long chapterId)
{
Publication publication = this.chapterManager.getRevision(chapterId, ChapterManager.LAST);
if (publication != null)
{
boolean workingCopy = !publication.isPublished();
return bookAuthor && workingCopy;
}
return false;
}
/**
* Get id to link to chapter display
*
* @return
*/
public Object[] getChapterCtx()
{
return new Object[]
{ this.getBookId(), this.currentChapter.getId() };
}
public Object[] getChapterWorkingCopyCtx()
{
return new Object[]
{ this.getBookId(), this.currentChapter.getId(), ChapterManager.LAST };
}
public Chapter getCurrentChapter()
{
return currentChapter;
}
public void setCurrentChapter(Chapter currentChapter)
{
this.currentChapter = currentChapter;
}
/**
* If request is XHR then return the TOC block, otherwise refresh the whole page.
*
* @return
*/
private Object tocRefresh()
{
if (request.isXHR())
{
setupBookDisplay();
return tableOfContents.getBody();
}
return null;
}
}