001: /*******************************************************************************
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *******************************************************************************/package org.ofbiz.content.webapp.ftl;
019:
020: import java.io.IOException;
021: import java.io.Writer;
022: import java.sql.Timestamp;
023: import java.util.ArrayList;
024: import java.util.HashMap;
025: import java.util.List;
026: import java.util.Locale;
027: import java.util.Map;
028:
029: import javax.servlet.http.HttpServletRequest;
030:
031: import org.ofbiz.base.util.Debug;
032: import org.ofbiz.base.util.GeneralException;
033: import org.ofbiz.base.util.StringUtil;
034: import org.ofbiz.base.util.UtilDateTime;
035: import org.ofbiz.base.util.UtilValidate;
036: import org.ofbiz.base.util.template.FreeMarkerWorker;
037: import org.ofbiz.content.content.ContentServicesComplex;
038: import org.ofbiz.content.content.ContentWorker;
039: import org.ofbiz.entity.GenericDelegator;
040: import org.ofbiz.entity.GenericEntityException;
041: import org.ofbiz.entity.GenericValue;
042: import org.ofbiz.minilang.MiniLangException;
043: import org.ofbiz.webapp.ftl.LoopWriter;
044:
045: import freemarker.core.Environment;
046: import freemarker.template.TemplateModelException;
047: import freemarker.template.TemplateTransformModel;
048: import freemarker.template.TransformControl;
049:
050: /**
051: * LimitedSubContentCacheTransform - Freemarker Transform for URLs (links)
052: */
053: public class LimitedSubContentCacheTransform implements
054: TemplateTransformModel {
055:
056: public static final String module = LimitedSubContentCacheTransform.class
057: .getName();
058:
059: public static final String[] upSaveKeyNames = { "globalNodeTrail" };
060: public static final String[] saveKeyNames = { "contentId",
061: "subContentId", "entityList", "entityIndex",
062: "subDataResourceTypeId", "mimeTypeId", "whenMap", "locale",
063: "entityList", "viewSize", "viewIndex", "highIndex",
064: "lowIndex", "listSize", "wrapTemplateId",
065: "encloseWrapText", "nullThruDatesOnly", "globalNodeTrail",
066: "outputIndex" };
067:
068: /**
069: * A wrapper for the FreeMarkerWorker version.
070: */
071: public static Object getWrappedObject(String varName,
072: Environment env) {
073: return FreeMarkerWorker.getWrappedObject(varName, env);
074: }
075:
076: public static String getArg(Map args, String key, Environment env) {
077: return FreeMarkerWorker.getArg(args, key, env);
078: }
079:
080: public static String getArg(Map args, String key, Map ctx) {
081: return FreeMarkerWorker.getArg(args, key, ctx);
082: }
083:
084: public Writer getWriter(final Writer out, Map args) {
085: //Profiler.begin("Limited");
086: final StringBuffer buf = new StringBuffer();
087: final Environment env = Environment.getCurrentEnvironment();
088: //final Map templateRoot = (Map) FreeMarkerWorker.getWrappedObject("context", env);
089: final Map templateRoot = FreeMarkerWorker
090: .createEnvironmentMap(env);
091: //FreeMarkerWorker.convertContext(templateRoot);
092: final GenericDelegator delegator = (GenericDelegator) FreeMarkerWorker
093: .getWrappedObject("delegator", env);
094: final HttpServletRequest request = (HttpServletRequest) FreeMarkerWorker
095: .getWrappedObject("request", env);
096: FreeMarkerWorker.getSiteParameters(request, templateRoot);
097: //templateRoot.put("buf", buf);
098: final Map savedValuesUp = new HashMap();
099: FreeMarkerWorker.saveContextValues(templateRoot,
100: upSaveKeyNames, savedValuesUp);
101: final Map savedValues = new HashMap();
102: FreeMarkerWorker.overrideWithArgs(templateRoot, args);
103: String contentAssocTypeId = (String) templateRoot
104: .get("contentAssocTypeId");
105: final Map pickedEntityIds = new HashMap();
106: //if (UtilValidate.isEmpty(contentAssocTypeId)) {
107: //throw new RuntimeException("contentAssocTypeId is empty");
108: //}
109: List assocTypes = StringUtil.split(contentAssocTypeId, "|");
110:
111: String contentPurposeTypeId = (String) templateRoot
112: .get("contentPurposeTypeId");
113: List purposeTypes = StringUtil.split(contentPurposeTypeId, "|");
114: templateRoot.put("purposeTypes", purposeTypes);
115: Locale locale = (Locale) templateRoot.get("locale");
116: if (locale == null) {
117: locale = Locale.getDefault();
118: templateRoot.put("locale", locale);
119: }
120:
121: Map whenMap = new HashMap();
122: whenMap.put("followWhen", (String) templateRoot
123: .get("followWhen"));
124: whenMap.put("pickWhen", (String) templateRoot.get("pickWhen"));
125: whenMap.put("returnBeforePickWhen", (String) templateRoot
126: .get("returnBeforePickWhen"));
127: whenMap.put("returnAfterPickWhen", (String) templateRoot
128: .get("returnAfterPickWhen"));
129: templateRoot.put("whenMap", whenMap);
130:
131: String fromDateStr = (String) templateRoot.get("fromDateStr");
132: Timestamp fromDate = null;
133: if (UtilValidate.isNotEmpty(fromDateStr)) {
134: fromDate = UtilDateTime.toTimestamp(fromDateStr);
135: }
136: if (fromDate == null)
137: fromDate = UtilDateTime.nowTimestamp();
138:
139: String limitSize = (String) templateRoot.get("limitSize");
140: final int returnLimit = Integer.parseInt(limitSize);
141: // limitMode will be "random" to begin with
142: String limitMode = (String) templateRoot.get("limitMode");
143: final GenericValue userLogin = (GenericValue) FreeMarkerWorker
144: .getWrappedObject("userLogin", env);
145: List globalNodeTrail = (List) templateRoot
146: .get("globalNodeTrail");
147: String strNullThruDatesOnly = (String) templateRoot
148: .get("nullThruDatesOnly");
149: String orderBy = (String) templateRoot.get("orderBy");
150: Boolean nullThruDatesOnly = (strNullThruDatesOnly != null && strNullThruDatesOnly
151: .equalsIgnoreCase("true")) ? Boolean.TRUE
152: : Boolean.FALSE;
153: String contentId = (String) templateRoot.get("subContentId");
154:
155: templateRoot.put("contentId", null);
156: templateRoot.put("subContentId", null);
157:
158: final String contentIdTo = contentId;
159:
160: Map results = null;
161: //if (Debug.infoOn()) Debug.logInfo("in LimitedSubContentCache(0), assocTypes ." + assocTypes, module);
162: String contentAssocPredicateId = (String) templateRoot
163: .get("contentAssocPredicateId");
164: try {
165: results = ContentServicesComplex
166: .getAssocAndContentAndDataResourceCacheMethod(
167: delegator, contentId, null, "From",
168: fromDate, null, assocTypes, null,
169: Boolean.TRUE, contentAssocPredicateId,
170: orderBy);
171: } catch (MiniLangException e2) {
172: throw new RuntimeException(e2.getMessage());
173: } catch (GenericEntityException e) {
174: throw new RuntimeException(e.getMessage());
175: }
176: List longList = (List) results.get("entityList");
177: templateRoot.put("entityList", longList);
178: //if (Debug.infoOn()) Debug.logInfo("in limited, longList:" + longList , "");
179:
180: return new LoopWriter(out) {
181:
182: public void write(char cbuf[], int off, int len) {
183: buf.append(cbuf, off, len);
184: //StringBuffer ctxBuf = (StringBuffer) templateRoot.get("buf");
185: //ctxBuf.append(cbuf, off, len);
186: }
187:
188: public void flush() throws IOException {
189: out.flush();
190: }
191:
192: public int onStart() throws TemplateModelException,
193: IOException {
194:
195: List globalNodeTrail = (List) templateRoot
196: .get("globalNodeTrail");
197: String trailCsv = ContentWorker
198: .nodeTrailToCsv(globalNodeTrail);
199: boolean inProgress = false;
200: //if (Debug.infoOn()) Debug.logInfo("in limited, returnLimit:" + returnLimit , "");
201: //if (Debug.infoOn()) Debug.logInfo("in limited, pickedEntityIds:" + pickedEntityIds , "");
202: if (pickedEntityIds.size() < returnLimit) {
203: inProgress = getNextMatchingEntity(templateRoot,
204: delegator, env);
205: }
206: FreeMarkerWorker.saveContextValues(templateRoot,
207: saveKeyNames, savedValues);
208: if (inProgress) {
209: return TransformControl.EVALUATE_BODY;
210: } else {
211: return TransformControl.SKIP_BODY;
212: }
213: }
214:
215: public int afterBody() throws TemplateModelException,
216: IOException {
217: FreeMarkerWorker.reloadValues(templateRoot,
218: savedValues, env);
219: List list = (List) templateRoot.get("globalNodeTrail");
220: List subList = list.subList(0, list.size() - 1);
221: templateRoot.put("globalNodeTrail", subList);
222: env.setVariable("globalNodeTrail", FreeMarkerWorker
223: .autoWrap(subList, env));
224:
225: //if (Debug.infoOn()) Debug.logInfo("highIndex(2):" + highIndexInteger , "");
226: //if (Debug.infoOn()) Debug.logInfo("in limited, returnLimit(2):" + returnLimit , "");
227: //if (Debug.verboseOn()) Debug.logVerbose("in limited, pickedEntityIds(2):" + pickedEntityIds , "");
228: boolean inProgress = false;
229: if (pickedEntityIds.size() < returnLimit) {
230: inProgress = getNextMatchingEntity(templateRoot,
231: delegator, env);
232: }
233:
234: FreeMarkerWorker.saveContextValues(templateRoot,
235: saveKeyNames, savedValues);
236: if (inProgress) {
237: return TransformControl.REPEAT_EVALUATION;
238: } else {
239: return TransformControl.END_EVALUATION;
240: }
241: }
242:
243: public void close() throws IOException {
244: FreeMarkerWorker.reloadValues(templateRoot,
245: savedValuesUp, env);
246: String wrappedContent = buf.toString();
247: out.write(wrappedContent);
248: //try {
249: //Profiler.end("Limited");
250: //FileOutputStream fw = new FileOutputStream(new File("/usr/local/agi/ofbiz/hot-deploy/sfmp/misc/profile.data"));
251: //Profiler.print(fw);
252: //fw.close();
253: //} catch (IOException e) {
254: //Debug.logError("[PROFILER] " + e.getMessage(),"");
255: //}
256: }
257:
258: public boolean prepCtx(GenericDelegator delegator, Map ctx,
259: Environment env, GenericValue view)
260: throws GeneralException {
261:
262: String dataResourceId = (String) view
263: .get("drDataResourceId");
264: String subContentIdSub = (String) view.get("contentId");
265: // This order is taken so that the dataResourceType can be overridden in the transform arguments.
266: String subDataResourceTypeId = (String) ctx
267: .get("subDataResourceTypeId");
268: if (UtilValidate.isEmpty(subDataResourceTypeId)) {
269: subDataResourceTypeId = (String) view
270: .get("drDataResourceTypeId");
271: // TODO: If this value is still empty then it is probably necessary to get a value from
272: // the parent context. But it will already have one and it is the same context that is
273: // being passed.
274: }
275:
276: String mimeTypeId = ContentWorker.getMimeTypeId(
277: delegator, view, ctx);
278:
279: Map trailNode = ContentWorker.makeNode(view);
280: Map whenMap = (Map) ctx.get("whenMap");
281: Locale locale = (Locale) ctx.get("locale");
282: if (locale == null) {
283: locale = Locale.getDefault();
284: }
285: GenericValue assocContent = null;
286: ContentWorker.checkConditions(delegator, trailNode,
287: assocContent, whenMap);
288: Boolean isReturnBeforeObj = (Boolean) trailNode
289: .get("isReturnBefore");
290: Boolean isReturnAfterObj = (Boolean) trailNode
291: .get("isReturnAfter");
292: Boolean isPickObj = (Boolean) trailNode.get("isPick");
293: Boolean isFollowObj = (Boolean) trailNode
294: .get("isFollow");
295: //if (Debug.infoOn()) Debug.logInfo("in LimitedSubContentCache, isReturnBeforeObj" + isReturnBeforeObj + " isPickObj:" + isPickObj + " isFollowObj:" + isFollowObj + " isReturnAfterObj:" + isReturnAfterObj, module);
296: if ((isReturnBeforeObj == null || !isReturnBeforeObj
297: .booleanValue())
298: && ((isPickObj != null && isPickObj
299: .booleanValue()) || (isFollowObj != null && isFollowObj
300: .booleanValue()))) {
301: List globalNodeTrail = (List) ctx
302: .get("globalNodeTrail");
303: if (globalNodeTrail == null) {
304: globalNodeTrail = new ArrayList();
305: }
306: globalNodeTrail.add(trailNode);
307: ctx.put("globalNodeTrail", globalNodeTrail);
308: String csvTrail = ContentWorker
309: .nodeTrailToCsv(globalNodeTrail);
310: ctx.put("nodeTrailCsv", csvTrail);
311: //if (Debug.infoOn()) Debug.logInfo("prepCtx, csvTrail(2):" + csvTrail, "");
312: int indentSz = globalNodeTrail.size();
313: ctx.put("indent", new Integer(indentSz));
314:
315: ctx.put("subDataResourceTypeId",
316: subDataResourceTypeId);
317: ctx.put("mimeTypeId", mimeTypeId);
318: ctx.put("subContentId", subContentIdSub);
319: ctx.put("content", view);
320:
321: env.setVariable("subDataResourceTypeId",
322: FreeMarkerWorker.autoWrap(
323: subDataResourceTypeId, env));
324: env.setVariable("indent", FreeMarkerWorker
325: .autoWrap(new Integer(indentSz), env));
326: env.setVariable("nodeTrailCsv", FreeMarkerWorker
327: .autoWrap(csvTrail, env));
328: env.setVariable("globalNodeTrail", FreeMarkerWorker
329: .autoWrap(globalNodeTrail, env));
330: env.setVariable("content", FreeMarkerWorker
331: .autoWrap(view, env));
332: env.setVariable("mimeTypeId", FreeMarkerWorker
333: .autoWrap(mimeTypeId, env));
334: env.setVariable("subContentId", FreeMarkerWorker
335: .autoWrap(subContentIdSub, env));
336: return true;
337: } else {
338: return false;
339: }
340: }
341:
342: public GenericValue getRandomEntity() {
343:
344: GenericValue pickEntity = null;
345: List lst = (List) templateRoot.get("entityList");
346: if (Debug.verboseOn())
347: Debug.logVerbose("in limited, lst:" + lst, "");
348:
349: while (pickEntity == null && lst.size() > 0) {
350: double randomValue = Math.random();
351: //if (Debug.infoOn()) Debug.logInfo("in limited, randomValue:" + randomValue , "");
352: int idx = (int) (lst.size() * randomValue);
353: //if (Debug.infoOn()) Debug.logInfo("in limited, idx:" + idx , "");
354: pickEntity = (GenericValue) lst.get(idx);
355: String pickEntityId = pickEntity
356: .getString("contentId");
357: if (pickedEntityIds.get(pickEntityId) == null) {
358: pickedEntityIds.put(pickEntityId, pickEntity);
359: lst.remove(idx);
360: } else {
361: pickEntity = null;
362: }
363: }
364: return pickEntity;
365: }
366:
367: public boolean getNextMatchingEntity(Map templateRoot,
368: GenericDelegator delegator, Environment env)
369: throws IOException {
370: boolean matchFound = false;
371: GenericValue pickEntity = getRandomEntity();
372:
373: while (pickEntity != null && !matchFound) {
374: try {
375: matchFound = prepCtx(delegator, templateRoot,
376: env, pickEntity);
377: } catch (GeneralException e) {
378: throw new IOException(e.getMessage());
379: }
380: if (!matchFound)
381: pickEntity = getRandomEntity();
382: }
383: return matchFound;
384: }
385: };
386: }
387: }
|