001: /*
002: * $Id: LoopSubContentCacheTransform.java,v 1.3 2004/01/13 06:16:30 byersa Exp $
003: *
004: * Copyright (c) 2001-2003 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
007: * in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
009: *
010: * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
011: *
012: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
013: * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
014: * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
015: *
016: */
017: package org.ofbiz.content.webapp.ftl;
018:
019: import java.io.IOException;
020: import java.io.Writer;
021: import java.sql.Timestamp;
022: import java.util.List;
023: import java.util.Locale;
024: import java.util.Map;
025: import java.util.Iterator;
026: import java.util.ArrayList;
027: import javax.servlet.http.HttpServletRequest;
028:
029: import org.ofbiz.base.util.Debug;
030: import org.ofbiz.base.util.GeneralException;
031: import org.ofbiz.base.util.UtilDateTime;
032: import org.ofbiz.base.util.UtilMisc;
033: import org.ofbiz.base.util.UtilValidate;
034: import org.ofbiz.content.content.ContentServicesComplex;
035: import org.ofbiz.content.content.ContentWorker;
036: import org.ofbiz.entity.GenericDelegator;
037: import org.ofbiz.entity.GenericEntityException;
038: import org.ofbiz.entity.GenericValue;
039: import org.ofbiz.minilang.MiniLangException;
040:
041: import freemarker.template.Environment;
042: import freemarker.template.SimpleHash;
043: import freemarker.template.TemplateHashModel;
044: import freemarker.template.TemplateTransformModel;
045: import freemarker.template.TransformControl;
046: import freemarker.template.TemplateModelException;
047:
048: /**
049: * LoopSubContentCacheTransform - Freemarker Transform for URLs (links)
050: *
051: * @author <a href="mailto:byersa@automationgroups.com">Al Byers</a>
052: * @version $Revision: 1.3 $
053: * @since 3.0
054: */
055: public class LoopSubContentCacheTransform implements
056: TemplateTransformModel {
057:
058: public static final String module = LoopSubContentCacheTransform.class
059: .getName();
060:
061: public static final String[] saveKeyNames = { "contentId",
062: "subContentId", "mimeTypeId", "subContentDataResourceView",
063: "wrapTemplateId", "contentTemplateId", "globalNodeTrail",
064: "entityList", "viewSize", "viewIndex", "highIndex",
065: "lowIndex", "listSize", "nodeTrail",
066: "passedGlobalNodeTrail" };
067: public static final String[] removeKeyNames = { "wrapTemplateId",
068: "entityList", "entityIndex", "textData", "dataResourceId",
069: "drDataResourceId", "subContentIdSub", "parentContent",
070: "wrappedFTL", "trailCsv", "indent" };
071:
072: /**
073: * A wrapper for the FreeMarkerWorker version.
074: */
075: public static Object getWrappedObject(String varName,
076: Environment env) {
077: return FreeMarkerWorker.getWrappedObject(varName, env);
078: }
079:
080: public static String getArg(Map args, String key, Environment env) {
081: return FreeMarkerWorker.getArg(args, key, env);
082: }
083:
084: public static String getArg(Map args, String key, Map ctx) {
085: return FreeMarkerWorker.getArg(args, key, ctx);
086: }
087:
088: public static boolean prepCtx(GenericDelegator delegator, Map ctx) {
089:
090: //String contentId = (String)ctx.get("contentId");
091: //String mimeTypeId = (String)ctx.get("mimeTypeId");
092: List lst = (List) ctx.get("entityList");
093: //if (Debug.verboseOn()) Debug.logVerbose("in LoopSubContentCache, prepCtx, lst :" + lst, module);
094: Integer idx = (Integer) ctx.get("entityIndex");
095: if (Debug.verboseOn())
096: Debug.logVerbose("in LoopSubContentCache, prepCtx, idx :"
097: + idx, module);
098: if (idx == null)
099: idx = new Integer(0);
100: int i = idx.intValue();
101: if (Debug.verboseOn())
102: Debug.logVerbose(
103: "in LoopSubContentCache, prepCtx, i :" + i, module);
104: if (i >= lst.size()) {
105: return false;
106: }
107: GenericValue view = (GenericValue) lst.get(i);
108: GenericValue electronicText = null;
109: try {
110: electronicText = view.getRelatedOne("ElectronicText");
111: } catch (GenericEntityException e) {
112: throw new RuntimeException(e.getMessage());
113: }
114: if (Debug.verboseOn())
115: Debug
116: .logVerbose(
117: "in LoopSubContentCache, subContentDataResourceView contentId/drDataResourceId:"
118: + view.get("contentId")
119: + " / "
120: + view.get("drDataResourceId"),
121: module);
122:
123: String dataResourceId = (String) view.get("drDataResourceId");
124: if (Debug.verboseOn())
125: Debug.logVerbose(
126: "in LoopSubContentCache(0), dataResourceId ."
127: + dataResourceId, module);
128: String subContentIdSub = (String) view.get("contentId");
129: if (Debug.verboseOn())
130: Debug.logVerbose(
131: "in LoopSubContentCache(0), subContentIdSub ."
132: + subContentIdSub, module);
133: // This order is taken so that the dataResourceType can be overridden in the transform arguments.
134: String subDataResourceTypeId = (String) ctx
135: .get("subDataResourceTypeId");
136: if (UtilValidate.isEmpty(subDataResourceTypeId)) {
137: subDataResourceTypeId = (String) view
138: .get("drDataResourceTypeId");
139: // TODO: If this value is still empty then it is probably necessary to get a value from
140: // the parent context. But it will already have one and it is the same context that is
141: // being passed.
142: }
143: // This order is taken so that the mimeType can be overridden in the transform arguments.
144: String mimeTypeId = (String) ctx.get("mimeTypeId");
145: if (UtilValidate.isEmpty(mimeTypeId)) {
146: mimeTypeId = (String) view.get("mimeTypeId");
147: String parentContentId = (String) ctx.get("contentId");
148: if (UtilValidate.isEmpty(mimeTypeId)
149: && UtilValidate.isNotEmpty(parentContentId)) { // will need these below
150: try {
151: GenericValue parentContent = delegator
152: .findByPrimaryKey("Content",
153: UtilMisc.toMap("contentId",
154: parentContentId));
155: if (parentContent != null) {
156: mimeTypeId = (String) parentContent
157: .get("mimeTypeId");
158: ctx.put("parentContent", parentContent);
159: if (Debug.verboseOn())
160: Debug.logVerbose(
161: "in LoopSubContentCache, parentContentId: "
162: + parentContent
163: .get("contentId"),
164: module);
165: }
166: } catch (GenericEntityException e) {
167: throw new RuntimeException(e.getMessage());
168: }
169: }
170:
171: }
172: if (Debug.verboseOn())
173: Debug.logVerbose("in LoopSubContentCache(2), mimeTypeId."
174: + mimeTypeId, module);
175: if (Debug.verboseOn())
176: Debug.logVerbose(
177: "in LoopSubContentCache, subContentId/Sub."
178: + subContentIdSub, module);
179:
180: // This is what the FM template will see.
181: List passedGlobalNodeTrail = (List) ctx
182: .get("passedGlobalNodeTrail");
183: Debug.logInfo("passedGlobalNodeTrail(prepCtx):"
184: + passedGlobalNodeTrail, "");
185: List trail = new ArrayList(passedGlobalNodeTrail);
186: trail.add(FreeMarkerWorker.makeNode(view));
187: int indentSz = trail.size();
188: ctx.put("indent", new Integer(indentSz));
189: ctx.put("globalNodeTrail", trail);
190: Debug.logInfo("prepCtx, globalNodeTrail csv:"
191: + FreeMarkerWorker.nodeTrailToCsv((List) trail), "");
192: if (electronicText != null)
193: ctx.put("textData", electronicText.get("textData"));
194: else
195: ctx.put("textData", null);
196: ctx.put("entityIndex", new Integer(i + 1));
197: ctx.put("subContentId", subContentIdSub);
198: ctx.put("drDataResourceId", dataResourceId);
199: ctx.put("mimeTypeId", mimeTypeId);
200: ctx.put("dataResourceId", dataResourceId);
201: ctx.put("subContentIdSub", subContentIdSub);
202: ctx.put("subDataResourceTypeId", subDataResourceTypeId);
203: if (Debug.verboseOn())
204: Debug.logVerbose(FreeMarkerWorker.logMap(
205: "(L)end of prepCtx", ctx, 0), module);
206: return true;
207: }
208:
209: public Writer getWriter(final Writer out, Map args) {
210: final StringBuffer buf = new StringBuffer();
211: final Environment env = Environment.getCurrentEnvironment();
212: final Map templateCtx = (Map) FreeMarkerWorker
213: .getWrappedObject("context", env);
214: //FreeMarkerWorker.convertContext(templateCtx);
215: final GenericDelegator delegator = (GenericDelegator) FreeMarkerWorker
216: .getWrappedObject("delegator", env);
217: final HttpServletRequest request = (HttpServletRequest) FreeMarkerWorker
218: .getWrappedObject("request", env);
219: FreeMarkerWorker.getSiteParameters(request, templateCtx);
220: //templateCtx.put("buf", buf);
221: if (Debug.verboseOn())
222: Debug.logVerbose(FreeMarkerWorker.logMap("(L)before save",
223: templateCtx, 0), module);
224: final Map savedValues = FreeMarkerWorker.saveValues(
225: templateCtx, saveKeyNames);
226: if (Debug.verboseOn())
227: Debug
228: .logVerbose("(L-0)savedValues: " + savedValues,
229: module);
230: FreeMarkerWorker.overrideWithArgs(templateCtx, args);
231: if (Debug.verboseOn())
232: Debug.logVerbose(FreeMarkerWorker.logMap(
233: "(L)after overrride", templateCtx, 0), module);
234: String contentAssocTypeId = (String) templateCtx
235: .get("contentAssocTypeId");
236: if (UtilValidate.isEmpty(contentAssocTypeId)) {
237: contentAssocTypeId = "SUB_CONTENT";
238: templateCtx.put("contentAssocTypeId ", contentAssocTypeId);
239: }
240: List assocTypes = UtilMisc.toList(contentAssocTypeId);
241: templateCtx.put("assocTypes", assocTypes);
242: Locale locale = (Locale) templateCtx.get("locale");
243: if (locale == null) {
244: locale = Locale.getDefault();
245: templateCtx.put("locale", locale);
246: }
247:
248: String fromDateStr = (String) templateCtx.get("fromDateStr");
249: Timestamp fromDate = null;
250: if (UtilValidate.isNotEmpty(fromDateStr)) {
251: fromDate = UtilDateTime.toTimestamp(fromDateStr);
252: }
253: if (fromDate == null)
254: fromDate = UtilDateTime.nowTimestamp();
255: GenericValue view = null;
256:
257: String contentId = (String) templateCtx.get("contentId");
258: final String contentIdTo = contentId;
259: String subContentId = (String) templateCtx.get("subContentId");
260: String this ContentId = (String) templateCtx.get("contentId");
261: if (UtilValidate.isEmpty(this ContentId)) {
262: this ContentId = (String) templateCtx.get("subContentId");
263: }
264: List trail = (List) templateCtx.get("globalNodeTrail");
265: List passedGlobalNodeTrail = null;
266: if (trail != null && trail.size() > 0)
267: passedGlobalNodeTrail = new ArrayList(trail);
268: else
269: passedGlobalNodeTrail = new ArrayList();
270: if (UtilValidate.isNotEmpty(subContentId)
271: || UtilValidate.isNotEmpty(contentId)) {
272:
273: // Don't want to duplicate a node value
274: String passedContentId = null;
275: if (passedGlobalNodeTrail.size() > 0) {
276: Map nd = (Map) passedGlobalNodeTrail
277: .get(passedGlobalNodeTrail.size() - 1);
278: passedContentId = (String) nd.get("contentId");
279: }
280: if (UtilValidate.isNotEmpty(this ContentId)
281: && (UtilValidate.isEmpty(passedContentId) || !this ContentId
282: .equals(passedContentId))) {
283:
284: try {
285: view = delegator.findByPrimaryKeyCache("Content",
286: UtilMisc.toMap("contentId", this ContentId));
287: } catch (GenericEntityException e) {
288: Debug.logError(e, "Error getting sub-content",
289: module);
290: throw new RuntimeException(e.getMessage());
291: }
292: passedGlobalNodeTrail.add(FreeMarkerWorker
293: .makeNode(view));
294: }
295: }
296: Debug.logInfo("passedGlobalNodeTrail(write):"
297: + passedGlobalNodeTrail, "");
298: templateCtx.put("passedGlobalNodeTrail", passedGlobalNodeTrail);
299: templateCtx.put("contentId", null);
300: templateCtx.put("subContentId", null);
301:
302: String this MapKey = (String) templateCtx.get("mapKey");
303: Map results = null;
304: try {
305: results = ContentServicesComplex
306: .getAssocAndContentAndDataResourceCacheMethod(
307: delegator, this ContentId, this MapKey,
308: "From", fromDate, null, assocTypes, null);
309: } catch (MiniLangException e2) {
310: throw new RuntimeException(e2.getMessage());
311: } catch (GenericEntityException e) {
312: throw new RuntimeException(e.getMessage());
313: }
314: List longList = (List) results.get("entityList");
315: String viewSizeStr = (String) templateCtx.get("viewSize");
316: if (UtilValidate.isEmpty(viewSizeStr))
317: viewSizeStr = "10";
318: int viewSize = Integer.parseInt(viewSizeStr);
319: Debug.logInfo("viewSize:" + viewSize, "");
320: String viewIndexStr = (String) templateCtx.get("viewIndex");
321: Debug.logInfo("viewIndexStr:" + viewIndexStr, "");
322: if (UtilValidate.isEmpty(viewIndexStr))
323: viewIndexStr = "0";
324: int viewIndex = Integer.parseInt(viewIndexStr);
325: Debug.logInfo("viewIndex:" + viewIndex, "");
326: int lowIndex = viewIndex * viewSize;
327: Debug.logInfo("lowIndex:" + lowIndex, "");
328: int listSize = longList.size();
329: Debug.logInfo("listSize:" + listSize, "");
330: int highIndex = (viewIndex + 1) * viewSize;
331: if (highIndex > listSize)
332: highIndex = listSize;
333: Debug.logInfo("highIndex:" + highIndex, "");
334: Iterator it = longList.iterator();
335: List entityList = longList.subList(lowIndex, highIndex);
336: templateCtx.put("entityList", entityList);
337: templateCtx.put("viewIndex", Integer.toString(viewIndex));
338: templateCtx.put("viewSize", Integer.toString(viewSize));
339: templateCtx.put("lowIndex", Integer.toString(lowIndex));
340: templateCtx.put("highIndex", Integer.toString(highIndex));
341: templateCtx.put("listSize", Integer.toString(listSize));
342:
343: return new LoopWriter(out) {
344:
345: public void write(char cbuf[], int off, int len) {
346: buf.append(cbuf, off, len);
347: //StringBuffer ctxBuf = (StringBuffer) templateCtx.get("buf");
348: //ctxBuf.append(cbuf, off, len);
349: if (Debug.verboseOn())
350: Debug.logVerbose("in LoopSubContentCache, buf:"
351: + buf.toString(), module);
352: }
353:
354: public void flush() throws IOException {
355: out.flush();
356: }
357:
358: public int onStart() throws TemplateModelException,
359: IOException {
360: templateCtx.put("entityIndex", new Integer(0));
361: if (Debug.verboseOn())
362: Debug.logVerbose("in LoopSubContentCache, onStart",
363: module);
364: boolean inProgress = prepCtx(delegator, templateCtx);
365: if (Debug.verboseOn())
366: Debug.logVerbose(
367: "in LoopSubContentCache, onStart, inProgress:"
368: + inProgress, module);
369: if (inProgress) {
370: return TransformControl.EVALUATE_BODY;
371: } else {
372: return TransformControl.SKIP_BODY;
373: }
374: }
375:
376: public int afterBody() throws TemplateModelException,
377: IOException {
378: if (Debug.verboseOn())
379: Debug.logVerbose(
380: "in LoopSubContentCache, afterBody, start",
381: module);
382: if (Debug.verboseOn())
383: Debug.logVerbose(FreeMarkerWorker.logMap(
384: "(L)after body", templateCtx, 0), module);
385: Integer idx = (Integer) templateCtx.get("entityIndex");
386: if (Debug.verboseOn())
387: Debug.logVerbose(
388: "in LoopSubContentCache, prepCtx, idx :"
389: + idx, module);
390: int i = idx.intValue();
391: if (Debug.verboseOn())
392: Debug
393: .logVerbose(
394: "in LoopSubContentCache, afterBody, i:"
395: + i, module);
396: if (Debug.verboseOn())
397: Debug.logVerbose(
398: "in LoopSubContentCache, afterBody, templateCtx.entityIndex:"
399: + templateCtx.get("entityIndex"),
400: module);
401: if (Debug.verboseOn())
402: Debug.logVerbose("buf:" + buf.toString(), module);
403: boolean inProgress = prepCtx(delegator, templateCtx);
404: if (Debug.verboseOn())
405: Debug.logVerbose(
406: "in LoopSubContentCache, afterBody, inProgress:"
407: + inProgress + " inProgress:"
408: + inProgress, module);
409: //out.write(buf.toString());
410: //buf.setLength(0);
411: if (inProgress)
412: return TransformControl.REPEAT_EVALUATION;
413: else
414: return TransformControl.END_EVALUATION;
415: }
416:
417: public void close() throws IOException {
418:
419: String wrappedFTL = buf.toString();
420: if (Debug.verboseOn())
421: Debug.logVerbose(
422: "in LoopSubContentCache, wrappedFTL:"
423: + wrappedFTL, module);
424: String encloseWrappedText = (String) templateCtx
425: .get("encloseWrappedText");
426: if (UtilValidate.isEmpty(encloseWrappedText)
427: || encloseWrappedText.equalsIgnoreCase("false")) {
428: out.write(wrappedFTL);
429: wrappedFTL = ""; // So it won't get written again below.
430: }
431: String wrapTemplateId = (String) templateCtx
432: .get("wrapTemplateId");
433: if (Debug.verboseOn())
434: Debug.logVerbose(
435: "in LoopSubContentCache, wrapTemplateId:"
436: + wrapTemplateId, module);
437: if (UtilValidate.isNotEmpty(wrapTemplateId)) {
438: templateCtx.put("wrappedFTL", wrappedFTL);
439: templateCtx.put("contentIdTo", contentIdTo);
440: //if (Debug.verboseOn()) Debug.logVerbose("in LoopSubContentCache, rootDir:" + rootDir, module);
441:
442: Map templateRoot = FreeMarkerWorker
443: .createEnvironmentMap(env);
444:
445: templateRoot.put("wrapDataResourceTypeId",
446: templateCtx.get("subDataResourceTypeId"));
447: templateRoot.put("wrapContentIdTo", templateCtx
448: .get("contentId"));
449: templateRoot.put("wrapMimeTypeId", templateCtx
450: .get("mimeTypeId"));
451: templateRoot.put("context", templateCtx);
452:
453: Locale locale = (Locale) templateCtx.get("locale");
454: if (locale == null)
455: locale = Locale.getDefault();
456: String mimeTypeId = (String) templateCtx
457: .get("mimeTypeId");
458: if (Debug.verboseOn())
459: Debug.logVerbose(FreeMarkerWorker.logMap(
460: "(L)close middle", templateCtx, 0),
461: module);
462: try {
463: ContentWorker.renderContentAsTextCache(
464: delegator, wrapTemplateId, out,
465: templateRoot, null, locale, mimeTypeId);
466: } catch (GeneralException e) {
467: Debug.logError(e, "Error rendering content",
468: module);
469: throw new IOException("Error rendering content"
470: + e.toString());
471: }
472: if (Debug.verboseOn())
473: Debug.logVerbose(FreeMarkerWorker.logMap(
474: "(L)close middle(2)", templateCtx, 0),
475: module);
476: } else {
477: if (UtilValidate.isNotEmpty(wrappedFTL))
478: out.write(wrappedFTL);
479: }
480: if (Debug.verboseOn())
481: Debug
482: .logVerbose(
483: FreeMarkerWorker.logMap(
484: "(L)before remove",
485: templateCtx, 0), module);
486: FreeMarkerWorker.removeValues(templateCtx,
487: removeKeyNames);
488: if (Debug.verboseOn())
489: Debug.logVerbose(FreeMarkerWorker.logMap(
490: "(L)after remove", templateCtx, 0), module);
491: if (Debug.verboseOn())
492: Debug.logVerbose(
493: "(L-1)savedValues: " + savedValues, module);
494: FreeMarkerWorker.reloadValues(templateCtx, savedValues);
495: if (Debug.verboseOn())
496: Debug.logVerbose(FreeMarkerWorker.logMap(
497: "(L)after reload", templateCtx, 0), module);
498: }
499: };
500: }
501: }
|