List of usage examples for java.text DateFormat setTimeZone
public void setTimeZone(TimeZone zone)
From source file:i5.las2peer.services.mobsos.SurveyService.java
/** * Marshals survey data in a result set from the MobSOS database to a JSON representation. *///from w ww . jav a 2 s . c o m private JSONObject readSurveyFromResultSet(ResultSet rs) throws SQLException { JSONObject o = new JSONObject(); o.put("id", rs.getInt("id")); o.put("name", rs.getString("name")); o.put("description", rs.getString("description")); o.put("owner", rs.getString("owner")); o.put("organization", rs.getString("organization")); o.put("logo", rs.getString("logo")); o.put("resource", rs.getString("resource")); o.put("qid", rs.getInt("qid")); long ts_start = rs.getTimestamp("start").getTime(); long ts_end = rs.getTimestamp("end").getTime(); DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String d_start = dateFormat.format(new Date(ts_start)); String d_end = dateFormat.format(new Date(ts_end)); //System.out.println(ts_start + " -> " + d_start); //System.out.println(ts_end + " -> " + d_end); o.put("start", d_start); o.put("end", d_end); o.put("lang", rs.getString("lang")); return o; }
From source file:net.bashtech.geobot.ReceiverBot.java
public String getTimeStreaming(String uptime) { uptime = uptime.replace("Z", "UTC"); DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); format.setTimeZone(java.util.TimeZone.getTimeZone("UTC")); try {//from w w w.j a v a2s . c o m Date then = format.parse(uptime); return "Streaming for " + this.getTimeTilNow(then) + "."; } catch (ParseException e) { e.printStackTrace(); } return "An error occurred or stream is offline."; }
From source file:org.codekaizen.vtj.text.BpDateFormatTest.java
/** * DOCUMENT ME!/*from w ww . j a va 2 s .c o m*/ * * @throws ParseException DOCUMENT ME! */ public void testParsing() throws ParseException { DateFormat fmt1 = null; DateFormat fmt2 = null; Date dt1 = null; Date dt2 = null; String s = null; fmt1 = new BpDateFormat(); fmt2 = new SimpleDateFormat("EEE MMM dd, yyyy"); s = "Mon Jul 29, 2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE, MMM dd, yyyy"); s = "Mon, Jul 29, 2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE,MMM dd, yyyy"); s = "Mon,Jul 29, 2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MM/dd/yyyy"); s = "11/17/2001"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEEEEE MM/dd/yyyy"); s = "Sunday 03/17/2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE MM/dd"); s = "THU 03/14"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MM/dd"); s = "03/14"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEEEEE: M/dd/yyyy"); s = "Sunday: 7/29/2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEEEEEE M/dd/yy"); s = "Tuesday 7/30/02"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("M/d/yy"); s = "7/3/02"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("M-d-yy"); s = "7-3-02"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MM-dd-yy"); s = "07-03-02"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-MM-dd"); s = "2002-07-03"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MM/d/yy"); s = "12/6/01"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MMddyy"); s = "072202"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE, MMM dd, yyyy"); s = "FRI, AUG 02, 2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS zzz"); s = "2002-01-21 12:00:00.000-0600"; dt1 = fmt1.parse(s); dt2 = fmt2.parse("2002-01-21 12:00:00.000 CST"); assertEquals(dt2, dt1); s = "2002-01-21T12:00:00.000-0600"; dt1 = fmt1.parse(s); dt2 = fmt2.parse("2002-01-21 12:00:00.000 CST"); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy zzz"); s = "Thu Jan 04 10:42:10 2001 CST"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy"); s = "Thu Jan 04 10:42:10 2001"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy"); s = "Sun Jul 18 22:51:47 PDT 1999"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("HH:mm:ss"); s = "10:42:10"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("hh:mm:ss aa"); s = "10:42:10 PM"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-'W'ww"); s = "2002-W28"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy\'W\'ww"); s = "2002W28"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("HH:mm"); s = "14:33"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS\'Z\'"); fmt2.setTimeZone(TimeZone.getTimeZone("UTC")); s = "2001-01-02 14:33:18.426Z"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-MM-dd\'T\'HH:mm:ss"); s = "2001-01-02T14:33:18"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MMM dd, yyyy"); s = "Jan 12, 1952"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("MM.dd.yy"); s = "12.13.52"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("h:mmaa"); s = "3:30pm"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("dd-MMM-yy"); s = "12-Jan-52"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("d-MMMMM-yyyy"); s = "8-August-2002"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("\'T\'HH:mm:ss"); s = "T14:33:18"; dt1 = fmt1.parse(s); dt2 = fmt2.parse(s); assertEquals(dt2, dt1); fmt2 = new SimpleDateFormat("yyyy-MM-dd\'T\'HH:mm:ssZ"); s = "2002-01-21T12:00:00-06:00"; dt1 = fmt1.parse(s); s = "2002-01-21T12:00:00-0600"; dt2 = fmt2.parse(s); assertEquals(dt2, dt1); }
From source file:org.apache.manifoldcf.crawler.connectors.rss.RSSConnector.java
/** Process a set of documents. * This is the method that should cause each document to be fetched, processed, and the results either added * to the queue of documents for the current job, and/or entered into the incremental ingestion manager. * The document specification allows this class to filter what is done based on the job. * The connector will be connected before this method can be called. *@param documentIdentifiers is the set of document identifiers to process. *@param statuses are the currently-stored document versions for each document in the set of document identifiers * passed in above./*from ww w . j av a 2 s . c om*/ *@param activities is the interface this method should use to queue up new document references * and ingest documents. *@param jobMode is an integer describing how the job is being run, whether continuous or once-only. *@param usesDefaultAuthority will be true only if the authority in use for these documents is the default one. */ @Override public void processDocuments(String[] documentIdentifiers, IExistingVersions statuses, Specification spec, IProcessActivity activities, int jobMode, boolean usesDefaultAuthority) throws ManifoldCFException, ServiceInterruption { getSession(); // The connection limit is designed to permit this connector to coexist with potentially other connectors, such as the web connector. // There is currently no good way to enforce connection limits across all installed connectors - this will require considerably more // thought to set up properly. int connectionLimit = 200; String[] fixedList = new String[2]; if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: In getDocumentVersions for " + Integer.toString(documentIdentifiers.length) + " documents"); Filter f = new Filter(spec, false); String[] acls = f.getAcls(); // Sort it, java.util.Arrays.sort(acls); // NOTE: There are two kinds of documents in here; documents that are RSS feeds (that presumably have a content-type // of text/xml), and documents that need to be indexed. // // For the latter, the metadata etc is part of the version string. For the former, the only thing that is part of the version string is the // document's checksum. // // The need to exclude documents from fetch based on whether they match an expression causes some difficulties, because we really // DON'T want this to apply to the feeds themselves. Since the distinguishing characteristic of a feed is that it is in the seed list, // and that its content-type is text/xml, we could use either of these characteristics to treat feeds differently from // fetchable urls. But the latter approach requires a fetch, which is forbidden. So - the spec will be used to characterize the url. // However, the spec might change, and the url might be dropped from the list - and then what?? // // The final solution is to simply not queue what cannot be mapped. int feedTimeout = f.getFeedTimeoutValue(); // The document specification has already been used to trim out documents that are not // allowed from appearing in the queue. So, even that has already been done. for (String documentIdentifier : documentIdentifiers) { // If it is in this list, we presume that it has been vetted against the map etc., so we don't do that again. We just fetch it. // And, if the content type is xml, we calculate the version as if it is a feed rather than a document. // Get the url String urlValue = documentIdentifier; if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Getting version string for '" + urlValue + "'"); String versionString; String ingestURL = null; String[] pubDates = null; String[] sources = null; String[] titles = null; String[] authorNames = null; String[] authorEmails = null; String[] categories = null; String[] descriptions = null; try { // If there's a carrydown "data" value for this url, we use that value rather than actually fetching the document. This also means we don't need to // do a robots check, because we aren't actually crawling anything. So, ALWAYS do this first... CharacterInput[] dechromedData = activities.retrieveParentDataAsFiles(urlValue, "data"); try { if (dechromedData.length > 0) { // Data already available. The fetch cycle can be entirely avoided, as can the robots check. ingestURL = f.mapDocumentURL(urlValue); if (ingestURL != null) { // Open up an input stream corresponding to the carrydown data. The stream will be encoded as utf-8. try { InputStream is = dechromedData[0].getUtf8Stream(); try { StringBuilder sb = new StringBuilder(); long checkSum = cache.addData(activities, urlValue, "text/html", is); // Grab what we need from the passed-down data for the document. These will all become part // of the version string. pubDates = activities.retrieveParentData(urlValue, "pubdate"); sources = activities.retrieveParentData(urlValue, "source"); titles = activities.retrieveParentData(urlValue, "title"); authorNames = activities.retrieveParentData(urlValue, "authorname"); authorEmails = activities.retrieveParentData(urlValue, "authoremail"); categories = activities.retrieveParentData(urlValue, "category"); descriptions = activities.retrieveParentData(urlValue, "description"); java.util.Arrays.sort(pubDates); java.util.Arrays.sort(sources); java.util.Arrays.sort(titles); java.util.Arrays.sort(authorNames); java.util.Arrays.sort(authorEmails); java.util.Arrays.sort(categories); java.util.Arrays.sort(descriptions); if (sources.length == 0) { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Warning; URL '" + ingestURL + "' doesn't seem to have any RSS feed source!"); } sb.append('+'); packList(sb, acls, '+'); if (acls.length > 0) { sb.append('+'); pack(sb, defaultAuthorityDenyToken, '+'); } else sb.append('-'); // The ingestion URL pack(sb, ingestURL, '+'); // The pub dates packList(sb, pubDates, '+'); // The titles packList(sb, titles, '+'); // The sources packList(sb, sources, '+'); // The categories packList(sb, categories, '+'); // The descriptions packList(sb, descriptions, '+'); // The author names packList(sb, authorNames, '+'); // The author emails packList(sb, authorEmails, '+'); // Do the checksum part, which does not need to be parseable. sb.append(new Long(checkSum).toString()); versionString = sb.toString(); } finally { is.close(); } } catch (java.net.SocketTimeoutException e) { throw new ManifoldCFException( "IO exception reading data from string: " + e.getMessage(), e); } catch (InterruptedIOException e) { throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED); } catch (IOException e) { throw new ManifoldCFException( "IO exception reading data from string: " + e.getMessage(), e); } } else { // Document a seed or unmappable; just skip if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Skipping carry-down document '" + urlValue + "' because it is unmappable or is a seed."); } } else { // Get the old version string String oldVersionString = statuses.getIndexedVersionString(documentIdentifier); // Unpack the old version as much as possible. // We are interested in what the ETag and Last-Modified headers were last time. String lastETagValue = null; String lastModifiedValue = null; // Note well: Non-continuous jobs cannot use etag because the rss document MUST be fetched each time for such jobs, // or the documents it points at would get deleted. // // NOTE: I disabled this code because we really need the feed's TTL value in order to reschedule properly. I can't get the // TTL value without refetching the document - therefore ETag and Last-Modified cannot be used :-( if (false && jobMode == JOBMODE_CONTINUOUS && oldVersionString != null && oldVersionString.startsWith("-")) { // It's a feed, so the last etag and last-modified fields should be encoded in this version string. StringBuilder lastETagBuffer = new StringBuilder(); int unpackPos = unpack(lastETagBuffer, oldVersionString, 1, '+'); StringBuilder lastModifiedBuffer = new StringBuilder(); unpackPos = unpack(lastModifiedBuffer, oldVersionString, unpackPos, '+'); if (lastETagBuffer.length() > 0) lastETagValue = lastETagBuffer.toString(); if (lastModifiedBuffer.length() > 0) lastModifiedValue = lastModifiedBuffer.toString(); } if (Logging.connectors.isDebugEnabled() && (lastETagValue != null || lastModifiedValue != null)) Logging.connectors.debug( "RSS: Document '" + urlValue + "' was found to have a previous ETag value of '" + ((lastETagValue == null) ? "null" : lastETagValue) + "' and a previous Last-Modified value of '" + ((lastModifiedValue == null) ? "null" : lastModifiedValue) + "'"); // Robots check. First, we need to separate the url into its components URL url; try { url = new URL(urlValue); } catch (MalformedURLException e) { Logging.connectors.debug("RSS: URL '" + urlValue + "' is malformed; skipping", e); activities.deleteDocument(documentIdentifier); continue; } String protocol = url.getProtocol(); int port = url.getPort(); String hostName = url.getHost(); String pathPart = url.getFile(); // Check with robots to see if it's allowed if (robotsUsage >= ROBOTS_DATA && !robots.isFetchAllowed(currentContext, throttleGroupName, protocol, port, hostName, url.getPath(), userAgent, from, proxyHost, proxyPort, proxyAuthDomain, proxyAuthUsername, proxyAuthPassword, activities, connectionLimit)) { activities.recordActivity(null, ACTIVITY_FETCH, null, urlValue, Integer.toString(-2), "Robots exclusion", null); if (Logging.connectors.isDebugEnabled()) Logging.connectors .debug("RSS: Skipping url '" + urlValue + "' because robots.txt says to"); activities.deleteDocument(documentIdentifier); continue; } // Now, use the fetcher, and get the file. IThrottledConnection connection = fetcher.createConnection(currentContext, throttleGroupName, hostName, connectionLimit, feedTimeout, proxyHost, proxyPort, proxyAuthDomain, proxyAuthUsername, proxyAuthPassword, activities); try { // Begin the fetch connection.beginFetch("Data"); try { // Execute the request. // Use the connect timeout from the document specification! int status = connection.executeFetch(protocol, port, pathPart, userAgent, from, lastETagValue, lastModifiedValue); switch (status) { case IThrottledConnection.STATUS_NOCHANGE: versionString = oldVersionString; break; case IThrottledConnection.STATUS_OK: try { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Successfully fetched " + urlValue); // Document successfully fetched! // If its content is xml, presume it's a feed... String contentType = connection.getResponseHeader("Content-Type"); // Some sites have multiple content types. We just look at the LAST one in that case. if (contentType != null) { String[] contentTypes = contentType.split(","); if (contentTypes.length > 0) contentType = contentTypes[contentTypes.length - 1].trim(); else contentType = null; } String strippedContentType = contentType; if (strippedContentType != null) { int pos = strippedContentType.indexOf(";"); if (pos != -1) strippedContentType = strippedContentType.substring(0, pos).trim(); } boolean isXML = (strippedContentType != null && xmlContentTypes.contains(strippedContentType)); ingestURL = null; if (!isXML) { // If the chromed content mode is set to "skip", and we got here, it means // we should not include the content. if (f.getChromedContentMode() == CHROMED_SKIP) { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Removing url '" + urlValue + "' because it no longer has dechromed content available"); versionString = null; break; } // Decide whether to exclude this document based on what we see here. // Basically, we want to get rid of everything that we don't know what // to do with in the ingestion system. if (!activities.checkMimeTypeIndexable(contentType)) { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Removing url '" + urlValue + "' because it had the wrong content type: " + ((contentType == null) ? "null" : "'" + contentType + "'")); versionString = null; break; } ingestURL = f.mapDocumentURL(urlValue); } else { if (Logging.connectors.isDebugEnabled()) Logging.connectors .debug("RSS: The url '" + urlValue + "' is a feed"); if (!f.isSeed(urlValue)) { // Remove the feed from consideration, since it has left the list of seeds if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Removing feed url '" + urlValue + "' because it is not a seed."); versionString = null; break; } } InputStream is = connection.getResponseBodyStream(); try { long checkSum = cache.addData(activities, urlValue, contentType, is); StringBuilder sb = new StringBuilder(); if (ingestURL != null) { // We think it is ingestable. The version string accordingly starts with a "+". // Grab what we need from the passed-down data for the document. These will all become part // of the version string. pubDates = activities.retrieveParentData(urlValue, "pubdate"); sources = activities.retrieveParentData(urlValue, "source"); titles = activities.retrieveParentData(urlValue, "title"); authorNames = activities.retrieveParentData(urlValue, "authorname"); authorEmails = activities.retrieveParentData(urlValue, "authoremail"); categories = activities.retrieveParentData(urlValue, "category"); descriptions = activities.retrieveParentData(urlValue, "description"); java.util.Arrays.sort(pubDates); java.util.Arrays.sort(sources); java.util.Arrays.sort(titles); java.util.Arrays.sort(authorNames); java.util.Arrays.sort(authorEmails); java.util.Arrays.sort(categories); java.util.Arrays.sort(descriptions); if (sources.length == 0) { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Warning; URL '" + ingestURL + "' doesn't seem to have any RSS feed source!"); } sb.append('+'); packList(sb, acls, '+'); if (acls.length > 0) { sb.append('+'); pack(sb, defaultAuthorityDenyToken, '+'); } else sb.append('-'); // The ingestion URL pack(sb, ingestURL, '+'); // The pub dates packList(sb, pubDates, '+'); // The titles packList(sb, titles, '+'); // The sources packList(sb, sources, '+'); // The categories packList(sb, categories, '+'); // The descriptions packList(sb, descriptions, '+'); // The author names packList(sb, authorNames, '+'); // The author emails packList(sb, authorEmails, '+'); } else { sb.append('-'); String etag = connection.getResponseHeader("ETag"); if (etag == null) pack(sb, "", '+'); else pack(sb, etag, '+'); String lastModified = connection.getResponseHeader("Last-Modified"); if (lastModified == null) pack(sb, "", '+'); else pack(sb, lastModified, '+'); } // Do the checksum part, which does not need to be parseable. sb.append(new Long(checkSum).toString()); versionString = sb.toString(); } finally { is.close(); } } catch (java.net.SocketTimeoutException e) { Logging.connectors .warn("RSS: Socket timeout exception fetching document contents '" + urlValue + "' - skipping: " + e.getMessage(), e); versionString = null; } catch (ConnectTimeoutException e) { Logging.connectors .warn("RSS: Connecto timeout exception fetching document contents '" + urlValue + "' - skipping: " + e.getMessage(), e); versionString = null; } catch (InterruptedIOException e) { throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED); } catch (IOException e) { Logging.connectors.warn("RSS: IO exception fetching document contents '" + urlValue + "' - skipping: " + e.getMessage(), e); versionString = null; } break; case IThrottledConnection.STATUS_SITEERROR: case IThrottledConnection.STATUS_PAGEERROR: default: // Record an *empty* version. // This signals the processDocuments() method that we really don't want to ingest this document, but we also don't // want to blow the document out of the queue, since then we'd wind up perhaps fetching it multiple times. versionString = ""; break; } } finally { connection.doneFetch(activities); } } finally { connection.close(); } if (versionString == null) { activities.deleteDocument(documentIdentifier); continue; } if (!(versionString.length() == 0 || activities.checkDocumentNeedsReindexing(documentIdentifier, versionString))) continue; // Process document! if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Processing '" + urlValue + "'"); // The only links we extract come from documents that we think are RSS feeds. // When we think that's the case, we attempt to parse it as RSS XML. if (ingestURL == null) { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Interpreting document '" + urlValue + "' as a feed"); // We think it is a feed. // If this is a continuous job, AND scanonly is true, it means that the document was either identical to the // previous fetch, or was not fetched at all. In that case, it may not even be there, and we *certainly* don't // want to attempt to process it in any case. // // NOTE: I re-enabled the scan permanently because we need the TTL value to be set whatever the cost. If the // TTL value is not set, we default to the specified job's feed-rescan time, which is not going to be current enough for some feeds. if (true || jobMode != JOBMODE_CONTINUOUS) { handleRSSFeedSAX(urlValue, activities, f); if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Extraction of feed '" + urlValue + "' complete"); // Record the feed's version string, so we won't refetch unless needed. // This functionality is required for the last ETag and Last-Modified fields to be sent to the rss server, and to // keep track of the adaptive parameters. activities.recordDocument(documentIdentifier, versionString); } else { // The problem here is that we really do need to set the rescan time to something reasonable. // But we might not even have read the feed! So what to do?? // One answer is to build a connector-specific table that carries the last value of every feed around. // Another answer is to change the version code to always read the feed (and the heck with ETag and Last-Modified). if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Feed '" + urlValue + "' does not appear to differ from previous fetch for a continuous job; not extracting!"); long currentTime = System.currentTimeMillis(); Long defaultRescanTime = f.getDefaultRescanTime(currentTime); if (defaultRescanTime != null) { Long minimumTime = f.getMinimumRescanTime(currentTime); if (minimumTime != null) { if (defaultRescanTime.longValue() < minimumTime.longValue()) defaultRescanTime = minimumTime; } } activities.setDocumentScheduleBounds(urlValue, defaultRescanTime, defaultRescanTime, null, null); } } else { if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Interpreting '" + urlValue + "' as a document"); String errorCode = null; String errorDesc = null; long startTime = System.currentTimeMillis(); Long fileLengthLong = null; try { long documentLength = cache.getDataLength(documentIdentifier); if (!activities.checkLengthIndexable(documentLength)) { activities.noDocument(documentIdentifier, versionString); errorCode = activities.EXCLUDED_LENGTH; errorDesc = "Document rejected because of length (" + documentLength + ")"; if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Skipping document '" + urlValue + "' because its length was rejected (" + documentLength + ")"); continue; } if (!activities.checkURLIndexable(documentIdentifier)) { activities.noDocument(documentIdentifier, versionString); errorCode = activities.EXCLUDED_URL; errorDesc = "Document rejected because of URL ('" + documentIdentifier + "')"; if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Skipping document '" + urlValue + "' because its URL was rejected ('" + documentIdentifier + "')"); continue; } // Check if it's a recognized content type String contentType = cache.getContentType(documentIdentifier); // Some sites have multiple content types. We just look at the LAST one in that case. if (contentType != null) { String[] contentTypes = contentType.split(","); if (contentTypes.length > 0) contentType = contentTypes[contentTypes.length - 1].trim(); else contentType = null; } if (!activities.checkMimeTypeIndexable(contentType)) { activities.noDocument(documentIdentifier, versionString); errorCode = activities.EXCLUDED_MIMETYPE; errorDesc = "Document rejected because of mime type (" + contentType + ")"; if (Logging.connectors.isDebugEnabled()) Logging.connectors.debug("RSS: Skipping document '" + urlValue + "' because its mime type was rejected ('" + contentType + "')"); continue; } // Treat it as an ingestable document. long dataSize = cache.getDataLength(urlValue); RepositoryDocument rd = new RepositoryDocument(); // Set content type if (contentType != null) rd.setMimeType(contentType); // Turn into acls and add into description String[] denyAcls; if (acls == null) denyAcls = null; else if (acls.length == 0) denyAcls = new String[0]; else denyAcls = new String[] { defaultAuthorityDenyToken }; if (acls != null && denyAcls != null) rd.setSecurity(RepositoryDocument.SECURITY_TYPE_DOCUMENT, acls, denyAcls); if (titles != null && titles.length > 0) rd.addField("title", titles); if (authorNames != null && authorNames.length > 0) rd.addField("authorname", authorNames); if (authorEmails != null && authorEmails.length > 0) rd.addField("authoremail", authorEmails); if (descriptions != null && descriptions.length > 0) rd.addField("summary", descriptions); if (sources != null && sources.length > 0) rd.addField("source", sources); if (categories != null && categories.length > 0) rd.addField("category", categories); // The pubdates are a ms since epoch value; we want the minimum one for the origination time. Long minimumOrigTime = null; if (pubDates != null && pubDates.length > 0) { String[] pubDateValuesISO = new String[pubDates.length]; TimeZone tz = TimeZone.getTimeZone("UTC"); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); df.setTimeZone(tz); for (int k = 0; k < pubDates.length; k++) { String pubDate = pubDates[k]; try { Long pubDateLong = new Long(pubDate); if (minimumOrigTime == null || pubDateLong.longValue() < minimumOrigTime.longValue()) minimumOrigTime = pubDateLong; pubDateValuesISO[k] = df.format(new Date(pubDateLong.longValue())); } catch (NumberFormatException e) { // Do nothing; the version string seems to not mean anything pubDateValuesISO[k] = ""; } } rd.addField("pubdate", pubDates); rd.addField("pubdateiso", pubDateValuesISO); } if (minimumOrigTime != null) activities.setDocumentOriginationTime(urlValue, minimumOrigTime); InputStream is = cache.getData(urlValue); if (is != null) { try { rd.setBinary(is, dataSize); try { activities.ingestDocumentWithException(documentIdentifier, versionString, ingestURL, rd); errorCode = "OK"; fileLengthLong = new Long(dataSize); } catch (IOException e) { errorCode = e.getClass().getSimpleName().toUpperCase(Locale.ROOT); errorDesc = e.getMessage(); handleIOException(e, "reading data"); } } finally { try { is.close(); } catch (IOException e) { errorCode = e.getClass().getSimpleName().toUpperCase(Locale.ROOT); errorDesc = e.getMessage(); handleIOException(e, "closing stream"); } } } } catch (ManifoldCFException e) { if (e.getErrorCode() == ManifoldCFException.INTERRUPTED) errorCode = null; throw e; } finally { if (errorCode != null) activities.recordActivity(new Long(startTime), ACTIVITY_PROCESS, null, urlValue, errorCode, errorDesc, null); } } } } finally { for (CharacterInput ci : dechromedData) { if (ci != null) ci.discard(); } } } finally { // Remove any fetched documents. cache.deleteData(documentIdentifier); } } }
From source file:org.sakaiproject.calendar.tool.CalendarAction.java
/** * Build the context for showing week view *///from w w w .j av a2 s.com protected void buildWeekContext(VelocityPortlet portlet, Context context, RunData runData, CalendarActionState state) { Calendar calendarObj = null; //Time st,et = null; //CalendarUtil calObj= null; MyYear yearObj = null; MyMonth monthObj1 = null; MyWeek weekObj = null; MyDay dayObj = null; MyDate dateObj1, dateObj2 = null; int dayofweek = 0; // new objects of myYear, myMonth, myDay, myWeek classes yearObj = new MyYear(); monthObj1 = new MyMonth(); weekObj = new MyWeek(); dayObj = new MyDay(); dateObj1 = new MyDate(); CalendarEventVector CalendarEventVectorObj = null; //calObj = state.getCalObj(); String peid = ((JetspeedRunData) runData).getJs_peid(); SessionState sstate = ((JetspeedRunData) runData).getPortletSessionState(peid); Time m_time = TimeService.newTime(); TimeBreakdown b = m_time.breakdownLocal(); int stateYear = b.getYear(); int stateMonth = b.getMonth(); int stateDay = b.getDay(); if ((sstate.getAttribute(STATE_YEAR) != null) && (sstate.getAttribute(STATE_MONTH) != null) && (sstate.getAttribute(STATE_DAY) != null)) { stateYear = ((Integer) sstate.getAttribute(STATE_YEAR)).intValue(); stateMonth = ((Integer) sstate.getAttribute(STATE_MONTH)).intValue(); stateDay = ((Integer) sstate.getAttribute(STATE_DAY)).intValue(); } CalendarUtil calObj = new CalendarUtil(); calObj.setDay(stateYear, stateMonth, stateDay); int iii = 0; dateObj1.setTodayDate(calObj.getMonthInteger(), calObj.getDayOfMonth(), calObj.getYear()); yearObj.setYear(calObj.getYear()); monthObj1.setMonth(calObj.getMonthInteger()); dayObj.setDay(calObj.getDayOfMonth()); String calId = state.getPrimaryCalendarReference(); // this loop will move the calendar to the begining of the week if (CalendarService.allowGetCalendar(calId) == false) { context.put(ALERT_MSG_KEY, rb.getString("java.alert.younotallow")); return; } else { try { calendarObj = CalendarService.getCalendar(calId); } catch (IdUnusedException e) { try { CalendarService.commitCalendar(CalendarService.addCalendar(calId)); calendarObj = CalendarService.getCalendar(calId); } catch (Exception err) { context.put(ALERT_MSG_KEY, rb.getString("java.alert.therenoactv")); M_log.debug(".buildWeekContext(): " + err); return; } } catch (PermissionException e) { context.put(ALERT_MSG_KEY, rb.getString("java.alert.younotperm")); M_log.debug(".buildWeekContext(): " + e); return; } } if (calendarObj.allowGetEvents() == true) { CalendarEventVectorObj = CalendarService.getEvents( getCalendarReferenceList(portlet, state.getPrimaryCalendarReference(), isOnWorkspaceTab()), getWeekTimeRange(calObj)); } else { CalendarEventVectorObj = new CalendarEventVector(); } calObj.setDay(dateObj1.getYear(), dateObj1.getMonth(), dateObj1.getDay()); dayofweek = calObj.getDay_Of_Week(true); calObj.setPrevDate(dayofweek - 1); dayofweek = calObj.getDay_Of_Week(true); Time[] pageStartTime = new Time[7]; Time[] pageEndTime = new Time[7]; for (int i = 7; i >= dayofweek; i--) { Vector eventVector = new Vector(); Vector eventVector1; dateObj2 = new MyDate(); dateObj2.setTodayDate(calObj.getMonthInteger(), calObj.getDayOfMonth(), calObj.getYear()); dateObj2.setDayName(calendarUtilGetDay(calObj.getDay_Of_Week(true))); dateObj2.setNameOfMonth(calendarUtilGetMonth(calObj.getMonthInteger())); if (calObj.getDayOfMonth() == dayObj.getDay()) dateObj2.setFlag(1); if (state.getCurrentPage().equals("third")) { eventVector1 = new Vector(); // JS -- the third page starts at 2PM(14 o'clock), and lasts 20 half-hour eventVector = getNewEvents(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), state, runData, THIRD_PAGE_START_HOUR, 19, context, CalendarEventVectorObj); for (int index = 0; index < eventVector1.size(); index++) { eventVector.add(eventVector.size(), eventVector1.get(index)); } // Reminder: weekview vm is using 0..6 pageStartTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), THIRD_PAGE_START_HOUR, 0, 0, 0); pageEndTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), 23, 59, 0, 0); } else if (state.getCurrentPage().equals("second")) { eventVector = getNewEvents(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), state, runData, SECOND_PAGE_START_HOUR, 19, context, CalendarEventVectorObj); // Reminder: weekview vm is using 0..6 pageStartTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), SECOND_PAGE_START_HOUR, 0, 0, 0); pageEndTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), 17, 59, 0, 0); } else { eventVector1 = new Vector(); // JS -- the first page starts at 12AM(0 o'clock), and lasts 20 half-hour eventVector1 = getNewEvents(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), state, runData, FIRST_PAGE_START_HOUR, 19, context, CalendarEventVectorObj); for (int index = 0; index < eventVector1.size(); index++) { eventVector.insertElementAt(eventVector1.get(index), index); } // Reminder: weekview vm is using 0..6 pageStartTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), 0, 0, 0, 0); pageEndTime[i - 1] = TimeService.newTimeLocal(calObj.getYear(), calObj.getMonthInteger(), calObj.getDayOfMonth(), 9, 59, 0, 0); } dateObj2.setEventBerWeek(eventVector); weekObj.setWeek(7 - i, dateObj2); // the purpose of this if condition is to check if we reached day 7 if yes do not // call next day. if (i > dayofweek) calObj.nextDate(); } calObj.setDay(yearObj.getYear(), monthObj1.getMonth(), dayObj.getDay()); context.put("week", weekObj); context.put("helper", new Helper()); context.put("date", dateObj1); context.put("page", state.getCurrentPage()); state.setState("week"); context.put("tlang", rb); context.put("config", configProps); context.put("message", state.getState()); DateFormat formatter = DateFormat.getDateInstance(DateFormat.FULL, new ResourceLoader().getLocale()); formatter.setTimeZone(TimeService.getLocalTimeZone()); try { context.put("beginWeek", formatter.format(calObj.getPrevTime(calObj.getDay_Of_Week(true) - 1))); } catch (Exception e) { context.put("beginWeek", calObj.getTodayDate()); } try { calObj.setNextWeek(); context.put("endWeek", formatter.format(calObj.getPrevTime(1))); } catch (Exception e) { context.put("endWeek", calObj.getTodayDate()); } buildMenu(portlet, context, runData, state, CalendarPermissions.allowCreateEvents(state.getPrimaryCalendarReference(), state.getSelectedCalendarReference()), CalendarPermissions.allowDeleteEvent(state.getPrimaryCalendarReference(), state.getSelectedCalendarReference(), state.getCalendarEventId()), CalendarPermissions.allowReviseEvents(state.getPrimaryCalendarReference(), state.getSelectedCalendarReference(), state.getCalendarEventId()), CalendarPermissions.allowMergeCalendars(state.getPrimaryCalendarReference()), CalendarPermissions.allowModifyCalendarProperties(state.getPrimaryCalendarReference()), CalendarPermissions.allowImport(state.getPrimaryCalendarReference()), CalendarPermissions.allowSubscribe(state.getPrimaryCalendarReference()), CalendarPermissions.allowSubscribeThis(state.getPrimaryCalendarReference())); calObj.setDay(yearObj.getYear(), monthObj1.getMonth(), dayObj.getDay()); context.put("realDate", TimeService.newTime()); context.put("tlang", rb); context.put("config", configProps); Vector vec = new Vector(); context.put("vec", vec); Vector conflictVec = new Vector(); context.put("conflictVec", conflictVec); Vector calVec = new Vector(); context.put("calVec", calVec); HashMap hm = new HashMap(); context.put("hm", hm); Integer intObj = Integer.valueOf(0); context.put("intObj", intObj); context.put("pageStartTime", pageStartTime); context.put("pageEndTime", pageEndTime); context.put("selectedView", rb.getString("java.byweek")); context.put("dayOfWeekNames", calObj.getCalendarDaysOfWeekNames(false)); }
From source file:org.sakaiproject.lessonbuildertool.tool.producers.ShowPageProducer.java
public void fillComponents(UIContainer tofill, ViewParameters viewParams, ComponentChecker checker) { GeneralViewParameters params = (GeneralViewParameters) viewParams; UIOutput.make(tofill, "html") .decorate(new UIFreeAttributeDecorator("lang", localegetter.get().getLanguage())) .decorate(new UIFreeAttributeDecorator("xml:lang", localegetter.get().getLanguage())); UIOutput.make(tofill, "datepicker").decorate( new UIFreeAttributeDecorator("src", (majorVersion >= 10 ? "/library" : "/lessonbuilder-tool") + "/js/lang-datepicker/lang-datepicker.js")); boolean iframeJavascriptDone = false; // security model: // canEditPage and canReadPage are normal Sakai privileges. They apply // to all/*from w w w . ja v a2 s. c o m*/ // pages in the site. // However when presented with a page, we need to make sure it's // actually in // this site, or users could get to pages in other sites. That's done // by updatePageObject. The model is that producers always work on the // current page, and updatePageObject makes sure that is in the current // site. // At that point we can safely use canEditPage. // somewhat misleading. sendingPage specifies the page we're supposed to // go to. If path is "none", we don't want this page to be what we see // when we come back to the tool if (params.getSendingPage() != -1) { // will fail if page not in this site // security then depends upon making sure that we only deal with // this page try { simplePageBean.updatePageObject(params.getSendingPage(), !params.getPath().equals("none")); } catch (Exception e) { log.warn("ShowPage permission exception " + e); UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.not_available")); return; } } boolean canEditPage = simplePageBean.canEditPage(); boolean canReadPage = simplePageBean.canReadPage(); boolean canSeeAll = simplePageBean.canSeeAll(); // always on if caneditpage boolean cameFromGradingPane = params.getPath().equals("none"); TimeZone localtz = timeService.getLocalTimeZone(); isoDateFormat.setTimeZone(localtz); if (!canReadPage) { // this code is intended for the situation where site permissions // haven't been set up. // So if the user can't read the page (which is pretty abnormal), // see if they have site.upd. // if so, give them some explanation and offer to call the // permissions helper String ref = "/site/" + simplePageBean.getCurrentSiteId(); if (simplePageBean.canEditSite()) { SimplePage currentPage = simplePageBean.getCurrentPage(); UIOutput.make(tofill, "needPermissions"); GeneralViewParameters permParams = new GeneralViewParameters(); permParams.setSendingPage(-1L); createStandardToolBarLink(PermissionsHelperProducer.VIEW_ID, tofill, "callpermissions", "simplepage.permissions", permParams, "simplepage.permissions.tooltip"); } // in any case, tell them they can't read the page UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.nopermissions")); return; } String addBefore = params.getAddBefore(); if (params.addTool == GeneralViewParameters.COMMENTS) { simplePageBean.addCommentsSection(addBefore); } else if (params.addTool == GeneralViewParameters.STUDENT_CONTENT) { simplePageBean.addStudentContentSection(addBefore); } else if (params.addTool == GeneralViewParameters.STUDENT_PAGE) { simplePageBean.createStudentPage(params.studentItemId); canEditPage = simplePageBean.canEditPage(); } // Find the MSIE version, if we're running it. int ieVersion = checkIEVersion(); // as far as I can tell, none of these supports fck or ck // we can make it configurable if necessary, or use WURFL // however this test is consistent with CKeditor's check. // that desireable, since if CKeditor is going to use a bare // text block, we want to handle it as noEditor String userAgent = httpServletRequest.getHeader("User-Agent"); if (userAgent == null) userAgent = ""; boolean noEditor = userAgent.toLowerCase().indexOf("mobile") >= 0; // set up locale Locale M_locale = null; String langLoc[] = localegetter.get().toString().split("_"); if (langLoc.length >= 2) { if ("en".equals(langLoc[0]) && "ZA".equals(langLoc[1])) { M_locale = new Locale("en", "GB"); } else { M_locale = new Locale(langLoc[0], langLoc[1]); } } else { M_locale = new Locale(langLoc[0]); } // clear session attribute if necessary, after calling Samigo String clearAttr = params.getClearAttr(); if (clearAttr != null && !clearAttr.equals("")) { Session session = SessionManager.getCurrentSession(); // don't let users clear random attributes if (clearAttr.startsWith("LESSONBUILDER_RETURNURL")) { session.setAttribute(clearAttr, null); } } if (htmlTypes == null) { String mmTypes = ServerConfigurationService.getString("lessonbuilder.html.types", DEFAULT_HTML_TYPES); htmlTypes = mmTypes.split(","); for (int i = 0; i < htmlTypes.length; i++) { htmlTypes[i] = htmlTypes[i].trim().toLowerCase(); } Arrays.sort(htmlTypes); } if (mp4Types == null) { String m4Types = ServerConfigurationService.getString("lessonbuilder.mp4.types", DEFAULT_MP4_TYPES); mp4Types = m4Types.split(","); for (int i = 0; i < mp4Types.length; i++) { mp4Types[i] = mp4Types[i].trim().toLowerCase(); } Arrays.sort(mp4Types); } if (html5Types == null) { String jTypes = ServerConfigurationService.getString("lessonbuilder.html5.types", DEFAULT_HTML5_TYPES); html5Types = jTypes.split(","); for (int i = 0; i < html5Types.length; i++) { html5Types[i] = html5Types[i].trim().toLowerCase(); } Arrays.sort(html5Types); } // remember that page tool was reset, so we need to give user the option // of going to the last page from the previous session SimplePageToolDao.PageData lastPage = simplePageBean.toolWasReset(); // if this page was copied from another site we may have to update links // can only do the fixups if you can write. We could hack permissions, but // I assume a site owner will access the site first if (canEditPage) simplePageBean.maybeUpdateLinks(); // if starting the tool, sendingpage isn't set. the following call // will give us the top page. SimplePage currentPage = simplePageBean.getCurrentPage(); // now we need to find our own item, for access checks, etc. SimplePageItem pageItem = null; if (currentPage != null) { pageItem = simplePageBean.getCurrentPageItem(params.getItemId()); } // one more security check: make sure the item actually involves this // page. // otherwise someone could pass us an item from a different page in // another site // actually this normally happens if the page doesn't exist and we don't // have permission to create it if (currentPage == null || pageItem == null || (pageItem.getType() != SimplePageItem.STUDENT_CONTENT && Long.valueOf(pageItem.getSakaiId()) != currentPage.getPageId())) { log.warn("ShowPage item not in page"); UIOutput.make(tofill, "error-div"); if (currentPage == null) // most likely tool was created by site info but no page // has created. It will created the first time an item is created, // so from a user point of view it looks like no item has been added UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.noitems_error_user")); else UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.not_available")); return; } // the reason for a seaprate release date test is so we can show the date. // there are currently some issues. If the page is not released and the user doesn't have // access because of groups, this will show the not released data. That's misleading because // when the release date comes the user still won't be able to see it. Not sure if it's worth // creating a separate function that just checks the groups. It's easy to test hidden, so I do that. The idea is that // if it's both hidden and not released it makes sense to show hidden. // check two parts of isitemvisible where we want to give specific errors // potentially need time zone for setting release date if (!canSeeAll && currentPage.getReleaseDate() != null && currentPage.getReleaseDate().after(new Date()) && !currentPage.isHidden()) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, M_locale); TimeZone tz = timeService.getLocalTimeZone(); df.setTimeZone(tz); String releaseDate = df.format(currentPage.getReleaseDate()); String releaseMessage = messageLocator.getMessage("simplepage.not_yet_available_releasedate") .replace("{}", releaseDate); UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", releaseMessage); return; } // the only thing not already tested (or tested in release check below) in isItemVisible is groups. In theory // no one should have a URL to a page for which they aren't in the group, // so I'm not trying to give a better message than just hidden if (!canSeeAll && currentPage.isHidden() || !simplePageBean.isItemVisible(pageItem)) { UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.not_available_hidden")); return; } // I believe we've now checked all the args for permissions issues. All // other item and // page references are generated here based on the contents of the page // and items. // needed to process path arguments first, so refresh page goes the right page if (simplePageBean.getTopRefresh()) { UIOutput.make(tofill, "refresh"); return; // but there's no point doing anything more } // error from previous operation // consumes the message, so don't do it if refreshing List<String> errMessages = simplePageBean.errMessages(); if (errMessages != null) { UIOutput.make(tofill, "error-div"); for (String e : errMessages) { UIBranchContainer er = UIBranchContainer.make(tofill, "errors:"); UIOutput.make(er, "error-message", e); } } if (canEditPage) { // special instructor-only javascript setup. // but not if we're refreshing UIOutput.make(tofill, "instructoronly"); // Chome and IE will abort a page if some on it was input from // a previous submit. I.e. if an HTML editor was used. In theory they // only do this if part of it is Javascript, but in practice they do // it for images as well. The protection isn't worthwhile, since it only // protects the first time. Since it will reesult in a garbled page, // people will just refresh the page, and then they'll get the new // contents. The Chrome guys refuse to fix this so it just applies to Javascript httpServletResponse.setHeader("X-XSS-Protection", "0"); } if (currentPage == null || pageItem == null) { UIOutput.make(tofill, "error-div"); if (canEditPage) { UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.impossible1")); } else { UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.not_available")); } return; } // Set up customizable CSS ContentResource cssLink = simplePageBean.getCssForCurrentPage(); if (cssLink != null) { UIOutput.make(tofill, "customCSS").decorate(new UIFreeAttributeDecorator("href", cssLink.getUrl())); } // offer to go to saved page if this is the start of a session, in case // user has logged off and logged on again. // need to offer to go to previous page? even if a new session, no need // if we're already on that page if (lastPage != null && lastPage.pageId != currentPage.getPageId()) { UIOutput.make(tofill, "refreshAlert"); UIOutput.make(tofill, "refresh-message", messageLocator.getMessage("simplepage.last-visited")); // Should simply refresh GeneralViewParameters p = new GeneralViewParameters(VIEW_ID); p.setSendingPage(lastPage.pageId); p.setItemId(lastPage.itemId); // reset the path to the saved one p.setPath("log"); String name = lastPage.name; // Titles are set oddly by Student Content Pages SimplePage lastPageObj = simplePageToolDao.getPage(lastPage.pageId); if (lastPageObj.getOwner() != null) { name = lastPageObj.getTitle(); } UIInternalLink.make(tofill, "refresh-link", name, p); } // path is the breadcrumbs. Push, pop or reset depending upon path= // programmer documentation. String title; String ownerName = null; if (pageItem.getType() != SimplePageItem.STUDENT_CONTENT) { title = pageItem.getName(); } else { title = currentPage.getTitle(); if (!pageItem.isAnonymous() || canEditPage) { try { String owner = currentPage.getOwner(); String group = currentPage.getGroup(); if (group != null) ownerName = simplePageBean.getCurrentSite().getGroup(group).getTitle(); else ownerName = UserDirectoryService.getUser(owner).getDisplayName(); } catch (Exception ignore) { } ; if (ownerName != null && !ownerName.equals(title)) title += " (" + ownerName + ")"; } } String newPath = null; // If the path is "none", then we don't want to record this page as being viewed, or set a path if (!params.getPath().equals("none")) { newPath = simplePageBean.adjustPath(params.getPath(), currentPage.getPageId(), pageItem.getId(), title); simplePageBean.adjustBackPath(params.getBackPath(), currentPage.getPageId(), pageItem.getId(), pageItem.getName()); } // put out link to index of pages GeneralViewParameters showAll = new GeneralViewParameters(PagePickerProducer.VIEW_ID); showAll.setSource("summary"); UIInternalLink.make(tofill, "print-view", messageLocator.getMessage("simplepage.print_view"), showAll); UIInternalLink.make(tofill, "show-pages", messageLocator.getMessage("simplepage.showallpages"), showAll); if (canEditPage) { // show tool bar, but not if coming from grading pane if (!cameFromGradingPane) { createToolBar(tofill, currentPage, (pageItem.getType() == SimplePageItem.STUDENT_CONTENT)); } UIOutput.make(tofill, "title-descrip"); String label = null; if (pageItem.getType() == SimplePageItem.STUDENT_CONTENT) label = messageLocator.getMessage("simplepage.editTitle"); else label = messageLocator.getMessage("simplepage.title"); String descrip = null; if (pageItem.getType() == SimplePageItem.STUDENT_CONTENT) descrip = messageLocator.getMessage("simplepage.title-student-descrip"); else if (pageItem.getPageId() == 0) descrip = messageLocator.getMessage("simplepage.title-top-descrip"); else descrip = messageLocator.getMessage("simplepage.title-descrip"); UIOutput.make(tofill, "edit-title").decorate(new UIFreeAttributeDecorator("title", descrip)); UIOutput.make(tofill, "edit-title-text", label); UIOutput.make(tofill, "title-descrip-text", descrip); if (pageItem.getPageId() == 0 && currentPage.getOwner() == null) { // top level page // need dropdown UIOutput.make(tofill, "dropdown"); UIOutput.make(tofill, "moreDiv"); UIOutput.make(tofill, "new-page").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.new-page-tooltip"))); createToolBarLink(PermissionsHelperProducer.VIEW_ID, tofill, "permissions", "simplepage.permissions", currentPage, "simplepage.permissions.tooltip"); UIOutput.make(tofill, "import-cc").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.import_cc.tooltip"))); UIOutput.make(tofill, "export-cc").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.export_cc.tooltip"))); // Check to see if we have tools registered for external import List<Map<String, Object>> toolsFileItem = simplePageBean.getToolsFileItem(); if (toolsFileItem.size() > 0) { UIOutput.make(tofill, "show-lti-import"); UIForm ltiImport = UIForm.make(tofill, "lti-import-form"); makeCsrf(ltiImport, "csrf1"); GeneralViewParameters ltiParams = new GeneralViewParameters(); ltiParams.setSendingPage(currentPage.getPageId()); ltiParams.viewID = LtiFileItemProducer.VIEW_ID; UILink link = UIInternalLink.make(tofill, "lti-import-link", messageLocator.getMessage("simplepage.import_lti_button"), ltiParams); link.decorate(new UITooltipDecorator(messageLocator.getMessage("simplepage.fileitem.tooltip"))); } } // Checks to see that user can edit and that this is either a top level page, // or a top level student page (not a subpage to a student page) if (simplePageBean.getEditPrivs() == 0 && (pageItem.getPageId() == 0)) { UIOutput.make(tofill, "remove-li"); UIOutput.make(tofill, "remove-page").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.remove-page-tooltip"))); if (allowDeleteOrphans) { UIOutput.make(tofill, "delete-orphan-li"); UIForm orphan = UIForm.make(tofill, "delete-orphan-form"); makeCsrf(orphan, "csrf1"); UICommand.make(orphan, "delete-orphan", "#{simplePageBean.deleteOrphanPages}"); UIOutput.make(orphan, "delete-orphan-link").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.delete-orphan-pages-desc"))); } } else if (simplePageBean.getEditPrivs() == 0 && currentPage.getOwner() != null) { // getEditPrivs < 2 if we want to let the student delete. Currently we don't. There can be comments // from other students and the page can be shared SimpleStudentPage studentPage = simplePageToolDao.findStudentPage(currentPage.getTopParent()); if (studentPage != null && studentPage.getPageId() == currentPage.getPageId()) { UIOutput.make(tofill, "remove-student"); UIOutput.make(tofill, "remove-page-student").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.remove-student-page-explanation"))); } } UIOutput.make(tofill, "dialogDiv"); UIOutput.make(tofill, "siteid", simplePageBean.getCurrentSiteId()); UIOutput.make(tofill, "locale", M_locale.toString()); } else if (!canReadPage) { return; } else if (!canSeeAll) { // see if there are any unsatisfied prerequisites // if this isn't a top level page, this will check that the page above is // accessible. That matters because we check visible, available and release // only for this page but not for the containing page List<String> needed = simplePageBean.pagesNeeded(pageItem); if (needed.size() > 0) { // yes. error and abort if (pageItem.getPageId() != 0) { // not top level. This should only happen from a "next" // link. // at any rate, the best approach is to send the user back // to the calling page List<SimplePageBean.PathEntry> path = simplePageBean.getHierarchy(); SimplePageBean.PathEntry containingPage = null; if (path.size() > 1) { // page above this. this page is on the top containingPage = path.get(path.size() - 2); } if (containingPage != null) { // not a top level page, point // to containing page GeneralViewParameters view = new GeneralViewParameters(VIEW_ID); view.setSendingPage(containingPage.pageId); view.setItemId(containingPage.pageItemId); view.setPath(Integer.toString(path.size() - 2)); UIInternalLink.make(tofill, "redirect-link", containingPage.title, view); UIOutput.make(tofill, "redirect"); } else { UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.not_available")); } return; } // top level page where prereqs not satisified. Output list of // pages he needs to do first UIOutput.make(tofill, "pagetitle", currentPage.getTitle()); UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.has_prerequistes")); UIBranchContainer errorList = UIBranchContainer.make(tofill, "error-list:"); for (String errorItem : needed) { UIBranchContainer errorListItem = UIBranchContainer.make(errorList, "error-item:"); UIOutput.make(errorListItem, "error-item-text", errorItem); } return; } } ToolSession toolSession = SessionManager.getCurrentToolSession(); // this code is now for 11 only. helpurl is used in 9 and 10 to indicate neo portal // at this point only two code paths are intended to work. inline and iframe. // inline pushes stuff into the morpheus-generated header. iframe uses an extra line // the previous mode required us to try to duplicate the header generated by morpheus // this was too error-prone. String helpurl = null; /* (String)toolSession.getAttribute("sakai-portal:help-action"); */ String reseturl = null; /* (String)toolSession.getAttribute("sakai-portal:reset-action"); */ Placement placement = toolManager.getCurrentPlacement(); String toolId = placement.getToolId(); boolean inline = false; // inline includes iframes when morpheus is in effect if ("morpheus".equals(portalTemplates) && httpServletRequest.getRequestURI().startsWith("/portal/site/")) { inline = true; } String skinName = null; String skinRepo = null; String iconBase = null; UIComponent titlediv = UIOutput.make(tofill, "titlediv"); if (inline) titlediv.decorate(new UIFreeAttributeDecorator("style", "display:none")); // we need to do special CSS for old portal else if (helpurl == null) titlediv.decorate(new UIStyleDecorator("oldPortal")); if (helpurl != null || reseturl != null) { // these URLs are defined if we're in the neo portal // in that case we need our own help and reset icons. We want // to take them from the current skin, so find its prefix. // unfortunately the neoportal tacks neo- on front of the skin // name, so this is more complex than you might think. skinRepo = ServerConfigurationService.getString("skin.repo", "/library/skin"); iconBase = skinRepo + "/" + CSSUtils.adjustCssSkinFolder(null) + "/images"; UIVerbatim.make(tofill, "iconstyle", ICONSTYLE.replace("{}", iconBase)); } if (helpurl != null) { UILink.make(tofill, (pageItem.getPageId() == 0 ? "helpbutton" : "helpbutton2"), helpurl) .decorate(new UIFreeAttributeDecorator("onclick", "openWindow('" + helpurl + "', 'Help', 'resizeable=yes,toolbar=no,scrollbars=yes,menubar=yes,width=800,height=600'); return false")) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.help-button"))); if (!inline) UIOutput.make(tofill, (pageItem.getPageId() == 0 ? "helpimage" : "helpimage2")).decorate( new UIFreeAttributeDecorator("alt", messageLocator.getMessage("simplepage.help-button"))); UIOutput.make(tofill, (pageItem.getPageId() == 0 ? "helpnewwindow" : "helpnewwindow2"), messageLocator.getMessage("simplepage.opens-in-new")); UILink.make(tofill, "directurl") .decorate(new UIFreeAttributeDecorator("rel", "#Main" + Web.escapeJavascript(placement.getId()) + "_directurl")) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.direct-link"))); // if (inline) { UIOutput.make(tofill, "directurl-div").decorate(new UIFreeAttributeDecorator("id", "Main" + Web.escapeJavascript(placement.getId()) + "_directurl")); // in general 2.9 doesn't have the url shortener if (majorVersion >= 10) { UIOutput.make(tofill, "directurl-input") .decorate(new UIFreeAttributeDecorator("onclick", "toggleShortUrlOutput('" + myUrl() + "/portal/directtool/" + placement.getId() + "/', this, 'Main" + Web.escapeJavascript(placement.getId()) + "_urlholder');")); UIOutput.make(tofill, "directurl-shorten", messageLocator.getMessage("simplepage.short-url")); } UIOutput.make(tofill, "directurl-textarea", myUrl() + "/portal/directtool/" + placement.getId() + "/") .decorate(new UIFreeAttributeDecorator("class", "portlet title-tools Main" + Web.escapeJavascript(placement.getId()) + "_urlholder")); // } else UIOutput.make(tofill, "directimage").decorate( new UIFreeAttributeDecorator("alt", messageLocator.getMessage("simplepage.direct-link"))); } // morpheus does reset as part of title if (reseturl != null && !inline) { UILink.make(tofill, (pageItem.getPageId() == 0 ? "resetbutton" : "resetbutton2"), reseturl) .decorate(new UIFreeAttributeDecorator("onclick", "location.href='" + reseturl + "'; return false")) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.reset-button"))); UIOutput.make(tofill, (pageItem.getPageId() == 0 ? "resetimage" : "resetimage2")).decorate( new UIFreeAttributeDecorator("alt", messageLocator.getMessage("simplepage.reset-button"))); } // note page accessed. the code checks to see whether all the required // items on it have been finished, and if so marks it complete, else just updates // access date save the path because if user goes to it later we want to restore the // breadcrumbs if (newPath != null) { if (pageItem.getType() != SimplePageItem.STUDENT_CONTENT) { simplePageBean.track(pageItem.getId(), newPath); } else { simplePageBean.track(pageItem.getId(), newPath, currentPage.getPageId()); } } if (currentPage.getOwner() != null && simplePageBean.getEditPrivs() == 0) { SimpleStudentPage student = simplePageToolDao.findStudentPageByPageId(currentPage.getPageId()); // Make sure this is a top level student page if (student != null && pageItem.getGradebookId() != null) { UIOutput.make(tofill, "gradingSpan"); UIOutput.make(tofill, "commentsUUID", String.valueOf(student.getId())); UIOutput.make(tofill, "commentPoints", String.valueOf((student.getPoints() != null ? student.getPoints() : ""))); UIOutput pointsBox = UIOutput.make(tofill, "studentPointsBox"); UIOutput.make(tofill, "topmaxpoints", String .valueOf((pageItem.getGradebookPoints() != null ? pageItem.getGradebookPoints() : ""))); if (ownerName != null) pointsBox.decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.grade-for-student").replace("{}", ownerName))); List<SimpleStudentPage> studentPages = simplePageToolDao.findStudentPages(student.getItemId()); Collections.sort(studentPages, new Comparator<SimpleStudentPage>() { public int compare(SimpleStudentPage o1, SimpleStudentPage o2) { String title1 = o1.getTitle(); if (title1 == null) title1 = ""; String title2 = o2.getTitle(); if (title2 == null) title2 = ""; return title1.compareTo(title2); } }); for (int in = 0; in < studentPages.size(); in++) { if (studentPages.get(in).isDeleted()) { studentPages.remove(in); } } int i = -1; for (int in = 0; in < studentPages.size(); in++) { if (student.getId() == studentPages.get(in).getId()) { i = in; break; } } if (i > 0) { GeneralViewParameters eParams = new GeneralViewParameters(ShowPageProducer.VIEW_ID, studentPages.get(i - 1).getPageId()); eParams.setItemId(studentPages.get(i - 1).getItemId()); eParams.setPath("next"); UIInternalLink.make(tofill, "gradingBack", eParams); } if (i < studentPages.size() - 1) { GeneralViewParameters eParams = new GeneralViewParameters(ShowPageProducer.VIEW_ID, studentPages.get(i + 1).getPageId()); eParams.setItemId(studentPages.get(i + 1).getItemId()); eParams.setPath("next"); UIInternalLink.make(tofill, "gradingForward", eParams); } printGradingForm(tofill); } } // breadcrumbs if (pageItem.getPageId() != 0) { // Not top-level, so we have to show breadcrumbs List<SimplePageBean.PathEntry> breadcrumbs = simplePageBean.getHierarchy(); int index = 0; if (breadcrumbs.size() > 1 || reseturl != null || helpurl != null) { UIOutput.make(tofill, "crumbdiv"); if (breadcrumbs.size() > 1) for (SimplePageBean.PathEntry e : breadcrumbs) { // don't show current page. We already have a title. This // was too much UIBranchContainer crumb = UIBranchContainer.make(tofill, "crumb:"); GeneralViewParameters view = new GeneralViewParameters(VIEW_ID); view.setSendingPage(e.pageId); view.setItemId(e.pageItemId); view.setPath(Integer.toString(index)); UIComponent link = null; if (index < breadcrumbs.size() - 1) { // Not the last item link = UIInternalLink.make(crumb, "crumb-link", e.title, view); UIOutput.make(crumb, "crumb-follow", " > "); } else { UIOutput.make(crumb, "crumb-follow", e.title).decorate(new UIStyleDecorator("bold")); } index++; } else { UIBranchContainer crumb = UIBranchContainer.make(tofill, "crumb:"); UILink.make(crumb, "crum-link", currentPage.getTitle(), reseturl); } } else { if (reseturl != null) { UIOutput.make(tofill, "pagetitletext", currentPage.getTitle()); } else if (!inline) { UIOutput.make(tofill, "pagetitle", currentPage.getTitle()); } } } else { if (reseturl != null) { UILink.make(tofill, "pagetitlelink", reseturl); UIOutput.make(tofill, "pagetitletext", currentPage.getTitle()); } else if (!inline) { UIOutput.make(tofill, "pagetitle", currentPage.getTitle()); } } // see if there's a next item in sequence. simplePageBean.addPrevLink(tofill, pageItem); simplePageBean.addNextLink(tofill, pageItem); // swfObject is not currently used boolean shownSwfObject = false; long newItemId = -1L; String newItemStr = (String) toolSession.getAttribute("lessonbuilder.newitem"); if (newItemStr != null) { toolSession.removeAttribute("lessonbuilder.newitem"); try { newItemId = Long.parseLong(newItemStr); } catch (Exception e) { } } // items to show List<SimplePageItem> itemList = (List<SimplePageItem>) simplePageBean .getItemsOnPage(currentPage.getPageId()); // Move all items with sequence <= 0 to the end of the list. // Count is necessary to guarantee we don't infinite loop over a // list that only has items with sequence <= 0. // Becauses sequence number is < 0, these start out at the beginning int count = 1; while (itemList.size() > count && itemList.get(0).getSequence() <= 0) { itemList.add(itemList.remove(0)); count++; } // Make sure we only add the comments javascript file once, // even if there are multiple comments tools on the page. boolean addedCommentsScript = false; int commentsCount = 0; // Find the most recent comment on the page by current user long postedCommentId = -1; if (params.postedComment) { postedCommentId = findMostRecentComment(); } boolean showDownloads = (simplePageBean.getCurrentSite().getProperties() .getProperty("lessonbuilder-nodownloadlinks") == null); // // // MAIN list of items // // produce the main table // Is anything visible? // Note that we don't need to check whether any item is available, since the first visible // item is always available. boolean anyItemVisible = false; if (itemList.size() > 0) { UIBranchContainer container = UIBranchContainer.make(tofill, "itemContainer:"); boolean showRefresh = false; boolean fisrt = false; int textboxcount = 1; int cols = 0; int colnum = 0; UIBranchContainer sectionContainer = null; UIBranchContainer columnContainer = null; UIBranchContainer tableContainer = null; boolean first = true; for (SimplePageItem i : itemList) { // break is not a normal item. handle it first // this will work whether first item is break or not. Might be a section // break or a normal item if (first || i.getType() == SimplePageItem.BREAK) { boolean sectionbreak = false; if (first || "section".equals(i.getFormat())) { sectionContainer = UIBranchContainer.make(container, "section:"); cols = colCount(itemList, i.getId()); sectionbreak = true; colnum = 0; } else if ("colunn".equals(i.getFormat())) colnum++; columnContainer = UIBranchContainer.make(sectionContainer, "column:"); tableContainer = UIBranchContainer.make(columnContainer, "itemTable:"); Integer width = new Integer( i.getAttribute("colwidth") == null ? "1" : i.getAttribute("colwidth")); Integer split = new Integer( i.getAttribute("colsplit") == null ? "1" : i.getAttribute("colsplit")); colnum += width; // number after this column String color = i.getAttribute("colcolor"); columnContainer.decorate(new UIStyleDecorator( "cols" + cols + (colnum == cols ? " lastcol" : "") + (width > 1 ? " double" : "") + (split > 1 ? " split" : "") + (color == null ? "" : " col" + color))); UIComponent delIcon = UIOutput.make(columnContainer, "section-td"); if (first) delIcon.decorate(new UIFreeAttributeDecorator("style", "display:none")); UIOutput.make(columnContainer, "break-msg", messageLocator .getMessage(sectionbreak ? "simplepage.break-here" : "simplepage.break-column-here")); UIOutput.make(columnContainer, "section2"); UIOutput.make(columnContainer, "section3").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.columnopen"))); UIOutput.make(columnContainer, "addbottom"); UIOutput.make(columnContainer, "addbottom2").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.add-item-column"))); UILink link = UILink.make(columnContainer, "section-del-link", (String) null, "/" + i.getId()); link.decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.join-items"))); link.decorate(new UIStyleDecorator(sectionbreak ? "section-merge-link" : "column-merge-link")); UIBranchContainer tableRow = UIBranchContainer.make(tableContainer, "item:"); tableRow.decorate(new UIFreeAttributeDecorator("class", "break" + i.getFormat())); first = false; if (i.getType() == SimplePageItem.BREAK) continue; // for first item, if wasn't break, process it } // listitem is mostly historical. it uses some shared HTML, but // if I were // doing it from scratch I wouldn't make this distinction. At // the moment it's // everything that isn't inline. boolean listItem = !(i.getType() == SimplePageItem.TEXT || i.getType() == SimplePageItem.MULTIMEDIA || i.getType() == SimplePageItem.COMMENTS || i.getType() == SimplePageItem.STUDENT_CONTENT || i.getType() == SimplePageItem.QUESTION || i.getType() == SimplePageItem.PEEREVAL || i.getType() == SimplePageItem.BREAK); // (i.getType() == SimplePageItem.PAGE && // "button".equals(i.getFormat()))) if (!simplePageBean.isItemVisible(i, currentPage)) { continue; } // break isn't a real item. probably don't want to count it if (i.getType() != SimplePageItem.BREAK) anyItemVisible = true; UIBranchContainer tableRow = UIBranchContainer.make(tableContainer, "item:"); // set class name showing what the type is, so people can do funky CSS String itemClassName = null; switch (i.getType()) { case SimplePageItem.RESOURCE: itemClassName = "resourceType"; break; case SimplePageItem.PAGE: itemClassName = "pageType"; break; case SimplePageItem.ASSIGNMENT: itemClassName = "assignmentType"; break; case SimplePageItem.ASSESSMENT: itemClassName = "assessmentType"; break; case SimplePageItem.TEXT: itemClassName = "textType"; break; case SimplePageItem.URL: itemClassName = "urlType"; break; case SimplePageItem.MULTIMEDIA: itemClassName = "multimediaType"; break; case SimplePageItem.FORUM: itemClassName = "forumType"; break; case SimplePageItem.COMMENTS: itemClassName = "commentsType"; break; case SimplePageItem.STUDENT_CONTENT: itemClassName = "studentContentType"; break; case SimplePageItem.QUESTION: itemClassName = "question"; break; case SimplePageItem.BLTI: itemClassName = "bltiType"; break; case SimplePageItem.PEEREVAL: itemClassName = "peereval"; break; } if (listItem) { itemClassName = itemClassName + " listType"; } if (canEditPage) { itemClassName = itemClassName + " canEdit"; } if (i.getId() == newItemId) itemClassName = itemClassName + " newItem"; tableRow.decorate(new UIFreeAttributeDecorator("class", itemClassName)); if (canEditPage) UIOutput.make(tableRow, "itemid", String.valueOf(i.getId())); // you really need the HTML file open at the same time to make // sense of the following code if (listItem) { // Not an HTML Text, Element or Multimedia // Element if (canEditPage) { UIOutput.make(tableRow, "current-item-id2", String.valueOf(i.getId())); } // users can declare a page item to be navigational. If so // we display // it to the left of the normal list items, and use a // button. This is // used for pages that are "next" pages, i.e. they replace // this page // rather than creating a new level in the breadcrumbs. // Since they can't // be required, they don't need the status image, which is // good because // they're displayed with colspan=2, so there's no space for // the image. boolean navButton = "button".equals(i.getFormat()) && !i.isRequired(); boolean notDone = false; Status status = Status.NOT_REQUIRED; if (!navButton) { status = handleStatusImage(tableRow, i); if (status == Status.REQUIRED) { notDone = true; } } boolean isInline = (i.getType() == SimplePageItem.BLTI && "inline".equals(i.getFormat())); UIOutput linktd = UIOutput.make(tableRow, "item-td"); UIOutput contentCol = UIOutput.make(tableRow, "contentCol"); // BLTI seems to require explicit specificaiton for column width. Otherwise // we get 300 px wide. Don't know why. Doesn't happen to other iframes if (isInline) contentCol.decorate(new UIFreeAttributeDecorator("style", "width:100%")); UIBranchContainer linkdiv = null; if (!isInline) { linkdiv = UIBranchContainer.make(tableRow, "link-div:"); UIOutput itemicon = UIOutput.make(linkdiv, "item-icon"); switch (i.getType()) { case SimplePageItem.FORUM: itemicon.decorate(new UIStyleDecorator("fa-comments")); break; case SimplePageItem.ASSIGNMENT: itemicon.decorate(new UIStyleDecorator("fa-tasks")); break; case SimplePageItem.ASSESSMENT: itemicon.decorate(new UIStyleDecorator("fa-puzzle-piece")); break; case SimplePageItem.BLTI: itemicon.decorate(new UIStyleDecorator("fa-globe")); break; case SimplePageItem.PAGE: itemicon.decorate(new UIStyleDecorator("fa-folder-open-o")); break; case SimplePageItem.RESOURCE: String mimeType = i.getHtml(); if ("application/octet-stream".equals(mimeType)) { // OS X reports octet stream for things like MS Excel documents. // Force a mimeType lookup so we get a decent icon. mimeType = null; } if (mimeType == null || mimeType.equals("")) { String s = i.getSakaiId(); int j = s.lastIndexOf("."); if (j >= 0) s = s.substring(j + 1); mimeType = ContentTypeImageService.getContentType(s); // System.out.println("type " + s + ">" + mimeType); } String src = null; //if (!useSakaiIcons) src = imageToMimeMap.get(mimeType); if (src == null) { src = "fa-file-o"; //String image = ContentTypeImageService.getContentTypeImage(mimeType); // if (image != null) // src = "/library/image/" + image; } if (src != null) { itemicon.decorate(new UIStyleDecorator(src)); } break; } } UIOutput descriptiondiv = null; // refresh isn't actually used anymore. We've changed the // way things are // done so the user never has to request a refresh. // FYI: this actually puts in an IFRAME for inline BLTI items showRefresh = !makeLink(tableRow, "link", i, canSeeAll, currentPage, notDone, status) || showRefresh; UILink.make(tableRow, "copylink", i.getName(), "http://lessonbuilder.sakaiproject.org/" + i.getId() + "/") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.copylink2").replace("{}", i.getName()))); // dummy is used when an assignment, quiz, or forum item is // copied // from another site. The way the copy code works, our // import code // doesn't have access to the necessary info to use the item // from the // new site. So we add a dummy, which generates an // explanation that the // author is going to have to choose the item from the // current site if (i.getSakaiId().equals(SimplePageItem.DUMMY)) { String code = null; switch (i.getType()) { case SimplePageItem.ASSIGNMENT: code = "simplepage.copied.assignment"; break; case SimplePageItem.ASSESSMENT: code = "simplepage.copied.assessment"; break; case SimplePageItem.FORUM: code = "simplepage.copied.forum"; break; } descriptiondiv = UIOutput.make(tableRow, "description", messageLocator.getMessage(code)); } else { descriptiondiv = UIOutput.make(tableRow, "description", i.getDescription()); } if (isInline) descriptiondiv.decorate(new UIFreeAttributeDecorator("style", "margin-top: 4px")); if (!isInline) { // nav button gets float left so any description goes to its // right. Otherwise the // description block will display underneath if ("button".equals(i.getFormat())) { linkdiv.decorate(new UIFreeAttributeDecorator("style", "float:none")); } // for accessibility if (navButton) { linkdiv.decorate(new UIFreeAttributeDecorator("role", "navigation")); } } // note that a lot of the info here is used by the // javascript that prepares // the jQuery dialogs String itemGroupString = null; boolean entityDeleted = false; boolean notPublished = false; if (canEditPage) { UIOutput.make(tableRow, "edit-td"); UILink.make(tableRow, "edit-link", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator .getMessage("simplepage.edit-title.generic").replace("{}", i.getName()))); // the following information is displayed using <INPUT // type=hidden ... // it contains information needed to populate the "edit" // popup dialog UIOutput.make(tableRow, "prerequisite-info", String.valueOf(i.isPrerequisite())); if (i.getType() == SimplePageItem.ASSIGNMENT) { // the type indicates whether scoring is letter // grade, number, etc. // the javascript needs this to present the right // choices to the user // types 6 and 8 aren't legal scoring types, so they // are used as // markers for quiz or forum. I ran out of numbers // and started using // text for things that aren't scoring types. That's // better anyway int type = 4; LessonEntity assignment = null; if (!i.getSakaiId().equals(SimplePageItem.DUMMY)) { assignment = assignmentEntity.getEntity(i.getSakaiId(), simplePageBean); if (assignment != null) { type = assignment.getTypeOfGrade(); String editUrl = assignment.editItemUrl(simplePageBean); if (editUrl != null) { UIOutput.make(tableRow, "edit-url", editUrl); } itemGroupString = simplePageBean.getItemGroupString(i, assignment, true); UIOutput.make(tableRow, "item-groups", itemGroupString); if (!assignment.objectExists()) entityDeleted = true; else if (assignment.notPublished()) notPublished = true; } } UIOutput.make(tableRow, "type", String.valueOf(type)); String requirement = String.valueOf(i.getSubrequirement()); if ((type == SimplePageItem.PAGE || type == SimplePageItem.ASSIGNMENT) && i.getSubrequirement()) { requirement = i.getRequirementText(); } UIOutput.make(tableRow, "requirement-text", requirement); } else if (i.getType() == SimplePageItem.ASSESSMENT) { UIOutput.make(tableRow, "type", "6"); // Not used by // assignments, // so it is // safe to dedicate to assessments UIOutput.make(tableRow, "requirement-text", (i.getSubrequirement() ? i.getRequirementText() : "false")); LessonEntity quiz = quizEntity.getEntity(i.getSakaiId(), simplePageBean); if (quiz != null) { String editUrl = quiz.editItemUrl(simplePageBean); if (editUrl != null) { UIOutput.make(tableRow, "edit-url", editUrl); } editUrl = quiz.editItemSettingsUrl(simplePageBean); if (editUrl != null) { UIOutput.make(tableRow, "edit-settings-url", editUrl); } itemGroupString = simplePageBean.getItemGroupString(i, quiz, true); UIOutput.make(tableRow, "item-groups", itemGroupString); if (!quiz.objectExists()) entityDeleted = true; } else notPublished = quizEntity.notPublished(i.getSakaiId()); } else if (i.getType() == SimplePageItem.BLTI) { UIOutput.make(tableRow, "type", "b"); LessonEntity blti = (bltiEntity == null ? null : bltiEntity.getEntity(i.getSakaiId())); if (blti != null) { String editUrl = blti.editItemUrl(simplePageBean); if (editUrl != null) UIOutput.make(tableRow, "edit-url", editUrl); UIOutput.make(tableRow, "item-format", i.getFormat()); if (i.getHeight() != null) UIOutput.make(tableRow, "item-height", i.getHeight()); itemGroupString = simplePageBean.getItemGroupString(i, null, true); UIOutput.make(tableRow, "item-groups", itemGroupString); if (!blti.objectExists()) entityDeleted = true; else if (blti.notPublished()) notPublished = true; } } else if (i.getType() == SimplePageItem.FORUM) { UIOutput.make(tableRow, "extra-info"); UIOutput.make(tableRow, "type", "8"); LessonEntity forum = forumEntity.getEntity(i.getSakaiId()); if (forum != null) { String editUrl = forum.editItemUrl(simplePageBean); if (editUrl != null) { UIOutput.make(tableRow, "edit-url", editUrl); } itemGroupString = simplePageBean.getItemGroupString(i, forum, true); UIOutput.make(tableRow, "item-groups", itemGroupString); if (!forum.objectExists()) entityDeleted = true; else if (forum.notPublished()) notPublished = true; } } else if (i.getType() == SimplePageItem.PAGE) { UIOutput.make(tableRow, "type", "page"); UIOutput.make(tableRow, "page-next", Boolean.toString(i.getNextPage())); UIOutput.make(tableRow, "page-button", Boolean.toString("button".equals(i.getFormat()))); itemGroupString = simplePageBean.getItemGroupString(i, null, true); UIOutput.make(tableRow, "item-groups", itemGroupString); } else if (i.getType() == SimplePageItem.RESOURCE) { try { itemGroupString = simplePageBean.getItemGroupStringOrErr(i, null, true); } catch (IdUnusedException e) { itemGroupString = ""; entityDeleted = true; } if (simplePageBean.getInherited()) UIOutput.make(tableRow, "item-groups", "--inherited--"); else UIOutput.make(tableRow, "item-groups", itemGroupString); UIOutput.make(tableRow, "item-samewindow", Boolean.toString(i.isSameWindow())); UIVerbatim.make(tableRow, "item-path", getItemPath(i)); } } // end of canEditPage if (canSeeAll) { // haven't set up itemgroupstring yet if (!canEditPage) { if (!i.getSakaiId().equals(SimplePageItem.DUMMY)) { LessonEntity lessonEntity = null; switch (i.getType()) { case SimplePageItem.ASSIGNMENT: lessonEntity = assignmentEntity.getEntity(i.getSakaiId(), simplePageBean); if (lessonEntity != null) itemGroupString = simplePageBean.getItemGroupString(i, lessonEntity, true); if (!lessonEntity.objectExists()) entityDeleted = true; else if (lessonEntity.notPublished()) notPublished = true; break; case SimplePageItem.ASSESSMENT: lessonEntity = quizEntity.getEntity(i.getSakaiId(), simplePageBean); if (lessonEntity != null) itemGroupString = simplePageBean.getItemGroupString(i, lessonEntity, true); else notPublished = quizEntity.notPublished(i.getSakaiId()); if (!lessonEntity.objectExists()) entityDeleted = true; break; case SimplePageItem.FORUM: lessonEntity = forumEntity.getEntity(i.getSakaiId()); if (lessonEntity != null) itemGroupString = simplePageBean.getItemGroupString(i, lessonEntity, true); if (!lessonEntity.objectExists()) entityDeleted = true; else if (lessonEntity.notPublished()) notPublished = true; break; case SimplePageItem.BLTI: if (bltiEntity != null) lessonEntity = bltiEntity.getEntity(i.getSakaiId()); if (lessonEntity != null) itemGroupString = simplePageBean.getItemGroupString(i, null, true); if (!lessonEntity.objectExists()) entityDeleted = true; else if (lessonEntity.notPublished()) notPublished = true; break; case SimplePageItem.PAGE: itemGroupString = simplePageBean.getItemGroupString(i, null, true); break; case SimplePageItem.RESOURCE: try { itemGroupString = simplePageBean.getItemGroupStringOrErr(i, null, true); } catch (IdUnusedException e) { itemGroupString = ""; entityDeleted = true; } break; } } } String releaseString = simplePageBean.getReleaseString(i); if (itemGroupString != null || releaseString != null || entityDeleted || notPublished) { if (itemGroupString != null) itemGroupString = simplePageBean.getItemGroupTitles(itemGroupString, i); if (itemGroupString != null) { itemGroupString = " [" + itemGroupString + "]"; if (releaseString != null) itemGroupString = " " + releaseString + itemGroupString; } else if (releaseString != null) itemGroupString = " " + releaseString; if (notPublished) { if (itemGroupString != null) itemGroupString = itemGroupString + " " + messageLocator.getMessage("simplepage.not-published"); else itemGroupString = messageLocator.getMessage("simplepage.not-published"); } if (entityDeleted) { if (itemGroupString != null) itemGroupString = itemGroupString + " " + messageLocator.getMessage("simplepage.deleted-entity"); else itemGroupString = messageLocator.getMessage("simplepage.deleted-entity"); } if (itemGroupString != null) UIOutput.make(tableRow, (isInline ? "item-group-titles-div" : "item-group-titles"), itemGroupString); } } // end of canSeeAll // the following are for the inline item types. Multimedia // is the most complex because // it can be IMG, IFRAME, or OBJECT, and Youtube is treated // separately } else if (i.getType() == SimplePageItem.MULTIMEDIA) { // This code should be read together with the code in SimplePageBean // that sets up this data, method addMultimedia. Most display is set // up here, but note that show-page.js invokes the jquery oembed on all // <A> items with class="oembed". // historically this code was to display files ,and urls leading to things // like MP4. as backup if we couldn't figure out what to do we'd put something // in an iframe. The one exception is youtube, which we supposed explicitly. // However we now support several ways to embed content. We use the // multimediaDisplayType code to indicate which. The codes are // 1 -- embed code, 2 -- av type, 3 -- oembed, 4 -- iframe // 2 is the original code: MP4, image, and as a special case youtube urls // since we have old entries with no type code, and that behave the same as // 2, we start by converting 2 to null. // then the logic is // if type == null & youtube, do youtube // if type == null & image, do iamge // if type == null & not HTML do MP4 or other player for file // final fallthrough to handel the new types, with IFRAME if all else fails // the old code creates ojbects in ContentHosting for both files and URLs. // The new code saves the embed code or URL itself as an atteibute of the item // If I were doing it again, I wouldn't create the ContebtHosting item // Note that IFRAME is only used for something where the far end claims the MIME // type is HTML. For weird stuff like MS Word files I use the file display code, which // will end up producing <OBJECT>. // the reason this code is complex is that we try to choose // the best // HTML for displaying the particular type of object. We've // added complexities // over time as we get more experience with different // object types and browsers. String itemGroupString = null; String itemGroupTitles = null; boolean entityDeleted = false; // new format explicit display indication String mmDisplayType = i.getAttribute("multimediaDisplayType"); // 2 is the generic "use old display" so treat it as null if ("".equals(mmDisplayType) || "2".equals(mmDisplayType)) mmDisplayType = null; if (canSeeAll) { try { itemGroupString = simplePageBean.getItemGroupStringOrErr(i, null, true); } catch (IdUnusedException e) { itemGroupString = ""; entityDeleted = true; } itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i); if (entityDeleted) { if (itemGroupTitles != null) itemGroupTitles = itemGroupTitles + " " + messageLocator.getMessage("simplepage.deleted-entity"); else itemGroupTitles = messageLocator.getMessage("simplepage.deleted-entity"); } if (itemGroupTitles != null) { itemGroupTitles = "[" + itemGroupTitles + "]"; } UIOutput.make(tableRow, "item-groups", itemGroupString); } else if (entityDeleted) continue; if (!"1".equals(mmDisplayType) && !"3".equals(mmDisplayType)) UIVerbatim.make(tableRow, "item-path", getItemPath(i)); // the reason this code is complex is that we try to choose // the best // HTML for displaying the particular type of object. We've // added complexities // over time as we get more experience with different // object types and browsers. StringTokenizer token = new StringTokenizer(i.getSakaiId(), "."); String extension = ""; while (token.hasMoreTokens()) { extension = token.nextToken().toLowerCase(); } // the extension is almost never used. Normally we have // the MIME type and use it. Extension is used only if // for some reason we don't have the MIME type UIComponent item; String youtubeKey; Length width = null; if (i.getWidth() != null) { width = new Length(i.getWidth()); } Length height = null; if (i.getHeight() != null) { height = new Length(i.getHeight()); } // Get the MIME type. For multimedia types is should be in // the html field. // The old code saved the URL there. So if it looks like a // URL ignore it. String mimeType = i.getHtml(); if (mimeType != null && (mimeType.startsWith("http") || mimeType.equals(""))) { mimeType = null; } // here goes. dispatch on the type and produce the right tag // type, // followed by the hidden INPUT tags with information for the // edit dialog if (mmDisplayType == null && simplePageBean.isImageType(i)) { if (canSeeAll || simplePageBean.isItemAvailable(i)) { UIOutput.make(tableRow, "imageSpan"); if (itemGroupString != null) { UIOutput.make(tableRow, "item-group-titles3", itemGroupTitles); UIOutput.make(tableRow, "item-groups3", itemGroupString); } String imageName = i.getAlt(); if (imageName == null || imageName.equals("")) { imageName = abbrevUrl(i.getURL()); } item = UIOutput.make(tableRow, "image") .decorate(new UIFreeAttributeDecorator("src", i.getItemURL(simplePageBean.getCurrentSiteId(), currentPage.getOwner()))) .decorate(new UIFreeAttributeDecorator("alt", imageName)); if (lengthOk(width)) { item.decorate(new UIFreeAttributeDecorator("width", width.getOld())); } if (lengthOk(height)) { item.decorate(new UIFreeAttributeDecorator("height", height.getOld())); } } else { UIComponent notAvailableText = UIOutput.make(tableRow, "notAvailableText", messageLocator.getMessage("simplepage.multimediaItemUnavailable")); // Grey it out notAvailableText.decorate(new UIFreeAttributeDecorator("class", "disabled-text-item")); } // stuff for the jquery dialog if (canEditPage) { UIOutput.make(tableRow, "imageHeight", getOrig(height)); UIOutput.make(tableRow, "imageWidth", getOrig(width)); UIOutput.make(tableRow, "mimetype2", mimeType); UIOutput.make(tableRow, "current-item-id4", Long.toString(i.getId())); UIOutput.make(tableRow, "item-prereq3", String.valueOf(i.isPrerequisite())); UIVerbatim.make(tableRow, "item-path3", getItemPath(i)); UIOutput.make(tableRow, "editimage-td"); UILink.make(tableRow, "image-edit", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.url").replace("{}", abbrevUrl(i.getURL())))); } UIOutput.make(tableRow, "description2", i.getDescription()); } else if (mmDisplayType == null && (youtubeKey = simplePageBean.getYoutubeKey(i)) != null) { String youtubeUrl = SimplePageBean.getYoutubeUrlFromKey(youtubeKey); if (canSeeAll || simplePageBean.isItemAvailable(i)) { UIOutput.make(tableRow, "youtubeSpan"); if (itemGroupString != null) { UIOutput.make(tableRow, "item-group-titles4", itemGroupTitles); UIOutput.make(tableRow, "item-groups4", itemGroupString); } // if width is blank or 100% scale the height if (width != null && height != null && !height.number.equals("")) { if (width.number.equals("") && width.unit.equals("") || width.number.equals("100") && width.unit.equals("%")) { int h = Integer.parseInt(height.number); if (h > 0) { width.number = Integer.toString((int) Math.round(h * 1.641025641)); width.unit = height.unit; } } } // <object style="height: 390px; width: 640px"><param // name="movie" // value="http://www.youtube.com/v/AKIC7OQqBrA?version=3"><param // name="allowFullScreen" value="true"><param // name="allowScriptAccess" value="always"><embed // src="http://www.youtube.com/v/AKIC7OQqBrA?version=3" // type="application/x-shockwave-flash" // allowfullscreen="true" allowScriptAccess="always" // width="640" height="390"></object> item = UIOutput.make(tableRow, "youtubeIFrame"); // youtube seems ok with length and width if (lengthOk(height)) { item.decorate(new UIFreeAttributeDecorator("height", height.getOld())); } if (lengthOk(width)) { item.decorate(new UIFreeAttributeDecorator("width", width.getOld())); } item.decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.youtube_player"))); item.decorate(new UIFreeAttributeDecorator("src", youtubeUrl)); } else { UIComponent notAvailableText = UIOutput.make(tableRow, "notAvailableText", messageLocator.getMessage("simplepage.multimediaItemUnavailable")); // Grey it out notAvailableText.decorate(new UIFreeAttributeDecorator("class", "disabled-text-item")); } if (canEditPage) { UIOutput.make(tableRow, "youtubeId", String.valueOf(i.getId())); UIOutput.make(tableRow, "currentYoutubeURL", youtubeUrl); UIOutput.make(tableRow, "currentYoutubeHeight", getOrig(height)); UIOutput.make(tableRow, "currentYoutubeWidth", getOrig(width)); UIOutput.make(tableRow, "current-item-id5", Long.toString(i.getId())); UIOutput.make(tableRow, "item-prereq4", String.valueOf(i.isPrerequisite())); UIVerbatim.make(tableRow, "item-path4", getItemPath(i)); UIOutput.make(tableRow, "youtube-td"); UILink.make(tableRow, "youtube-edit", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.youtube"))); } UIOutput.make(tableRow, "description4", i.getDescription()); // as of Oct 28, 2010, we store the mime type. mimeType // null is an old entry. // For that use the old approach of checking the // extension. // Otherwise we want to use iframes for HTML and OBJECT // for everything else // We need the iframes because IE up through 8 doesn't // reliably display // HTML with OBJECT. Experiments show that everything // else works with OBJECT // for most browsers. Unfortunately IE, even IE 9, // doesn't reliably call the // right player with OBJECT. EMBED works. But it's not // as nice because you can't // nest error recovery code. So we use OBJECT for // everything except IE, where we // use EMBED. OBJECT does work with Flash. // application/xhtml+xml is XHTML. } else if (mmDisplayType == null && ((mimeType != null && !mimeType.equals("text/html") && !mimeType.equals("application/xhtml+xml")) || // ((mimeType != null && (mimeType.startsWith("audio/") || mimeType.startsWith("video/"))) || (mimeType == null && !(Arrays.binarySearch(htmlTypes, extension) >= 0)))) { // except where explicit display is set, // this code is used for everything that isn't an image, // Youtube, or HTML // This could be audio, video, flash, or something random like MS word. // Random stuff will turn into an object. // HTML is done with an IFRAME in the next "if" case // The explicit display types are handled there as well // in theory the things that fall through to iframe are // html and random stuff without a defined mime type // random stuff with mime type is displayed with object if (mimeType == null) { mimeType = ""; } String oMimeType = mimeType; // in case we change it for // FLV or others if (itemGroupString != null) { UIOutput.make(tableRow, "item-group-titles5", itemGroupTitles); UIOutput.make(tableRow, "item-groups5", itemGroupString); } UIOutput.make(tableRow, "movieSpan"); if (canSeeAll || simplePageBean.isItemAvailable(i)) { UIComponent item2; String movieUrl = i.getItemURL(simplePageBean.getCurrentSiteId(), currentPage.getOwner()); // movieUrl = "https://heidelberg.rutgers.edu" + movieUrl; // Safari doens't always pass cookies to plugins, so we have to pass the arg // this requires session.parameter.allow=true in sakai.properties // don't pass the arg unless that is set, since the whole point of defaulting // off is to not expose the session id String sessionParameter = getSessionParameter(movieUrl); if (sessionParameter != null) movieUrl = movieUrl + "?lb.session=" + sessionParameter; UIComponent movieLink = UIOutput.make(tableRow, "movie-link-div"); if (showDownloads) UILink.make(tableRow, "movie-link-link", messageLocator.getMessage("simplepage.download_file"), movieUrl); // if (allowSessionId) // movieUrl = movieUrl + "?sakai.session=" + SessionManager.getCurrentSession().getId(); boolean useFlvPlayer = false; // isMp4 means we try the flash player (if not HTML5) // we also try the flash player for FLV but for mp4 we do an // additional backup if flash fails, but that doesn't make sense for FLV boolean isMp4 = Arrays.binarySearch(mp4Types, mimeType) >= 0; boolean isHtml5 = Arrays.binarySearch(html5Types, mimeType) >= 0; // wrap whatever stuff we decide to put out in HTML5 if appropriate // javascript is used to do the wrapping, because RSF can't really handle this if (isHtml5) { // flag for javascript boolean isAudio = mimeType.startsWith("audio/"); UIComponent h5video = UIOutput.make(tableRow, (isAudio ? "h5audio" : "h5video")); UIComponent h5source = UIOutput.make(tableRow, (isAudio ? "h5asource" : "h5source")); if (lengthOk(height) && height.getOld().indexOf("%") < 0) h5video.decorate(new UIFreeAttributeDecorator("height", height.getOld())); if (lengthOk(width) && width.getOld().indexOf("%") < 0) h5video.decorate(new UIFreeAttributeDecorator("width", width.getOld())); h5source.decorate(new UIFreeAttributeDecorator("src", movieUrl)) .decorate(new UIFreeAttributeDecorator("type", mimeType)); String caption = i.getAttribute("captionfile"); if (!isAudio && caption != null && caption.length() > 0) { movieLink.decorate( new UIFreeAttributeDecorator("class", "has-caption allow-caption")); String captionUrl = "/access/lessonbuilder/item/" + i.getId() + caption; sessionParameter = getSessionParameter(captionUrl); // sessionParameter should always be non-null // because this overrides all other checks in /access/lessonbuilder, // we haven't adjusted it to handle these files otherwise if (sessionParameter != null) captionUrl = captionUrl + "?lb.session=" + sessionParameter; UIOutput.make(tableRow, "h5track") .decorate(new UIFreeAttributeDecorator("src", captionUrl)); } else if (!isAudio) { movieLink.decorate(new UIFreeAttributeDecorator("class", "allow-caption")); } } // FLV is special. There's no player for flash video in // the browser // it shows with a special flash program, which I // supply. For the moment MP4 is // shown with the same player so it uses much of the // same code if (mimeType != null && (mimeType.equals("video/x-flv") || mimeType.equals("video/flv") || isMp4)) { mimeType = "application/x-shockwave-flash"; movieUrl = "/lessonbuilder-tool/templates/StrobeMediaPlayback.swf"; useFlvPlayer = true; } // for IE, if we're not supplying a player it's safest // to use embed // otherwise Quicktime won't work. Oddly, with IE 9 only // it works if you set CLASSID to the MIME type, // but that's so unexpected that I hate to rely on it. // EMBED is in HTML 5, so I think we're OK // using it permanently for IE. // I prefer OBJECT where possible because of the nesting // ability. boolean useEmbed = ieVersion > 0 && !mimeType.equals("application/x-shockwave-flash"); if (useEmbed) { item2 = UIOutput.make(tableRow, "movieEmbed") .decorate(new UIFreeAttributeDecorator("src", movieUrl)) .decorate(new UIFreeAttributeDecorator("alt", messageLocator.getMessage("simplepage.mm_player").replace("{}", abbrevUrl(i.getURL())))); } else { item2 = UIOutput.make(tableRow, "movieObject") .decorate(new UIFreeAttributeDecorator("data", movieUrl)) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.mm_player").replace("{}", abbrevUrl(i.getURL())))); } if (mimeType != null) { item2.decorate(new UIFreeAttributeDecorator("type", mimeType)); } if (canEditPage) { //item2.decorate(new UIFreeAttributeDecorator("style", "border: 1px solid black")); } // some object types seem to need a specification, so supply our default if necessary if (lengthOk(height) && lengthOk(width)) { item2.decorate(new UIFreeAttributeDecorator("height", height.getOld())) .decorate(new UIFreeAttributeDecorator("width", width.getOld())); } else { if (oMimeType.startsWith("audio/")) item2.decorate(new UIFreeAttributeDecorator("height", "100")) .decorate(new UIFreeAttributeDecorator("width", "400")); else item2.decorate(new UIFreeAttributeDecorator("height", "300")) .decorate(new UIFreeAttributeDecorator("width", "400")); } if (!useEmbed) { if (useFlvPlayer) { UIOutput.make(tableRow, "flashvars") .decorate( new UIFreeAttributeDecorator("value", "src=" + URLEncoder.encode(myUrl() + i.getItemURL( simplePageBean.getCurrentSiteId(), currentPage.getOwner())))); // need wmode=opaque for player to stack properly with dialogs, etc. // there is a performance impact, but I'm guessing in our application we don't // need ultimate performance for embedded video. I'm setting it only for // the player, so flash games and other applications will still get wmode=window UIOutput.make(tableRow, "wmode"); } else if (mimeType.equals("application/x-shockwave-flash")) UIOutput.make(tableRow, "wmode"); UIOutput.make(tableRow, "movieURLInject") .decorate(new UIFreeAttributeDecorator("value", movieUrl)); if (!isMp4 && showDownloads) { UIOutput.make(tableRow, "noplugin-p", messageLocator.getMessage("simplepage.noplugin")); UIOutput.make(tableRow, "noplugin-br"); UILink.make(tableRow, "noplugin", i.getName(), movieUrl); } } if (isMp4) { // do fallback. for ie use EMBED if (ieVersion > 0) { item2 = UIOutput.make(tableRow, "mp4-embed") .decorate(new UIFreeAttributeDecorator("src", i.getItemURL(simplePageBean.getCurrentSiteId(), currentPage.getOwner()))) .decorate(new UIFreeAttributeDecorator("alt", messageLocator.getMessage("simplepage.mm_player").replace("{}", abbrevUrl(i.getURL())))); } else { item2 = UIOutput.make(tableRow, "mp4-object") .decorate(new UIFreeAttributeDecorator("data", i.getItemURL(simplePageBean.getCurrentSiteId(), currentPage.getOwner()))) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.mm_player").replace("{}", abbrevUrl(i.getURL())))); } if (oMimeType != null) { item2.decorate(new UIFreeAttributeDecorator("type", oMimeType)); } // some object types seem to need a specification, so give a default if needed if (lengthOk(height) && lengthOk(width)) { item2.decorate(new UIFreeAttributeDecorator("height", height.getOld())) .decorate(new UIFreeAttributeDecorator("width", width.getOld())); } else { if (oMimeType.startsWith("audio/")) item2.decorate(new UIFreeAttributeDecorator("height", "100")) .decorate(new UIFreeAttributeDecorator("width", "100%")); else item2.decorate(new UIFreeAttributeDecorator("height", "300")) .decorate(new UIFreeAttributeDecorator("width", "100%")); } if (!useEmbed) { UIOutput.make(tableRow, "mp4-inject") .decorate(new UIFreeAttributeDecorator("value", i.getItemURL( simplePageBean.getCurrentSiteId(), currentPage.getOwner()))); if (showDownloads) { UIOutput.make(tableRow, "mp4-noplugin-p", messageLocator.getMessage("simplepage.noplugin")); UILink.make(tableRow, "mp4-noplugin", i.getName(), i.getItemURL( simplePageBean.getCurrentSiteId(), currentPage.getOwner())); } } } UIOutput.make(tableRow, "description3", i.getDescription()); } else { UIVerbatim notAvailableText = UIVerbatim.make(tableRow, "notAvailableText", messageLocator.getMessage("simplepage.multimediaItemUnavailable")); // Grey it out notAvailableText .decorate(new UIFreeAttributeDecorator("class", "disabled-multimedia-item")); } if (canEditPage) { UIOutput.make(tableRow, "movieId", String.valueOf(i.getId())); UIOutput.make(tableRow, "movieHeight", getOrig(height)); UIOutput.make(tableRow, "movieWidth", getOrig(width)); UIOutput.make(tableRow, "mimetype5", oMimeType); UIOutput.make(tableRow, "prerequisite", (i.isPrerequisite()) ? "true" : "false"); UIOutput.make(tableRow, "current-item-id6", Long.toString(i.getId())); UIVerbatim.make(tableRow, "item-path5", getItemPath(i)); UIOutput.make(tableRow, "movie-td"); UILink.make(tableRow, "edit-movie", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.url").replace("{}", abbrevUrl(i.getURL())))); } } else { // this is fallthrough for html or an explicit mm display type (i.e. embed code) // odd types such as MS word will be handled by the AV code, and presented as <OBJECT> if (canSeeAll || simplePageBean.isItemAvailable(i)) { // definition of resizeiframe, at top of page if (!iframeJavascriptDone && getOrig(height).equals("auto")) { UIOutput.make(tofill, "iframeJavascript"); iframeJavascriptDone = true; } UIOutput.make(tableRow, "iframeSpan"); if (itemGroupString != null) { UIOutput.make(tableRow, "item-group-titles2", itemGroupTitles); UIOutput.make(tableRow, "item-groups2", itemGroupString); } String itemUrl = i.getItemURL(simplePageBean.getCurrentSiteId(), currentPage.getOwner()); if ("1".equals(mmDisplayType)) { // embed item = UIVerbatim.make(tableRow, "mm-embed", i.getAttribute("multimediaEmbedCode")); //String style = getStyle(width, height); //if (style != null) //item.decorate(new UIFreeAttributeDecorator("style", style)); } else if ("3".equals(mmDisplayType)) { item = UILink.make(tableRow, "mm-oembed", i.getAttribute("multimediaUrl"), i.getAttribute("multimediaUrl")); if (lengthOk(width)) item.decorate(new UIFreeAttributeDecorator("maxWidth", width.getOld())); if (lengthOk(height)) item.decorate(new UIFreeAttributeDecorator("maxHeight", height.getOld())); // oembed } else { UIOutput.make(tableRow, "iframe-link-div"); UILink.make(tableRow, "iframe-link-link", messageLocator.getMessage("simplepage.open_new_window"), itemUrl); item = UIOutput.make(tableRow, "iframe") .decorate(new UIFreeAttributeDecorator("src", itemUrl)); // if user specifies auto, use Javascript to resize the // iframe when the // content changes. This only works for URLs with the // same origin, i.e. // URLs in this sakai system if (getOrig(height).equals("auto")) { item.decorate(new UIFreeAttributeDecorator("onload", "resizeiframe('" + item.getFullID() + "')")); if (lengthOk(width)) { item.decorate(new UIFreeAttributeDecorator("width", width.getOld())); } item.decorate(new UIFreeAttributeDecorator("height", "300")); } else { // we seem OK without a spec if (lengthOk(height) && lengthOk(width)) { item.decorate(new UIFreeAttributeDecorator("height", height.getOld())) .decorate(new UIFreeAttributeDecorator("width", width.getOld())); } } } item.decorate(new UIFreeAttributeDecorator("title", messageLocator .getMessage("simplepage.web_content").replace("{}", abbrevUrl(i.getURL())))); if (canEditPage) { UIOutput.make(tableRow, "iframeHeight", getOrig(height)); UIOutput.make(tableRow, "iframeWidth", getOrig(width)); UIOutput.make(tableRow, "mimetype3", mimeType); UIOutput.make(tableRow, "item-prereq2", String.valueOf(i.isPrerequisite())); UIOutput.make(tableRow, "embedtype", mmDisplayType); UIOutput.make(tableRow, "current-item-id3", Long.toString(i.getId())); UIVerbatim.make(tableRow, "item-path2", getItemPath(i)); UIOutput.make(tableRow, "editmm-td"); UILink.make(tableRow, "iframe-edit", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.url").replace("{}", abbrevUrl(i.getURL())))); } UIOutput.make(tableRow, "description5", i.getDescription()); } else { UIVerbatim notAvailableText = UIVerbatim.make(tableRow, "notAvailableText", messageLocator.getMessage("simplepage.multimediaItemUnavailable")); // Grey it out notAvailableText .decorate(new UIFreeAttributeDecorator("class", "disabled-multimedia-item")); } } // end of multimedia object } else if (i.getType() == SimplePageItem.COMMENTS) { // Load later using AJAX and CommentsProducer UIOutput.make(tableRow, "commentsSpan"); boolean isAvailable = simplePageBean.isItemAvailable(i); // faculty missing preqs get warning but still see the comments if (!isAvailable && canSeeAll) UIOutput.make(tableRow, "missing-prereqs", messageLocator.getMessage("simplepage.fake-missing-prereqs")); // students get warning and not the content if (!isAvailable && !canSeeAll) { UIOutput.make(tableRow, "missing-prereqs", messageLocator.getMessage("simplepage.missing-prereqs")); } else { UIOutput.make(tableRow, "commentsDiv"); UIOutput.make(tableRow, "placementId", placement.getId()); // note: the URL will be rewritten in comments.js to look like // /lessonbuilder-tool/faces/Comments... CommentsViewParameters eParams = new CommentsViewParameters(CommentsProducer.VIEW_ID); eParams.itemId = i.getId(); eParams.placementId = placement.getId(); if (params.postedComment) { eParams.postedComment = postedCommentId; } eParams.siteId = simplePageBean.getCurrentSiteId(); eParams.pageId = currentPage.getPageId(); if (params.author != null && !params.author.equals("")) { eParams.author = params.author; eParams.showAllComments = true; } UIInternalLink.make(tableRow, "commentsLink", eParams); if (!addedCommentsScript) { UIOutput.make(tofill, "comments-script"); UIOutput.make(tofill, "fckScript"); addedCommentsScript = true; UIOutput.make(tofill, "delete-dialog"); } // forced comments have to be edited on the main page if (canEditPage) { // Checks to make sure that the comments item isn't on a student page. // That it is graded. And that we didn't just come from the grading pane. if (i.getPageId() > 0 && i.getGradebookId() != null && !cameFromGradingPane) { CommentsGradingPaneViewParameters gp = new CommentsGradingPaneViewParameters( CommentGradingPaneProducer.VIEW_ID); gp.placementId = toolManager.getCurrentPlacement().getId(); gp.commentsItemId = i.getId(); gp.pageId = currentPage.getPageId(); gp.pageItemId = pageItem.getId(); gp.siteId = simplePageBean.getCurrentSiteId(); UIInternalLink.make(tableRow, "gradingPaneLink", messageLocator.getMessage("simplepage.show-grading-pane-comments"), gp) .decorate(new UIFreeAttributeDecorator("title", messageLocator .getMessage("simplepage.show-grading-pane-comments"))); } UIOutput.make(tableRow, "comments-td"); if (i.getSequence() > 0) { UILink.make(tableRow, "edit-comments", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.comments"))); UIOutput.make(tableRow, "commentsId", String.valueOf(i.getId())); UIOutput.make(tableRow, "commentsAnon", String.valueOf(i.isAnonymous())); UIOutput.make(tableRow, "commentsitem-required", String.valueOf(i.isRequired())); UIOutput.make(tableRow, "commentsitem-prerequisite", String.valueOf(i.isPrerequisite())); UIOutput.make(tableRow, "commentsGrade", String.valueOf(i.getGradebookId() != null)); UIOutput.make(tableRow, "commentsMaxPoints", String.valueOf(i.getGradebookPoints())); String itemGroupString = simplePageBean.getItemGroupString(i, null, true); if (itemGroupString != null) { String itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i); if (itemGroupTitles != null) { itemGroupTitles = "[" + itemGroupTitles + "]"; } UIOutput.make(tableRow, "comments-groups", itemGroupString); UIOutput.make(tableRow, "item-group-titles6", itemGroupTitles); } } // Allows AJAX posting of comment grades printGradingForm(tofill); } UIForm form = UIForm.make(tableRow, "comment-form"); makeCsrf(form, "csrf2"); UIInput.make(form, "comment-item-id", "#{simplePageBean.itemId}", String.valueOf(i.getId())); UIInput.make(form, "comment-edit-id", "#{simplePageBean.editId}"); // usage * image is required and not done if (i.isRequired() && !simplePageBean.isItemComplete(i)) UIOutput.make(tableRow, "comment-required-image"); UIOutput.make(tableRow, "add-comment-link"); UIOutput.make(tableRow, "add-comment-text", messageLocator.getMessage("simplepage.add-comment")); UIInput fckInput = UIInput.make(form, "comment-text-area-evolved:", "#{simplePageBean.formattedComment}"); fckInput.decorate(new UIFreeAttributeDecorator("height", "175")); fckInput.decorate(new UIFreeAttributeDecorator("width", "800")); fckInput.decorate(new UIStyleDecorator("evolved-box")); fckInput.decorate(new UIFreeAttributeDecorator("aria-label", messageLocator.getMessage("simplepage.editor"))); fckInput.decorate(new UIFreeAttributeDecorator("role", "dialog")); if (!noEditor) { fckInput.decorate(new UIStyleDecorator("using-editor")); // javascript needs to know ((SakaiFCKTextEvolver) richTextEvolver).evolveTextInput(fckInput, "" + commentsCount); } UICommand.make(form, "add-comment", "#{simplePageBean.addComment}"); } } else if (i.getType() == SimplePageItem.PEEREVAL) { String owner = currentPage.getOwner(); String currentUser = UserDirectoryService.getCurrentUser().getId(); Long pageId = currentPage.getPageId(); UIOutput.make(tableRow, "peerReviewRubricStudent"); UIOutput.make(tableRow, "peer-review-form"); makePeerRubric(tableRow, i, makeStudentRubric); boolean isOpen = false; boolean isPastDue = false; String peerEvalDateOpenStr = i.getAttribute("rubricOpenDate"); String peerEvalDateDueStr = i.getAttribute("rubricDueDate"); boolean peerEvalAllowSelfGrade = Boolean.parseBoolean(i.getAttribute("rubricAllowSelfGrade")); boolean gradingSelf = owner.equals(currentUser) && peerEvalAllowSelfGrade; if (peerEvalDateOpenStr != null && peerEvalDateDueStr != null) { Date peerEvalNow = new Date(); Date peerEvalOpen = new Date(Long.valueOf(peerEvalDateOpenStr)); Date peerEvalDue = new Date(Long.valueOf(peerEvalDateDueStr)); isOpen = peerEvalNow.after(peerEvalOpen); isPastDue = peerEvalNow.after(peerEvalDue); } if (isOpen) { if (owner.equals(currentUser)) { //owner gets their own data class PeerEvaluation { String category; public int grade, count; public PeerEvaluation(String category, int grade) { this.category = category; this.grade = grade; count = 1; } public void increment() { count++; } public boolean equals(Object o) { if (!(o instanceof PeerEvaluation)) return false; PeerEvaluation pe = (PeerEvaluation) o; return category.equals(pe.category) && grade == pe.grade; } public String toString() { return category + " " + grade + " [" + count + "]"; } } ArrayList<PeerEvaluation> myEvaluations = new ArrayList<PeerEvaluation>(); List<SimplePagePeerEvalResult> evaluations = simplePageToolDao .findPeerEvalResultByOwner(pageId.longValue(), owner); if (evaluations != null) for (SimplePagePeerEvalResult eval : evaluations) { PeerEvaluation target = new PeerEvaluation(eval.getRowText(), eval.getColumnValue()); int targetIndex = myEvaluations.indexOf(target); if (targetIndex != -1) { myEvaluations.get(targetIndex).increment(); } else myEvaluations.add(target); } UIOutput.make(tableRow, "my-existing-peer-eval-data"); for (PeerEvaluation eval : myEvaluations) { UIBranchContainer evalData = UIBranchContainer.make(tableRow, "my-peer-eval-data:"); UIOutput.make(evalData, "peer-eval-row-text", eval.category); UIOutput.make(evalData, "peer-eval-grade", String.valueOf(eval.grade)); UIOutput.make(evalData, "peer-eval-count", String.valueOf(eval.count)); } } if (!owner.equals(currentUser) || gradingSelf) { List<SimplePagePeerEvalResult> evaluations = simplePageToolDao .findPeerEvalResult(pageId, currentUser, owner); //existing evaluation data if (evaluations != null && evaluations.size() != 0) { UIOutput.make(tableRow, "existing-peer-eval-data"); for (SimplePagePeerEvalResult eval : evaluations) { UIBranchContainer evalData = UIBranchContainer.make(tableRow, "peer-eval-data:"); UIOutput.make(evalData, "peer-eval-row-text", eval.getRowText()); UIOutput.make(evalData, "peer-eval-grade", String.valueOf(eval.getColumnValue())); } } //form for peer evaluation results UIForm form = UIForm.make(tofill, "rubricSelection"); makeCsrf(form, "csrf6"); UIInput.make(form, "rubricPeerGrade", "#{simplePageBean.rubricPeerGrade}"); UICommand.make(form, "update-peer-eval-grade", messageLocator.getMessage("simplepage.edit"), "#{simplePageBean.savePeerEvalResult}"); } //buttons UIOutput.make(tableRow, "add-peereval-link"); UIOutput.make(tableRow, "add-peereval-text", messageLocator.getMessage("simplepage.view-peereval")); if (isPastDue) { UIOutput.make(tableRow, "peer-eval-grade-directions", messageLocator.getMessage("simplepage.peer-eval.past-due-date")); } else if (!owner.equals(currentUser) || gradingSelf) { UIOutput.make(tableRow, "save-peereval-link"); UIOutput.make(tableRow, "save-peereval-text", messageLocator.getMessage("simplepage.save")); UIOutput.make(tableRow, "cancel-peereval-link"); UIOutput.make(tableRow, "cancel-peereval-text", messageLocator.getMessage("simplepage.cancel")); UIOutput.make(tableRow, "peer-eval-grade-directions", messageLocator.getMessage("simplepage.peer-eval.click-on-cell")); } else { //owner who cannot grade himself UIOutput.make(tableRow, "peer-eval-grade-directions", messageLocator.getMessage("simplepage.peer-eval.cant-eval-yourself")); } if (canEditPage) UIOutput.make(tableRow, "peerReviewRubricStudent-edit");//lines up rubric with edit btn column for users with editing privs } } else if (i.getType() == SimplePageItem.STUDENT_CONTENT) { UIOutput.make(tableRow, "studentSpan"); boolean isAvailable = simplePageBean.isItemAvailable(i); // faculty missing preqs get warning but still see the comments if (!isAvailable && canSeeAll) UIOutput.make(tableRow, "student-missing-prereqs", messageLocator.getMessage("simplepage.student-fake-missing-prereqs")); if (!isAvailable && !canSeeAll) UIOutput.make(tableRow, "student-missing-prereqs", messageLocator.getMessage("simplepage.student-missing-prereqs")); else { UIOutput.make(tableRow, "studentDiv"); HashMap<Long, SimplePageLogEntry> cache = simplePageBean .cacheStudentPageLogEntries(i.getId()); List<SimpleStudentPage> studentPages = simplePageToolDao.findStudentPages(i.getId()); boolean hasOwnPage = false; String userId = UserDirectoryService.getCurrentUser().getId(); Collections.sort(studentPages, new Comparator<SimpleStudentPage>() { public int compare(SimpleStudentPage o1, SimpleStudentPage o2) { String title1 = o1.getTitle(); if (title1 == null) title1 = ""; String title2 = o2.getTitle(); if (title2 == null) title2 = ""; return title1.compareTo(title2); } }); UIOutput contentList = UIOutput.make(tableRow, "studentContentTable"); UIOutput contentTitle = UIOutput.make(tableRow, "studentContentTitle", messageLocator.getMessage("simplepage.student")); contentList.decorate( new UIFreeAttributeDecorator("aria-labelledby", contentTitle.getFullID())); // Print each row in the table for (SimpleStudentPage page : studentPages) { if (page.isDeleted()) continue; SimplePageLogEntry entry = cache.get(page.getPageId()); UIBranchContainer row = UIBranchContainer.make(tableRow, "studentRow:"); // There's content they haven't seen if (entry == null || entry.getLastViewed().compareTo(page.getLastUpdated()) < 0) { UIOutput.make(row, "newContentImg").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.new-student-content"))); } else UIOutput.make(row, "newContentImgT"); // The comments tool exists, so we might have to show the icon if (i.getShowComments() != null && i.getShowComments()) { // New comments have been added since they last viewed the page if (page.getLastCommentChange() != null && (entry == null || entry.getLastViewed().compareTo(page.getLastCommentChange()) < 0)) { UIOutput.make(row, "newCommentsImg").decorate(new UIFreeAttributeDecorator( "title", messageLocator.getMessage("simplepage.new-student-comments"))); } else UIOutput.make(row, "newCommentsImgT"); } // Never visited page if (entry == null) { UIOutput.make(row, "newPageImg").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.new-student-page"))); } else UIOutput.make(row, "newPageImgT"); GeneralViewParameters eParams = new GeneralViewParameters(ShowPageProducer.VIEW_ID, page.getPageId()); eParams.setItemId(i.getId()); eParams.setPath("push"); String studentTitle = page.getTitle(); String sownerName = null; try { if (!i.isAnonymous() || canEditPage) { if (page.getGroup() != null) sownerName = simplePageBean.getCurrentSite().getGroup(page.getGroup()) .getTitle(); else sownerName = UserDirectoryService.getUser(page.getOwner()).getDisplayName(); if (sownerName != null && sownerName.equals(studentTitle)) studentTitle = "(" + sownerName + ")"; else studentTitle += " (" + sownerName + ")"; } else if (simplePageBean.isPageOwner(page)) { studentTitle += " (" + messageLocator.getMessage("simplepage.comment-you") + ")"; } } catch (UserNotDefinedException e) { } UIInternalLink.make(row, "studentLink", studentTitle, eParams); if (simplePageBean.isPageOwner(page)) { hasOwnPage = true; } if (i.getGradebookId() != null && simplePageBean.getEditPrivs() == 0) { UIOutput.make(row, "studentGradingCell", String.valueOf((page.getPoints() != null ? page.getPoints() : ""))); } } if (!hasOwnPage && simplePageBean.myStudentPageGroupsOk(i)) { UIBranchContainer row = UIBranchContainer.make(tableRow, "studentRow:"); UIOutput.make(row, "linkRow"); UIOutput.make(row, "linkCell"); if (i.isRequired() && !simplePageBean.isItemComplete(i)) UIOutput.make(row, "student-required-image"); GeneralViewParameters eParams = new GeneralViewParameters(ShowPageProducer.VIEW_ID); eParams.addTool = GeneralViewParameters.STUDENT_PAGE; eParams.studentItemId = i.getId(); UIInternalLink.make(row, "linkLink", messageLocator.getMessage("simplepage.add-page"), eParams); } String itemGroupString = null; // do before canEditAll because we need itemGroupString in it if (canSeeAll) { itemGroupString = simplePageBean.getItemGroupString(i, null, true); if (itemGroupString != null) { String itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i); if (itemGroupTitles != null) { itemGroupTitles = "[" + itemGroupTitles + "]"; } UIOutput.make(tableRow, "item-group-titles7", itemGroupTitles); } } if (canEditPage) { // Checks to make sure that the comments are graded and that we didn't // just come from a grading pane (would be confusing) if (i.getAltGradebook() != null && !cameFromGradingPane) { CommentsGradingPaneViewParameters gp = new CommentsGradingPaneViewParameters( CommentGradingPaneProducer.VIEW_ID); gp.placementId = toolManager.getCurrentPlacement().getId(); gp.commentsItemId = i.getId(); gp.pageId = currentPage.getPageId(); gp.pageItemId = pageItem.getId(); gp.studentContentItem = true; UIInternalLink.make(tableRow, "studentGradingPaneLink", messageLocator.getMessage("simplepage.show-grading-pane-content"), gp) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.show-grading-pane-content"))); } UIOutput.make(tableRow, "student-td"); UILink.make(tableRow, "edit-student", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.student"))); UIOutput.make(tableRow, "studentId", String.valueOf(i.getId())); UIOutput.make(tableRow, "studentAnon", String.valueOf(i.isAnonymous())); UIOutput.make(tableRow, "studentComments", String.valueOf(i.getShowComments())); UIOutput.make(tableRow, "forcedAnon", String.valueOf(i.getForcedCommentsAnonymous())); UIOutput.make(tableRow, "studentGrade", String.valueOf(i.getGradebookId() != null)); UIOutput.make(tableRow, "studentMaxPoints", String.valueOf(i.getGradebookPoints())); UIOutput.make(tableRow, "studentGrade2", String.valueOf(i.getAltGradebook() != null)); UIOutput.make(tableRow, "studentMaxPoints2", String.valueOf(i.getAltPoints())); UIOutput.make(tableRow, "studentitem-required", String.valueOf(i.isRequired())); UIOutput.make(tableRow, "studentitem-prerequisite", String.valueOf(i.isPrerequisite())); UIOutput.make(tableRow, "peer-eval", String.valueOf(i.getShowPeerEval())); makePeerRubric(tableRow, i, makeMaintainRubric); makeSamplePeerEval(tableRow); String peerEvalDate = i.getAttribute("rubricOpenDate"); String peerDueDate = i.getAttribute("rubricDueDate"); Calendar peerevalcal = Calendar.getInstance(); if (peerEvalDate != null && peerDueDate != null) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, M_locale); //Open date from attribute string peerevalcal.setTimeInMillis(Long.valueOf(peerEvalDate)); String dateStr = isoDateFormat.format(peerevalcal.getTime()); UIOutput.make(tableRow, "peer-eval-open-date", dateStr); //Due date from attribute string peerevalcal.setTimeInMillis(Long.valueOf(peerDueDate)); dateStr = isoDateFormat.format(peerevalcal.getTime()); UIOutput.make(tableRow, "peer-eval-due-date", dateStr); UIOutput.make(tableRow, "peer-eval-allow-self", i.getAttribute("rubricAllowSelfGrade")); } else { //Default open and due date Date now = new Date(); peerevalcal.setTime(now); //Default open date: now String dateStr = isoDateFormat.format(peerevalcal.getTime()); UIOutput.make(tableRow, "peer-eval-open-date", dateStr); //Default due date: 7 days from now Date later = new Date(peerevalcal.getTimeInMillis() + 604800000); peerevalcal.setTime(later); dateStr = isoDateFormat.format(peerevalcal.getTime()); //System.out.println("Setting date to " + dateStr + " and time to " + timeStr); UIOutput.make(tableRow, "peer-eval-due-date", dateStr); UIOutput.make(tableRow, "peer-eval-allow-self", i.getAttribute("rubricAllowSelfGrade")); } //Peer Eval Stats link GeneralViewParameters view = new GeneralViewParameters(PeerEvalStatsProducer.VIEW_ID); view.setSendingPage(currentPage.getPageId()); view.setItemId(i.getId()); if (i.getShowPeerEval()) { UILink link = UIInternalLink.make(tableRow, "peer-eval-stats-link", view); } if (itemGroupString != null) { UIOutput.make(tableRow, "student-groups", itemGroupString); } UIOutput.make(tableRow, "student-owner-groups", simplePageBean.getItemOwnerGroupString(i)); UIOutput.make(tableRow, "student-group-owned", (i.isGroupOwned() ? "true" : "false")); } } } else if (i.getType() == SimplePageItem.QUESTION) { String itemGroupString = null; String itemGroupTitles = null; if (canSeeAll) { itemGroupString = simplePageBean.getItemGroupString(i, null, true); if (itemGroupString != null) itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i); if (itemGroupTitles != null) { itemGroupTitles = "[" + itemGroupTitles + "]"; } if (canEditPage) UIOutput.make(tableRow, "item-groups", itemGroupString); if (itemGroupTitles != null) UIOutput.make(tableRow, "questionitem-group-titles", itemGroupTitles); } SimplePageQuestionResponse response = simplePageToolDao.findQuestionResponse(i.getId(), simplePageBean.getCurrentUserId()); UIOutput.make(tableRow, "questionSpan"); boolean isAvailable = simplePageBean.isItemAvailable(i) || canSeeAll; UIOutput.make(tableRow, "questionDiv"); UIOutput.make(tableRow, "questionText", i.getAttribute("questionText")); List<SimplePageQuestionAnswer> answers = new ArrayList<SimplePageQuestionAnswer>(); if ("multipleChoice".equals(i.getAttribute("questionType"))) { answers = simplePageToolDao.findAnswerChoices(i); UIOutput.make(tableRow, "multipleChoiceDiv"); UIForm questionForm = UIForm.make(tableRow, "multipleChoiceForm"); makeCsrf(questionForm, "csrf4"); UIInput.make(questionForm, "multipleChoiceId", "#{simplePageBean.questionId}", String.valueOf(i.getId())); String[] options = new String[answers.size()]; String initValue = null; for (int j = 0; j < answers.size(); j++) { options[j] = String.valueOf(answers.get(j).getId()); if (response != null && answers.get(j).getId() == response.getMultipleChoiceId()) { initValue = String.valueOf(answers.get(j).getId()); } } UISelect multipleChoiceSelect = UISelect.make(questionForm, "multipleChoiceSelect:", options, "#{simplePageBean.questionResponse}", initValue); if (!isAvailable || response != null) { multipleChoiceSelect.decorate(new UIDisabledDecorator()); } for (int j = 0; j < answers.size(); j++) { UIBranchContainer answerContainer = UIBranchContainer.make(questionForm, "multipleChoiceAnswer:", String.valueOf(j)); UISelectChoice multipleChoiceInput = UISelectChoice.make(answerContainer, "multipleChoiceAnswerRadio", multipleChoiceSelect.getFullID(), j); multipleChoiceInput .decorate(new UIFreeAttributeDecorator("id", multipleChoiceInput.getFullID())); UIOutput.make(answerContainer, "multipleChoiceAnswerText", answers.get(j).getText()) .decorate(new UIFreeAttributeDecorator("for", multipleChoiceInput.getFullID())); if (!isAvailable || response != null) { multipleChoiceInput.decorate(new UIDisabledDecorator()); } } UICommand answerButton = UICommand.make(questionForm, "answerMultipleChoice", messageLocator.getMessage("simplepage.answer_question"), "#{simplePageBean.answerMultipleChoiceQuestion}"); if (!isAvailable || response != null) { answerButton.decorate(new UIDisabledDecorator()); } } else if ("shortanswer".equals(i.getAttribute("questionType"))) { UIOutput.make(tableRow, "shortanswerDiv"); UIForm questionForm = UIForm.make(tableRow, "shortanswerForm"); makeCsrf(questionForm, "csrf5"); UIInput.make(questionForm, "shortanswerId", "#{simplePageBean.questionId}", String.valueOf(i.getId())); UIInput shortanswerInput = UIInput.make(questionForm, "shortanswerInput", "#{simplePageBean.questionResponse}"); if (!isAvailable || response != null) { shortanswerInput.decorate(new UIDisabledDecorator()); if (response != null && response.getShortanswer() != null) { shortanswerInput.setValue(response.getShortanswer()); } } UICommand answerButton = UICommand.make(questionForm, "answerShortanswer", messageLocator.getMessage("simplepage.answer_question"), "#{simplePageBean.answerShortanswerQuestion}"); if (!isAvailable || response != null) { answerButton.decorate(new UIDisabledDecorator()); } } Status questionStatus = getQuestionStatus(i, response); addStatusImage(questionStatus, tableRow, "questionStatus", null); String statusNote = getStatusNote(questionStatus); if (statusNote != null) // accessibility version of icon UIOutput.make(tableRow, "questionNote", statusNote); String statusText = null; if (questionStatus == Status.COMPLETED) statusText = i.getAttribute("questionCorrectText"); else if (questionStatus == Status.FAILED) statusText = i.getAttribute("questionIncorrectText"); if (statusText != null && !"".equals(statusText.trim())) UIOutput.make(tableRow, "questionStatusText", statusText); // Output the poll data if ("multipleChoice".equals(i.getAttribute("questionType")) && (canEditPage || ("true".equals(i.getAttribute("questionShowPoll")) && (questionStatus == Status.COMPLETED || questionStatus == Status.FAILED)))) { UIOutput.make(tableRow, "showPollGraph", messageLocator.getMessage("simplepage.show-poll")); UIOutput questionGraph = UIOutput.make(tableRow, "questionPollGraph"); questionGraph.decorate(new UIFreeAttributeDecorator("id", "poll" + i.getId())); List<SimplePageQuestionResponseTotals> totals = simplePageToolDao.findQRTotals(i.getId()); HashMap<Long, Long> responseCounts = new HashMap<Long, Long>(); // in theory we don't need the first loop, as there should be a total // entry for all possible answers. But in case things are out of sync ... for (SimplePageQuestionAnswer answer : answers) responseCounts.put(answer.getId(), 0L); for (SimplePageQuestionResponseTotals total : totals) responseCounts.put(total.getResponseId(), total.getCount()); for (int j = 0; j < answers.size(); j++) { UIBranchContainer pollContainer = UIBranchContainer.make(tableRow, "questionPollData:", String.valueOf(j)); UIOutput.make(pollContainer, "questionPollText", answers.get(j).getText()); UIOutput.make(pollContainer, "questionPollNumber", String.valueOf(responseCounts.get(answers.get(j).getId()))); } } if (canEditPage) { UIOutput.make(tableRow, "question-td"); // always show grading panel. Currently this is the only way to get feedback if (!cameFromGradingPane) { QuestionGradingPaneViewParameters gp = new QuestionGradingPaneViewParameters( QuestionGradingPaneProducer.VIEW_ID); gp.placementId = toolManager.getCurrentPlacement().getId(); gp.questionItemId = i.getId(); gp.pageId = currentPage.getPageId(); gp.pageItemId = pageItem.getId(); UIInternalLink .make(tableRow, "questionGradingPaneLink", messageLocator.getMessage("simplepage.show-grading-pane"), gp) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.show-grading-pane"))); } UILink.make(tableRow, "edit-question", (String) null, "") .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.question"))); UIOutput.make(tableRow, "questionId", String.valueOf(i.getId())); boolean graded = "true".equals(i.getAttribute("questionGraded")) || i.getGradebookId() != null; UIOutput.make(tableRow, "questionGrade", String.valueOf(graded)); UIOutput.make(tableRow, "questionMaxPoints", String.valueOf(i.getGradebookPoints())); UIOutput.make(tableRow, "questionGradebookTitle", String.valueOf(i.getGradebookTitle())); UIOutput.make(tableRow, "questionitem-required", String.valueOf(i.isRequired())); UIOutput.make(tableRow, "questionitem-prerequisite", String.valueOf(i.isPrerequisite())); UIOutput.make(tableRow, "questionitem-groups", itemGroupString); UIOutput.make(tableRow, "questionCorrectText", String.valueOf(i.getAttribute("questionCorrectText"))); UIOutput.make(tableRow, "questionIncorrectText", String.valueOf(i.getAttribute("questionIncorrectText"))); if ("shortanswer".equals(i.getAttribute("questionType"))) { UIOutput.make(tableRow, "questionType", "shortanswer"); UIOutput.make(tableRow, "questionAnswer", i.getAttribute("questionAnswer")); } else { UIOutput.make(tableRow, "questionType", "multipleChoice"); for (int j = 0; j < answers.size(); j++) { UIBranchContainer answerContainer = UIBranchContainer.make(tableRow, "questionMultipleChoiceAnswer:", String.valueOf(j)); UIOutput.make(answerContainer, "questionMultipleChoiceAnswerId", String.valueOf(answers.get(j).getId())); UIOutput.make(answerContainer, "questionMultipleChoiceAnswerText", answers.get(j).getText()); UIOutput.make(answerContainer, "questionMultipleChoiceAnswerCorrect", String.valueOf(answers.get(j).isCorrect())); } UIOutput.make(tableRow, "questionShowPoll", String.valueOf(i.getAttribute("questionShowPoll"))); } } } else { // remaining type must be a block of HTML UIOutput.make(tableRow, "itemSpan"); if (canSeeAll) { String itemGroupString = simplePageBean.getItemGroupString(i, null, true); String itemGroupTitles = simplePageBean.getItemGroupTitles(itemGroupString, i); if (itemGroupTitles != null) { itemGroupTitles = "[" + itemGroupTitles + "]"; } UIOutput.make(tableRow, "item-groups-titles-text", itemGroupTitles); } if (canSeeAll || simplePageBean.isItemAvailable(i)) { UIVerbatim.make(tableRow, "content", (i.getHtml() == null ? "" : i.getHtml())); } else { UIComponent unavailableText = UIOutput.make(tableRow, "content", messageLocator.getMessage("simplepage.textItemUnavailable")); unavailableText.decorate(new UIFreeAttributeDecorator("class", "disabled-text-item")); } // editing is done using a special producer that calls FCK. if (canEditPage) { GeneralViewParameters eParams = new GeneralViewParameters(); eParams.setSendingPage(currentPage.getPageId()); eParams.setItemId(i.getId()); eParams.viewID = EditPageProducer.VIEW_ID; UIOutput.make(tableRow, "edittext-td"); UIInternalLink.make(tableRow, "edit-link", (String) null, eParams) .decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.edit-title.textbox").replace("{}", Integer.toString(textboxcount)))); textboxcount++; } } } // end of items. This is the end for normal users. Following is // special // checks and putting out the dialogs for the popups, for // instructors. boolean showBreak = false; // I believe refresh is now done automatically in all cases // if (showRefresh) { // UIOutput.make(tofill, "refreshAlert"); // // // Should simply refresh // GeneralViewParameters p = new GeneralViewParameters(VIEW_ID); // p.setSendingPage(currentPage.getPageId()); // UIInternalLink.make(tofill, "refreshLink", p); // showBreak = true; // } // stuff goes on the page in the order in the HTML file. So the fact // that it's here doesn't mean it shows // up at the end. This code produces errors and other odd stuff. if (canSeeAll) { // if the page is hidden, warn the faculty [students get stopped // at // the top] if (currentPage.isHidden()) { UIOutput.make(tofill, "hiddenAlert").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.pagehidden"))); UIVerbatim.make(tofill, "hidden-text", messageLocator.getMessage("simplepage.pagehidden.text")); showBreak = true; // similarly warn them if it isn't released yet } else if (currentPage.getReleaseDate() != null && currentPage.getReleaseDate().after(new Date())) { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, M_locale); TimeZone tz = timeService.getLocalTimeZone(); df.setTimeZone(tz); String releaseDate = df.format(currentPage.getReleaseDate()); UIOutput.make(tofill, "hiddenAlert").decorate(new UIFreeAttributeDecorator("title", messageLocator.getMessage("simplepage.notreleased"))); UIVerbatim.make(tofill, "hidden-text", messageLocator.getMessage("simplepage.notreleased.text").replace("{}", releaseDate)); showBreak = true; } } if (showBreak) { UIOutput.make(tofill, "breakAfterWarnings"); } } // more warnings: if no item on the page, give faculty instructions, // students an error if (!anyItemVisible) { if (canEditPage) { String helpUrl = null; // order: // localized placedholder // localized general // default placeholder // we know the defaults exist because we include them, so // we never need to consider default general if (currentPage.getOwner() != null) helpUrl = getLocalizedURL("student.html", true); else { helpUrl = getLocalizedURL("placeholder.html", false); if (helpUrl == null) helpUrl = getLocalizedURL("general.html", false); if (helpUrl == null) helpUrl = getLocalizedURL("placeholder.html", true); } UIOutput.make(tofill, "startupHelp").decorate(new UIFreeAttributeDecorator("src", helpUrl)) .decorate(new UIFreeAttributeDecorator("id", "iframe")); if (!iframeJavascriptDone) { UIOutput.make(tofill, "iframeJavascript"); iframeJavascriptDone = true; } } else { UIOutput.make(tofill, "error-div"); UIOutput.make(tofill, "error", messageLocator.getMessage("simplepage.noitems_error_user")); } } // now output the dialogs. but only for faculty (to avoid making the // file bigger) if (canEditPage) { createSubpageDialog(tofill, currentPage); } createDialogs(tofill, currentPage, pageItem); }
From source file:org.sakaiproject.lessonbuildertool.tool.beans.SimplePageBean.java
public String addAssignment() { DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, new ResourceLoader().getLocale()); df.setTimeZone(TimeService.getLocalTimeZone()); if (!itemOk(itemId)) return "permission-failed"; if (!canEditPage()) return "permission-failed"; if (!checkCsrf()) return "permission-failed"; if (selectedAssignment == null) { return "failure"; } else {//from w w w . j av a2 s .c o m try { LessonEntity selectedObject = assignmentEntity.getEntity(selectedAssignment); if (selectedObject == null) return "failure"; SimplePageItem i; // editing existing item? if (itemId != null && itemId != -1) { i = findItem(itemId); // if no change, don't worry LessonEntity existing = assignmentEntity.getEntity(i.getSakaiId()); String ref = null; if (existing != null) ref = existing.getReference(); // if same quiz, nothing to do if ((existing == null) || !ref.equals(selectedAssignment)) { // if access controlled, clear restriction from old assignment and add to new if (i.isPrerequisite()) { if (existing != null) { i.setPrerequisite(false); checkControlGroup(i, false); } // sakaiid and name are used in setting control i.setSakaiId(selectedAssignment); i.setName(selectedObject.getTitle()); i.setPrerequisite(true); checkControlGroup(i, true); } else { i.setSakaiId(selectedAssignment); i.setName(selectedObject.getTitle()); } // reset assignment-specific stuff // Because we don't update the due date when it changes, this raises more // problems than it fixes. It's also done only for assignments and not tests // if (selectedObject.getDueDate() != null) // i.setDescription("(" + messageLocator.getMessage("simplepage.due") + " " + df.format(selectedObject.getDueDate()) + ")"); // else // i.setDescription(null); update(i); } } else { // no, add new item i = appendItem(selectedAssignment, selectedObject.getTitle(), SimplePageItem.ASSIGNMENT); //if (selectedObject.getDueDate() != null) // i.setDescription("(" + messageLocator.getMessage("simplepage.due") + " " + df.format(selectedObject.getDueDate()) + ")"); //else i.setDescription(null); update(i); } return "success"; } catch (Exception ex) { ex.printStackTrace(); return "failure"; } finally { selectedAssignment = null; } } }