/*
* Copyright (C) 2001 - 2003 Red Hat Inc. All Rights Reserved.
*
* The contents of this file are subject to the CCM Public
* License (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.redhat.com/licenses/ccmpl.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Created on Dec 19, 2003
*
*/
package com.arsdigita.cms.docmgr.ui;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.ExternalLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.PaginationModelBuilder;
import com.arsdigita.bebop.Paginator;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Tree;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.table.AbstractTableModelBuilder;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.cms.ContentBundle;
import com.arsdigita.cms.docmgr.DocFolder;
import com.arsdigita.cms.docmgr.DocLink;
import com.arsdigita.cms.docmgr.Document;
import com.arsdigita.cms.docmgr.search.SearchResult;
import com.arsdigita.cms.docmgr.search.SearchResults;
import com.arsdigita.dispatcher.ObjectNotFoundException;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelExcursion;
import com.arsdigita.kernel.Party;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.persistence.OID;
import com.arsdigita.versioning.Versions;
import java.math.BigDecimal;
import java.util.Iterator;
import org.apache.log4j.Logger;
/**
*
* A UI class used to create the objects of type DocLink.
* This class displays a table which contains the results of Documents searched
* by the user.
*
* Action column displays ActionLinks to create a Link to the Document
* displayed in the current row of the table.
*
* @author Shashin Shinde
*
* $Id: //apps/docmgr-cms/dev/src/com/arsdigita/cms/docmgr/ui/CreateDocLinkSearchTable.java#2 $
*
*/
public class CreateDocLinkSearchTable extends Table implements DMConstants{
private static final Logger s_log = Logger.getLogger(CreateDocLinkSearchTable.class);
public static final int PAGE_SIZE = 10;
/** Table Headers. */
private static String[] s_headers = {"Name", "Workspace/Application", "Action"};
private TableColumn m_createColumn;
private Component m_parent;
private Tree m_tree;
private CreateDocLinkPane m_linkPane;
/**
* Constructor.
* @param linkPane to which this Table is added.Used to display some error messages.
* @param parent. Used to return to after creating the link and cleaning up the Table selection.
* @param tree.Tree object to get the currently selected parent Folder under
* which to create the link.
* @param form.Search Form to get the terms to search for.
*/
CreateDocLinkSearchTable(CreateDocLinkPane linkPane, Component parent,Tree tree,SearchForm form){
super(new CreateDocLinkTableModelBuilder(form), s_headers);
m_parent = parent;
m_tree = tree;
m_linkPane = linkPane;
setWidth("100%");
setRenderers();
addTableActionListener(new LinkCreator());
}
/**Just private helper method to group adding of all renderers in one place.*/
private void setRenderers(){
getColumn(0).setCellRenderer(new NameCellRenderer());
getColumn(1).setCellRenderer(new WorkspaceCellRenderer());
m_createColumn = getColumn(2);
m_createColumn.setCellRenderer(new ActionCellRenderer());
m_createColumn.setAlign("center");
}
/**
* Extension of TableActionAdapter class only to work on clicks generated
* by ActionCellRenderer.
*/
private class LinkCreator extends TableActionAdapter {
public void cellSelected(TableActionEvent e) {
int col = e.getColumn().intValue();
if ( m_createColumn != getColumn(col) ) {
return;
}
PageState s = e.getPageState();
BigDecimal id = new BigDecimal(e.getRowKey().toString());
boolean valid = true;
OID oid = new OID(Document.TYPE, id.abs());
final Document doc = (Document) DomainObjectFactory.newInstance(oid);
final DocFolder parent = getSelectedFolder(s);
s_log.debug("Document Item: " + doc + " Parent Folder: " + parent);
//Performe some validation and update the error messages label.
if(doc.getParentResource().getID() == parent.getID()){
m_linkPane.getErrorLable().setLabel("Document in Same Folder",s);
valid = false;
}
try{
parent.retrieveSubResource(doc.getName());
m_linkPane.getErrorLable().setLabel(RESOURCE_EXISTS_ERROR,s);
valid = false;
}catch (DataObjectNotFoundException donf){
//Do nothing.
}
if(! valid){
((Table) e.getSource()).clearSelection(s);
return;
}
//Reached here indicates we can now proceed with Link Creation.
DocLink newLink;
BigDecimal doclinkID = (BigDecimal) s.getValue(m_linkPane.getEditDoclinkIDParam());
if (doclinkID != null) {
newLink = new DocLink(doclinkID);
newLink.setExternalURL(null);
}
else {
newLink = new DocLink();
}
newLink.setName(doc.getName());
newLink.setTitle(doc.getTitle());
newLink.setDescription(doc.getDescription());
//FIXME: when our client decides upon what permissions to adopt , change this one
//and permissions code accordingly.
newLink.setRepository(DocFolder.getRepository(parent));
newLink.setLanguage("en");
newLink.setTarget(doc);
Versions.tag(
newLink.getOID(),
(FILE_UPLOAD_INITIAL_TRANSACTION_DESCRIPTION
.localize(s.getRequest())
.toString()));
final ContentBundle bundle = new ContentBundle(newLink);
bundle.setParent(parent);
bundle.setContentSection(parent.getContentSection());
bundle.save();
new KernelExcursion() {
protected void excurse() {
Party currentParty = Kernel.getContext().getParty();
setParty(Kernel.getSystemParty());
PermissionService.setContext(bundle, parent);
}
}.run();
((Table) e.getSource()).clearSelection(s);
((BrowsePane) m_parent).displayFolderContentPanel(s);
}
}
/**
* Produce Links to the create a Link to the given Document in the current row.
*/
private static class ActionCellRenderer implements TableCellRenderer {
private final static Logger logger = Logger.getLogger(ActionCellRenderer.class);
private static ControlLink s_link;
static {
logger.debug("Static initalizer starting...");
s_link = new ControlLink(new Label(DMConstants.FOLDER_NEW_CREATE_LINK));
s_link.setConfirmation("Create Link to this Document ?");
logger.debug("Static initalizer finished.");
}
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
return s_link;
}
}
/**
* Compute the Workspace for the Document in the current row.We have to
* instantiate it in order to get it's repository and the workspace which
* is parent application of the repository.
*/
private static class WorkspaceCellRenderer implements TableCellRenderer {
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
SearchResult result = (SearchResult) value;
BigDecimal id = result.getID();
OID oid = new OID(Document.TYPE, id.abs());
final Document doc = (Document) DomainObjectFactory.newInstance(oid);
String workspace = doc.getRepository().getParentApplication().getDisplayName() + "/" + doc.getRepository().getDisplayName();
return new Label(workspace);
}
}
/**
* Produce External Links to view a Document displayed in the current row.
* Link is around it's name.
*/
private class NameCellRenderer extends DefaultTableCellRenderer {
public NameCellRenderer() {
super(true);
}
public Component getComponent(Table table, PageState state, Object value,
boolean isSelected, Object key,
int row, int column) {
SearchResult result = (SearchResult) value;
String url = result.getUrlStub();
ExternalLink m_title = new ExternalLink(result.getLink(), url);
return m_title;
}
}
/**Helper method to return the currently Selected Parent Folder in the tree */
private DocFolder getSelectedFolder(PageState state){
DocFolder p = null;
String selKey = (String) m_tree.getSelectedKey(state);
if (selKey == null) {
p = DMUtils.getRootFolder(state);
} else {
BigDecimal folderID = new BigDecimal(selKey);
try {
p = new DocFolder(folderID);
} catch (DataObjectNotFoundException nf) {
throw new ObjectNotFoundException(
(String) FOLDER_PARENTNOTFOUND_ERROR.localize(state.getRequest()));
}
}
return p;
}
/**
* Table model build around SearchResults.getResults iterator.
* The row count is the no. of rows returned as a result of search.
* Every row indicates one SearchResult object.
*/
private static class CreateDocLinkTableModel implements TableModel {
private static final int NAME = 0;
private static final int WORKSPACE = 1;
private static final int CREATABLE = 2;
private PageState m_state;
private CreateDocLinkSearchTable m_table;
private Iterator m_results;
private SearchResult m_result;
public CreateDocLinkTableModel
(CreateDocLinkSearchTable table, PageState state, SearchResults results) {
m_state = state;
m_table = table;
if ( results != null ) {
m_results = results.getResults();
s_log.debug("In CreateDocLinkTableModel - Iterator ID: " + m_results.toString());
}
}
public int getColumnCount() {
return 3;
}
public boolean nextRow() {
if ( m_results != null && m_results.hasNext() ) {
m_result = (SearchResult) m_results.next();
return true;
}
return false;
}
/**
* Just return the corresponding SearchResult object associated with the
* current row for all the columns.
*/
public Object getElementAt(int columnIndex) {
return m_result;
}
/**The ID of the Document in the current row is the key.*/
public Object getKeyAt(int columnIndex) {
return m_result.getID();
}
}
/**
* Search Table Model Builder.
* Also set's up the pagination for the Table.
*/
private static class CreateDocLinkTableModelBuilder
extends AbstractTableModelBuilder implements PaginationModelBuilder {
private RequestLocal m_resultsLocal;
private SearchForm m_form;
public CreateDocLinkTableModelBuilder(SearchForm form) {
super();
m_resultsLocal = new RequestLocal();
m_form = form;
}
/**
* Provide implementation for
* @see com.arsdigita.bebop.table.TableModelBuilder#makeModel(com.arsdigita.bebop.Table, com.arsdigita.bebop.PageState)
* Construct the table model from our SearchResults object
* which is provided by SearchForm.
*/
public TableModel makeModel(Table t, PageState ps) {
SearchResults results = (SearchResults) m_resultsLocal.get(ps);
if ( results == null ) {
return Table.EMPTY_MODEL;
} else {
t.getRowSelectionModel().clearSelection(ps);
return new CreateDocLinkTableModel
((CreateDocLinkSearchTable) t, ps, (SearchResults) m_resultsLocal.get(ps));
}
}
/**
* Provide implementation for
* @see com.arsdigita.bebop.PaginationModelBuilder#getTotalSize(com.arsdigita.bebop.Paginator, com.arsdigita.bebop.PageState)
* Return the size of SearchResults objects and set it into the
* RequestLocal cache.
*/
public int getTotalSize(Paginator p, PageState ps) {
SearchResults results = null;
if(m_resultsLocal.get(ps) == null){
results = m_form.getSearchHits(ps);
m_resultsLocal.set(ps,results);
}
if (results == null) {
return 0;
} else {
int totalSize = (int) results.getTotalSize();
s_log.debug("Setting paginator: size = " + results.getTotalSize() +
" first = " + p.getFirst(ps) + " last = " + p.getLast(ps));
results.setRange(new Integer(p.getFirst(ps)),new Integer(p.getLast(ps) + 1));
s_log.debug("totoalsize is "+ totalSize);
return totalSize;
}
}
public boolean isVisible(PageState state) {
return m_form.isVisible(state);
}
}
}