/**
* $URL:$
* $Id:$
*
* Copyright (c) 2006-2009 The Sakai Foundation
*
* Licensed under the Educational Community 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.opensource.org/licenses/ECL-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 org.sakaiproject.sitestats.tool.wicket.components;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Request;
import org.apache.wicket.RequestCycle;
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.HiddenField;
import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.protocol.http.WebResponse;
import org.apache.wicket.request.target.basic.EmptyRequestTarget;
import org.sakaiproject.content.api.ContentCollection;
import org.sakaiproject.content.api.ContentEntity;
import org.sakaiproject.exception.IdUnusedException;
import org.sakaiproject.exception.PermissionException;
import org.sakaiproject.exception.TypeException;
import org.sakaiproject.sitestats.api.StatsManager;
import org.sakaiproject.sitestats.tool.facade.Locator;
import org.sakaiproject.sitestats.tool.wicket.models.CHResourceModel;
import org.sakaiproject.sitestats.tool.wicket.pages.BasePage;
/**
* @author Nuno Fernandes
*/
public class FileSelectorPanel extends Panel {
private static final long serialVersionUID = 1L;
private static final String BASE_DIR = "/";
private String siteId;
private String siteTitle;
private boolean showDefaultBaseFoldersOnly;
private String currentDir = BASE_DIR;
private final AjaxResourcesLoader ajaxResourcesLoader = new AjaxResourcesLoader();
public FileSelectorPanel(String id, String siteId, boolean showDefaultBaseFoldersOnly) {
this(id, siteId, null, showDefaultBaseFoldersOnly);
}
public FileSelectorPanel(String id, String siteId, IModel model, boolean showDefaultBaseFoldersOnly) {
super(id, model);
this.siteId = siteId;
try{
this.siteTitle = Locator.getFacade().getSiteService().getSite(siteId).getTitle();
}catch(IdUnusedException e){
this.siteTitle = siteId;
}
this.showDefaultBaseFoldersOnly = showDefaultBaseFoldersOnly;
// selected files
HiddenField selectedFiles = new HiddenField("selectedFiles", new PropertyModel(this, "selectedFiles"));
add(selectedFiles);
// hover div (for disabling control)
WebMarkupContainer containerHover = new WebMarkupContainer("containerHover");
if(isEnabled()) {
containerHover.add(new AttributeModifier("style", true, new Model("display: block")));
}else{
containerHover.add(new AttributeModifier("style", true, new Model("display: none")));
}
add(containerHover);
add(ajaxResourcesLoader);
}
public List<String> getSelectedFilesId() {
List<String> files = (List<String>) getDefaultModelObject();
if(!showDefaultBaseFoldersOnly) {
List<String> files2 = new ArrayList<String>();
for(String f : files) {
if(StatsManager.RESOURCES_DIR.equals(f) || StatsManager.DROPBOX_DIR.equals(f) || StatsManager.ATTACHMENTS_DIR.equals(f)){
files2.add(f + siteId + "/");
}else{
files2.add(f);
}
}
return files2;
}
return files;
}
public void setSelectedFilesId(List<String> files) {
setDefaultModelObject(files);
}
public String getSelectedFiles() {
List<String> files = (List<String>) getDefaultModelObject();
StringBuilder filesEncoded = new StringBuilder();
for(String s : files) {
if(filesEncoded.length() != 0) {
filesEncoded.append("|||");
}
if(!showDefaultBaseFoldersOnly && (StatsManager.RESOURCES_DIR.equals(s) || StatsManager.DROPBOX_DIR.equals(s) || StatsManager.ATTACHMENTS_DIR.equals(s))){
filesEncoded.append(s + siteId + "/");
}else{
filesEncoded.append(s);
}
}
return filesEncoded.toString();
}
public void setSelectedFiles(String filesEncoded) {
List<String> files = new ArrayList<String>();
if(filesEncoded != null) {
String[] t = filesEncoded.split("\\|\\|\\|");
for(int i=0; i<t.length; i++) {
files.add(t[i]);
}
}
setDefaultModelObject(files);
}
private boolean isSelected(String resourceId) {
return getSelectedFilesId().contains(resourceId);
}
private boolean isFolderPartOfSelectedFiles(String collectionId) {
for(String id : getSelectedFilesId()) {
if(id.startsWith(collectionId)) {
return true;
}
}
return false;
}
@Override
public void renderHead(HtmlHeaderContainer container) {
container.getHeaderResponse().renderJavascriptReference(BasePage.JQUERYSCRIPT);
container.getHeaderResponse().renderJavascriptReference(StatsManager.SITESTATS_WEBAPP+"/html/components/jqueryFileTree/jqueryFileTree.js");
container.getHeaderResponse().renderCSSReference(StatsManager.SITESTATS_WEBAPP+"/html/components/jqueryFileTree/jqueryFileTree.css");
StringBuilder onDomReady = new StringBuilder();
onDomReady.append("jQuery('#containerInner').fileTree(");
onDomReady.append(" {root: '");
onDomReady.append(BASE_DIR);
onDomReady.append("', script: '");
onDomReady.append(ajaxResourcesLoader.getCallbackUrl());
onDomReady.append("', duration: 100},");
onDomReady.append(" function(file) {return false;}");
onDomReady.append(");");
container.getHeaderResponse().renderOnDomReadyJavascript(onDomReady.toString());
super.renderHead(container);
}
private List<CHResourceModel> getResources(String dir) throws IdUnusedException, TypeException, PermissionException {
List<CHResourceModel> resourcesList = new ArrayList<CHResourceModel>();
String resourcesCollectionId = null;
String dropboxCollectionId = null;
String attachmentsCollectionId = null;
if(!showDefaultBaseFoldersOnly) {
resourcesCollectionId = Locator.getFacade().getContentHostingService().getSiteCollection(siteId);
dropboxCollectionId = Locator.getFacade().getContentHostingService().getDropboxCollection(siteId);
attachmentsCollectionId = resourcesCollectionId.replaceFirst(StatsManager.RESOURCES_DIR, StatsManager.ATTACHMENTS_DIR);
}else{
resourcesCollectionId = StatsManager.RESOURCES_DIR;
dropboxCollectionId = StatsManager.DROPBOX_DIR;
attachmentsCollectionId = StatsManager.ATTACHMENTS_DIR;
}
if(dir.equals(BASE_DIR)) {
resourcesList.add(new CHResourceModel(resourcesCollectionId, Locator.getFacade().getToolManager().getTool(StatsManager.RESOURCES_TOOLID).getTitle()/*(String) new ResourceModel("report_content_resources").getObject()*/, true));
resourcesList.add(new CHResourceModel(dropboxCollectionId, Locator.getFacade().getToolManager().getTool(StatsManager.DROPBOX_TOOLID).getTitle()/*(String) new ResourceModel("report_content_dropbox").getObject()*/, true));
resourcesList.add(new CHResourceModel(attachmentsCollectionId, (String) new ResourceModel("report_content_attachments").getObject(), true));
}else if(!showDefaultBaseFoldersOnly) {
ContentCollection collection = Locator.getFacade().getContentHostingService().getCollection(dir);
if(collection != null) {
List<ContentEntity> members = collection.getMemberResources();
for(ContentEntity ce : members) {
String dispName = Locator.getFacade().getStatsManager().getResourceName("/content"+ce.getId(), false);
resourcesList.add(new CHResourceModel(ce.getId(), dispName, ce.isCollection()));
}
}
}
return resourcesList;
}
/**
* Ajax behavior for lazy loading CHS resources
* @author Nuno Fernandes
*/
private class AjaxResourcesLoader extends AbstractDefaultAjaxBehavior {
private static final long serialVersionUID = 1L;
@Override
protected void respond(AjaxRequestTarget target) {
// get dir
Request req = RequestCycle.get().getRequest();
try{
currentDir = req.getParameter("dir");
String enc = "UTF-8";
RequestCycle.get().setRequestTarget(EmptyRequestTarget.getInstance());
WebResponse response = (WebResponse) getResponse();
response.setContentType("text/html;charset="+enc);
OutputStream out = getResponse().getOutputStream();
try{
out.write("<ul class=\"jqueryFileTree\" style=\"display: none;\">".getBytes(enc));
boolean expandToSelection = currentDir.equals(BASE_DIR) && getSelectedFilesId() != null && getSelectedFilesId().size() > 0;
getResourcesMarkup(currentDir, out, expandToSelection, enc);
out.write("</ul>".getBytes(enc));
}finally{
out.close();
}
}catch(RuntimeException e){
// ignore - do nothing
}catch(Exception e){
// ignore - do nothing
}
}
private void getResourcesMarkup(String folder, OutputStream out, boolean expandToSelection, String encoding) throws IdUnusedException, TypeException, PermissionException, IOException, UnsupportedEncodingException {
List<CHResourceModel> list = getResources(folder);
if(list != null) {
for(CHResourceModel rm : list) {
if(rm.isCollection()) {
if(!expandToSelection
|| (expandToSelection && !isFolderPartOfSelectedFiles(rm.getResourceId()))
) {
StringBuilder collectionMarkup = new StringBuilder();
collectionMarkup.append(" <li class=\"directory collapsed\">");
collectionMarkup.append(" <input type=\"checkbox\" value=\""+rm.getResourceId()+"\" "+ (isSelected(rm.getResourceId()) ? "checked=\"checked\"" : "") +"onchange=\"updateFieldWithSelectedFiles('.selectedFiles')\"/>");
collectionMarkup.append(" <a href=\"#\" rel=\""+rm.getResourceId()+"\">"+rm.getResourceNameEscaped()+"</a>");
collectionMarkup.append(" </li>");
out.write(collectionMarkup.toString().getBytes(encoding));
}else{
StringBuilder collectionMarkup = new StringBuilder();
collectionMarkup.append(" <li class=\"directory expanded\" style=\"position: static;\">");
collectionMarkup.append(" <input type=\"checkbox\" value=\""+rm.getResourceId()+"\" "+ (isSelected(rm.getResourceId()) ? "checked=\"checked\"" : "") +"onchange=\"updateFieldWithSelectedFiles('.selectedFiles')\"/>");
collectionMarkup.append(" <a href=\"#\" rel=\""+rm.getResourceId()+"\">"+rm.getResourceNameEscaped()+"</a>");
collectionMarkup.append(" <ul style=\"display: block;\" class=\"jqueryFileTree\">");
out.write(collectionMarkup.toString().getBytes(encoding));
// get contents recursively
collectionMarkup = new StringBuilder();
getResourcesMarkup(rm.getResourceId(), out, expandToSelection, encoding);
collectionMarkup.append(" </ul>");
collectionMarkup.append(" </li>");
out.write(collectionMarkup.toString().getBytes(encoding));
}
}else{
StringBuilder markup = new StringBuilder();
markup.append(" <li class=\"file ext_"+rm.getResourceExtension()+"\">");
markup.append(" <input type=\"checkbox\" value=\""+rm.getResourceId()+"\" "+ (isSelected(rm.getResourceId()) ? "checked=\"checked\"" : "") +"onchange=\"updateFieldWithSelectedFiles('.selectedFiles')\"/>");
markup.append(" <span>"+rm.getResourceNameEscaped()+"</span>");
markup.append(" </li>");
out.write(markup.toString().getBytes(encoding));
}
}
}
}
}
}