/**********************************************************************************
* $URL: $
* $Id: $
***********************************************************************************
*
* Author: Charles Hedrick, hedrick@rutgers.edu
*
* Copyright (c) 2013 Rutgers, the State University of New Jersey
*
* 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.lessonbuildertool.ccexport;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Collections;
import java.util.SortedSet;
import java.util.SortedMap;
import java.util.TreeSet;
import java.util.TreeMap;
import java.util.Comparator;
import java.util.Date;
import java.util.Map;
import java.util.Iterator;
import java.net.URLEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.StringEscapeUtils;
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.w3c.dom.Document;
import org.sakaiproject.site.api.Group;
import org.sakaiproject.site.api.Site;
import org.sakaiproject.site.cover.SiteService;
import org.sakaiproject.tool.api.Session;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.tool.cover.SessionManager;
import org.sakaiproject.memory.api.Cache;
import org.sakaiproject.memory.api.CacheRefresher;
import org.sakaiproject.memory.api.MemoryService;
import uk.org.ponder.messageutil.MessageLocator;
import org.sakaiproject.lessonbuildertool.SimplePageItem;
import org.sakaiproject.lessonbuildertool.model.SimplePageToolDao;
import org.sakaiproject.db.cover.SqlService;
import org.sakaiproject.db.api.SqlReader;
import org.sakaiproject.content.api.ContentResource;
import org.sakaiproject.content.cover.ContentHostingService;
import java.sql.Connection;
import java.sql.ResultSet;
import org.sakaiproject.lessonbuildertool.ccexport.ZipPrintStream;
import org.sakaiproject.lessonbuildertool.service.LessonEntity;
import org.sakaiproject.assignment.api.Assignment;
import org.sakaiproject.assignment.api.AssignmentEdit;
import org.sakaiproject.assignment.api.AssignmentSubmission;
import org.sakaiproject.assignment.api.AssignmentContent;
import org.sakaiproject.assignment.api.AssignmentContentEdit;
import org.sakaiproject.assignment.cover.AssignmentService;
import org.sakaiproject.entity.api.Reference;
import org.sakaiproject.entity.api.ResourceProperties;
import org.sakaiproject.util.Validator;
/*
* set up as a singleton, but CCExport is not.
*/
public class AssignmentExport {
private static Log log = LogFactory.getLog(AssignmentExport.class);
private static SimplePageToolDao simplePageToolDao;
public void setSimplePageToolDao(Object dao) {
simplePageToolDao = (SimplePageToolDao) dao;
}
static MessageLocator messageLocator = null;
public void setMessageLocator(MessageLocator m) {
messageLocator = m;
}
static AssignmentExport next = null;
public void setNext(AssignmentExport n) {
next = n;
}
public void init () {
// currently nothing to do
log.info("init()");
}
public void destroy()
{
log.info("destroy()");
}
public List<AssignmentItem> getItemsInSite(String siteId) {
List<AssignmentItem> ret = new ArrayList<AssignmentItem>();
Iterator i = AssignmentService.getAssignmentsForContext(siteId);
while (i.hasNext()) {
Assignment assignment = (Assignment)i.next();
String deleted = assignment.getProperties().getProperty(ResourceProperties.PROP_ASSIGNMENT_DELETED);
if ((deleted == null || "".equals(deleted)) && !assignment.getDraft()) {
AssignmentContent content = assignment.getContent();
List<Reference>attachments = content.getAttachments();
String instructions = content.getInstructions();
AssignmentItem item = new AssignmentItem();
item.id = LessonEntity.ASSIGNMENT + "/" + assignment.getId().toString();
item.instructions = instructions;
item.attachments = new ArrayList<String>();
for (Reference ref: attachments) {
item.attachments.add(ref.getReference());
}
ret.add(item);
}
}
if (next != null) {
List<AssignmentItem>nextList = next.getItemsInSite(siteId);
if (nextList != null)
ret.addAll(nextList);
}
return ret;
}
// find topics in site, but organized by forum
public List<String> getEntitiesInSite(String siteId, CCExport bean) {
List<String> ret = new ArrayList<String>();
String siteRef = "/group/" + siteId + "/";
List<AssignmentItem>items = getItemsInSite(siteId);
for (AssignmentItem item: items) {
String instructions = item.instructions;
List<String>attachments = item.attachments;
// special case. one attachment and nothing else.
// just export the attachment
String intendeduse = null;
if ((instructions == null || instructions.trim().equals("")) &&
(attachments != null && attachments.size() == 1)) {
intendeduse = "assignment"; // simple case. just set intended use for attachment
} else { // complex case. need to do full assignment generation
ret.add(item.id);
}
// arrange to include the attachments
for (String sakaiId: attachments) {
if (sakaiId.startsWith("/content/"))
sakaiId = sakaiId.substring("/content".length());
String url = null;
// if it is a URL, need the URL rather than copying the file
try {
ContentResource resource = ContentHostingService.getResource(sakaiId);
String type = resource.getContentType();
if ("text/url".equals(type)) {
url = new String(resource.getContent());
}
} catch (Exception e) {
}
// if attachment isn't a file in resources, arrange for it to be included
if (url != null)
; // if it's a URL we don't need a file
else if (! sakaiId.startsWith(siteRef)) { // if in resources, already included
String assignmentId = item.id;
int i = assignmentId.indexOf("/");
assignmentId = assignmentId.substring(i+1);
int lastSlash = sakaiId.lastIndexOf("/");
String lastAtom = sakaiId.substring(lastSlash + 1);
bean.addFile(sakaiId, "attachments/" + assignmentId + "/" + lastAtom, intendeduse);
} else if (intendeduse != null) { // already there, just set intended use
bean.setIntendeduse(sakaiId, intendeduse);
}
}
}
return ret;
}
public static class AssignmentItem {
public String id;
public String title;
public String instructions;
public List<String> attachments;
}
public AssignmentItem getContents(String assignmentRef) {
if (!assignmentRef.startsWith(LessonEntity.ASSIGNMENT + "/")) {
if (next == null)
return null;
else
return next.getContents(assignmentRef);
}
AssignmentItem ret = new AssignmentItem();
ret.attachments = new ArrayList<String>();
int i = assignmentRef.indexOf("/");
String assignmentId = assignmentRef.substring(i+1);
ret.id = assignmentId;
Assignment assignment = null;
try {
assignment = AssignmentService.getAssignment(assignmentId);
} catch (Exception e) {
System.out.println("failed to find " + assignmentId);
return null;
}
ret.title = assignment.getTitle();
AssignmentContent content = assignment.getContent();
ret.instructions = content.getInstructions();
List<Reference>attachments = content.getAttachments();
for (Reference ref: attachments) {
String sakaiId = ref.getReference();
ret.attachments.add(sakaiId);
}
return ret;
}
// this is weird, because it's a web content, not a learning application. So we need to produce an HTML file
// with instructions and relative references to any attachments
public boolean outputEntity(String assignmentRef, ZipPrintStream out, PrintStream errStream, CCExport bean, CCExport.Resource resource) {
AssignmentItem contents = getContents(assignmentRef);
if (contents == null)
return false;
String title = contents.title;
String attachmentDir = "attachments/" + contents.id + "/";
String instructions = bean.relFixup(contents.instructions, resource);
List<String>attachments = contents.attachments;
out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">");
out.println("<body>");
if (instructions != null && !instructions.trim().equals("")) {
out.println("<div>");
out.println(instructions);
out.println("</div> ");
}
for (String sakaiId: attachments) {
if (sakaiId.startsWith("/content/"))
sakaiId = sakaiId.substring("/content".length());
String URL = null;
// if it is a URL, need the URL rather than copying the file
try {
ContentResource res = ContentHostingService.getResource(sakaiId);
String type = res.getContentType();
if ("text/url".equals(type)) {
URL = new String(res.getContent());
}
} catch (Exception e) {
}
String location = bean.getLocation(sakaiId);
int lastSlash = sakaiId.lastIndexOf("/");
String lastAtom = sakaiId.substring(lastSlash + 1);
if (URL != null) {
out.println("<a href=\"" + URL + "\">" + StringEscapeUtils.escapeHtml(URL) + "</a><br/>");
} else {
if (location.startsWith(attachmentDir))
URL = lastAtom; // if in attachment dir, relative reference
else
URL = "../../" + location; // else it's in the normal site content
URL = URL.replaceAll("//", "/");
try {
out.println("<a href=\"" + URLEncoder.encode(URL, "UTF-8") + "\">" + StringEscapeUtils.escapeHtml(lastAtom) + "</a><br/>");
} catch (java.io.UnsupportedEncodingException e) {
System.out.println("UTF-8 unsupported");
}
bean.addDependency(resource, sakaiId);
}
}
out.println("</body>");
out.println("</html>");
return true;
}
}