/*******************************************************************************
* Copyright 2009, 2010 Innovation Gate GmbH. All Rights Reserved.
*
* This file is part of the OpenWGA server platform.
*
* OpenWGA is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, a special exception is granted by the copyright holders
* of OpenWGA called "OpenWGA plugin exception". You should have received
* a copy of this exception along with OpenWGA in file COPYING.
* If not, see <http://www.openwga.com/gpl-plugin-exception>.
*
* OpenWGA is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenWGA in file COPYING.
* If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package de.innovationgate.wgpublisher.webtml;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import de.innovationgate.utils.ObjectComparator;
import de.innovationgate.utils.PrefetchingIterator;
import de.innovationgate.utils.SkippingIterator;
import de.innovationgate.utils.WGUtils;
import de.innovationgate.webgate.api.WGAPIException;
import de.innovationgate.webgate.api.WGAbstractResultSetIterator;
import de.innovationgate.webgate.api.WGContent;
import de.innovationgate.webgate.api.WGContentNavigator;
import de.innovationgate.webgate.api.WGFactory;
import de.innovationgate.wgpublisher.expressions.ExpressionEngine;
import de.innovationgate.wgpublisher.expressions.ExpressionEngineFactory;
import de.innovationgate.wgpublisher.expressions.ExpressionResult;
import de.innovationgate.wgpublisher.lang.WebTMLLanguageChooser;
import de.innovationgate.wgpublisher.webtml.utils.ContentComparator;
import de.innovationgate.wgpublisher.webtml.utils.ExpressionComparator;
import de.innovationgate.wgpublisher.webtml.utils.IterationTagStatus;
import de.innovationgate.wgpublisher.webtml.utils.ResultIterator;
import de.innovationgate.wgpublisher.webtml.utils.ResultSetTagStatus;
import de.innovationgate.wgpublisher.webtml.utils.TMLContext;
import de.innovationgate.wgpublisher.webtml.utils.TMLException;
public class ForEach extends Base implements IterationTag {
public class FilterIterator extends PrefetchingIterator {
private Iterator _it;
private TMLContext _dummyContext;
private String _expression;
public FilterIterator(String expression, Iterator it) throws WGAPIException {
_it = it;
_expression = expression;
_dummyContext = getTMLContext().dbContext(getTMLContext().db());
}
@Override
protected Object fetchNextValue() {
try {
Object valueToReturn = null;
while(_it.hasNext()) {
Object currentValue = _it.next();
TMLContext filterContext = _dummyContext;
Map<String, Object> additionalObjects = new HashMap<String, Object>();
if (currentValue instanceof WGContent) {
filterContext = getTMLContext().context((WGContent) currentValue);
}
else {
additionalObjects.put("currentValue", currentValue);
}
ExpressionResult result = ExpressionEngineFactory.getTMLScriptEngine().evaluateExpression(_expression, filterContext, ExpressionEngine.TYPE_EXPRESSION, additionalObjects);
if (result.isTrue()) {
valueToReturn = currentValue;
break;
}
else if (result.isError()) {
getTMLContext().getlog().error("Error executing filter expression", result.getException());
addExpressionWarning(_expression, result);
}
}
return valueToReturn;
}
catch (WGAPIException e) {
throw new RuntimeException("Exception filtering values", e);
}
}
}
public class OnlyVisibleIterator extends WGAbstractResultSetIterator<WGContent> {
protected boolean _enhanced = false;
public OnlyVisibleIterator(ResultIterator<WGContent> it, boolean enhanced) {
super(it);
_enhanced = enhanced;
}
@Override
protected WGContent fetchContentForResult(WGContent result) throws WGAPIException {
return result;
}
@Override
protected boolean passesFilter(WGContent content) {
try {
return (!_enhanced || content.mayBePublished(getStatus().isBrowserInterface(), WGContent.DISPLAYTYPE_NONE));
}
catch (WGAPIException e) {
WGFactory.getLogger().error("Exception determining visibility state of " + content.getDocumentKey(), e);
return false;
}
}
}
public static final String TAGINFO_CURRENTPAGE = "currentpage";
public static final String TAGINFO_PAGES = "pages";
public static final String TAGINFO_CURRENTVALUE = "currentvalue";
public static final String TAGINFO_HASPREVIOUSPAGE= "haspreviouspage";
public static final String TAGINFO_HASNEXTPAGE= "hasnextpage";
public static final String TAGINFO_STARTINDEX = "startindex";
public static final String TAGINFO_ENDINDEX = "endindex";
public static final String TAGINFO_COUNT = "count";
// attributes
private String type;
private String item;
private String relationgroup;
private String count;
private String sourceTag;
private String pageSize;
private String page;
private String sortOrder;
private String sortExpression;
private String sortLanguage;
private String currentvalue;
private String filllastpage;
private String onlypublished;
private String linear;
private String sortmeta;
private String sortitem;
private String filter;
private String offset;
public static class Status extends BaseTagStatus implements IterationTagStatus {
int currentPage = 1;
int pages = 1;
int offset = 0;
int lastDisplayedRow = 0;
protected String forEachType;
Iterator resultIterator;
Object currentObject;
int resultSize = 0;
String contentLanguage = null;
Object _varOverriddenValue = null;
boolean _varOverridden = false;
int intPageSize = -1;
boolean endReached;
boolean onlyPublished;
public int baseOffset = 0;
/**
* @see IterationTag#hasNextPage()
*/
public boolean hasNextPage() {
if (this.currentPage < this.pages && !this.endReached) {
return true;
}
else {
return false;
}
}
/**
* @see IterationTag#hasPreviousPage()
*/
public boolean hasPreviousPage() {
if (this.currentPage > 1) {
return true;
}
else {
return false;
}
}
/**
* @see IterationTag#isLastIteration()
*/
public boolean isLastIteration() {
return !this.resultIterator.hasNext();
}
/**
* @see IterationTag#getIterationIndex()
*/
public int getIterationIndex() {
return this.iteration;
}
@Override
public Object getTagInfo(String name) throws WGAPIException {
if (name.equals(TAGINFO_CURRENTPAGE)) {
return new Integer(currentPage);
}
else if (name.equals(TAGINFO_PAGES)) {
return new Integer(pages);
}
else if (name.equals(TAGINFO_CURRENTVALUE)) {
return currentObject;
}
else if (name.equals(TAGINFO_HASNEXTPAGE)) {
return new Boolean(hasNextPage());
}
else if (name.equals(TAGINFO_HASPREVIOUSPAGE)) {
return new Boolean(hasPreviousPage());
}
else if (name.equals(TAGINFO_STARTINDEX)) {
if (resultSize > 0) {
return new Integer(offset + 1);
}
else {
return new Integer(0);
}
}
else if (name.equals(TAGINFO_ENDINDEX)) {
return new Integer(lastDisplayedRow);
}
else if (name.equals(TAGINFO_COUNT)) {
return new Integer(resultSize);
}
return super.getTagInfo(name);
}
@Override
public void initAttributeDelegates(Base tag) {
ForEach feTag = (ForEach) tag;
this.forEachType = feTag.getType();
// Autodetect some foreach types
if (this.forEachType == null) {
if (!WGUtils.isEmpty(feTag.getItem())) {
this.forEachType = "itemvalue";
}
else if (!WGUtils.isEmpty(feTag.getCount())) {
this.forEachType = "loop";
}
else {
this.forEachType = "content";
}
}
this.forEachType = this.forEachType.toLowerCase().trim();
this.onlyPublished = tag.stringToBoolean(feTag.getOnlypublished());
super.initAttributeDelegates(tag);
}
}
@Override
public BaseTagStatus createTagStatus() {
Status status = new Status();
return status;
}
public Status getStatus() {
return (Status) super.getStatus();
}
/**
* @throws WGAPIException
* @see Base#tmlStartTag(TMLContext)
*/
public void tmlStartTag() throws TMLException, WGAPIException {
Status status = (Status) getStatus();
// store tmlvariable with same name than currentvalue - used for restore in end tag
if (getCurrentvalue() != null && getTMLContext().hasVariable(getCurrentvalue())) {
status._varOverridden = true;
status._varOverriddenValue = getTMLContext().getvar(getCurrentvalue());
}
// Init private members
status.currentPage = 1;
status.pages = 1;
status.offset = 0;
status.baseOffset = 0;
status.resultSize = 0;
status.lastDisplayedRow = 0;
status.endReached = false;
status.resultIterator = null;
status.currentObject = null;
status.contentLanguage = null;
// Get base offset
String offsetStr = getOffset();
if (offsetStr != null) {
try {
status.baseOffset = Double.valueOf(offsetStr).intValue() - 1;
status.offset += status.baseOffset;
}
catch (NumberFormatException e) {
this.addWarning("Could not parse offset attribute as number: " + offsetStr);
}
}
// calculate page, pagesize and number of objects to display
status.intPageSize = -1;
String strPageSize = this.getPageSize();
if (strPageSize != null) {
try {
status.intPageSize = WGUtils.parseInt(strPageSize);
}
catch (NumberFormatException exc) {
this.addWarning("Could not parse pageSize as number: " + strPageSize, true);
return;
}
calcCurrentPage(status.intPageSize);
}
// get iteration items
ResultIterator objectIterator = retrieveResultIterator();
// If no objects retrieved, exit tag
if (objectIterator == null) {
this.setEvalBody(false);
return;
}
// sorting of entries - We must prefetch all contents here to be able to sort them in WebTML
String sortOrder = this.getSortorder();
if (sortOrder != null && !sortOrder.equals("none")) {
List<Object> objects = objectIterator.extractCompleteList();
if (!status.forEachType.equals("content")) {
java.util.Collections.sort(objects, new ObjectComparator(retrieveCollator()));
}
else {
contentSort(objects);
}
if (sortOrder.startsWith("desc")) {
Collections.reverse(objects);
}
objectIterator = new ResultIterator(objects);
}
// In case of type content wrap the iterator inside a FilterVisibleIterator() to filter out hidden docs
if (status.forEachType.equals("content")) {
OnlyVisibleIterator onlyVisibleIterator = new OnlyVisibleIterator(objectIterator, status.onlyPublished);
objectIterator = new ResultIterator(onlyVisibleIterator, objectIterator.getResultSize());
}
// In case of a filter condition wrap it into a filter iterator
String filterExpression = getFilter();
if (filterExpression != null) {
FilterIterator filterIterator = new FilterIterator(filterExpression, objectIterator);
objectIterator = new ResultIterator(filterIterator, objectIterator.getResultSize());
}
// Fill last page behaviour - Fetch the double pagesize and only use the last pageSize of docs of it. This should in most situations ensure that enough docs are retrieved
int realResultSize = objectIterator.getResultSize();
if (status.intPageSize > 0 && stringToBoolean(getFilllastpage())) {
int pageOffset = status.offset - status.baseOffset;
int goBack = (pageOffset >= status.intPageSize ? status.intPageSize : pageOffset);
int newOffset = status.offset - goBack;
objectIterator.proceedToOffset(newOffset, stringToBoolean(getLinear()));
List results = new ArrayList<Object>();
for (int docsToFetch = 1; docsToFetch <= goBack + status.intPageSize; docsToFetch++) {
if (!objectIterator.hasNext()) {
realResultSize = newOffset + (docsToFetch - 1);
break;
}
results.add(objectIterator.next());
}
List subList;
if (results.size() > status.intPageSize) {
int startIndex = results.size() - status.intPageSize;
subList = results.subList(startIndex, results.size());
status.offset = newOffset + startIndex;
}
else {
subList = results;
status.offset = newOffset;
}
objectIterator = new ResultIterator(subList.iterator(), realResultSize);
}
// Else proceed directly to offset
else {
objectIterator.proceedToOffset(status.offset, stringToBoolean(getLinear()));
}
status.resultIterator = objectIterator;
status.resultSize = realResultSize;
if (status.intPageSize > 0) {
status.pages = (int) Math.ceil((double) realResultSize / status.intPageSize);
status.lastDisplayedRow = status.offset + status.intPageSize;
}
else {
status.lastDisplayedRow = status.resultSize;
}
// Set system variables - compatibility to TML1
TMLContext context = this.getTMLContext();
try {
context.setvar("c_from", new Integer(status.offset + 1).toString(), false);
context.setvar("c_to", new Integer(status.lastDisplayedRow).toString());
context.setvar("c_total", new Integer(realResultSize).toString());
}
catch (WGAPIException e) {
this.addWarning("Unable to set system vars 'c_from', 'c_to', 'c_total': " + e.getMessage(), false);
this.getCore().getLog().error("Unable to set system vars 'c_from', 'c_to', 'c_total'", e);
}
// Set the first value
this.setEvalBody(this.proceedValues());
}
private ResultIterator retrieveResultIterator() throws TMLException, WGAPIException {
ResultIterator objectIterator = null;
Status status = (Status) getStatus();
if (status.forEachType.equals("content")) {
ResultSetTagStatus tag;
if (this.getSourcetag() != null) {
tag = (ResultSetTagStatus) this.getTagStatusById(this.getSourcetag(), ResultSetTagStatus.class);
if (tag == null) {
throw new TMLException("Could not find content list tag with id " + this.getSourcetag(), true);
}
}
else if (this.getRelationgroup() != null) {
String group = getRelationgroup();
status.contentLanguage = getTMLContext().content().getLanguage().getName();
return new ResultIterator(getTMLContext().content().getRelationsOfGroup(group));
}
else if (getStatus() instanceof ResultSetTagStatus) {
tag = (ResultSetTagStatus) getStatus();
}
else {
tag = (ResultSetTagStatus) getStatus().getAncestorTag(ResultSetTagStatus.class);
if (tag == null) {
throw new TMLException("No content list tag specified", true);
}
}
objectIterator = tag.getResultIterator();
status.contentLanguage = tag.getResultLanguage();
}
else if (status.forEachType.equals("loop") || status.forEachType.equals("level")) {
int count = 0;
if (status.forEachType.equals("loop")) {
String strCount = this.getCount();
if (strCount == null) {
throw new TMLException("Foreach with type loop but without attribute count", true);
}
count = stringToInteger(strCount, 0);
}
else if (status.forEachType.equals("level")) {
WGContentNavigator nav = new WGContentNavigator(null, new WebTMLLanguageChooser(getTMLContext().db(), getTMLContext()));
count = nav.getContentLevel(this.getTMLContext().content()).intValue();
}
List objects = new java.util.ArrayList();
for (int idx = 0; idx < count; idx++) {
objects.add(new Integer(idx + 1));
}
objectIterator = new ResultIterator(objects.iterator(), objects.size());
}
else if (status.forEachType.equals("itemvalue")) {
Object obj = this.getTMLContext().itemlist(this.getItem());
if (obj == null) {
throw new TMLException("Could not retrieve item " + this.getItem(), true);
}
if (obj instanceof List) {
objectIterator = new ResultIterator((java.util.List) obj);
}
else {
objectIterator = new ResultIterator(java.util.Collections.singletonList(obj));
}
}
else if (status.forEachType.equals("fieldvalue")) {
Object obj=null;
// Register with form parent (if present) and retrieve item values from it;
FormInputRegistrator form = (FormInputRegistrator) getStatus().getAncestorTag(FormBase.class);
if (form != null)
obj=form.getFieldValue(this.getItem(), false, "", false);
else obj = this.getTMLContext().itemlist(this.getItem());
if (obj == null) {
throw new TMLException("Could not retrieve item " + this.getItem(), true);
}
if (obj instanceof List) {
objectIterator = new ResultIterator((java.util.List) obj);
}
else {
objectIterator = new ResultIterator(java.util.Collections.singletonList(obj));
}
}
else if (status.forEachType.equals("tagresult")) {
if (this.getSourcetag() == null) {
throw new TMLException("No tag specified to take tagresult from", true);
}
BaseTagStatus tag = this.getTagStatusById(this.getSourcetag());
if (tag == null) {
throw new TMLException("Could not find tag with id " + this.getSourcetag(), true);
}
Object result = tag.result;
if (de.innovationgate.utils.WGUtils.isCollection(result)) {
objectIterator = new ResultIterator((java.util.Collection) result);
}
else {
objectIterator = new ResultIterator(java.util.Collections.singletonList(result));
}
}
else {
throw new TMLException("Unknown type for foreach tag: " + status.forEachType, true);
}
return objectIterator;
}
private void calcCurrentPage(int pageSize) {
Status status = (Status) getStatus();
// Page attribute
String strPage = this.getPage();
if (strPage != null && strPage!="") {
try {
status.currentPage = WGUtils.parseInt(strPage);
status.offset += pageSize * (status.currentPage - 1);
return;
}
catch (NumberFormatException exc) {
this.addWarning("Could not parse page attribute as number: " + strPage);
}
}
// WebTML-Variable
String currentPageParam = this.getId() + "Page";
try {
String varName = "$" + currentPageParam;
if (!getTMLContext().isempty(varName)) {
Object pageObj = getTMLContext().item(varName);
if (pageObj instanceof String) {
try {
status.currentPage = Integer.parseInt((String) pageObj);
status.offset += pageSize * (status.currentPage - 1);
return;
}
catch (NumberFormatException exc) {
this.addWarning("Could not parse page variable '" + varName + "' as number: " + String.valueOf(pageObj));
}
}
else if (pageObj instanceof Number) {
status.currentPage = ((Number) pageObj).intValue();
status.offset += pageSize * (status.currentPage - 1);
return;
}
else {
addWarning("Invalid data type for item '$" + currentPageParam + "' to specify foreach page: " + pageObj.getClass().getName());
}
}
}
catch (WGAPIException e) {
log.error("Error retrieving foreach page item '$" + status.currentPage + "'", e);
}
// URL-Parameter
strPage = this.pageContext.getRequest().getParameter(currentPageParam);
if (strPage != null) {
try {
status.currentPage = Integer.parseInt(strPage);
status.offset += pageSize * (status.currentPage - 1);
return;
}
catch (NumberFormatException exc) {
this.addWarning("Could not parse page url parameter as number: " + strPage);
}
}
}
private boolean proceedValues() throws WGAPIException {
Status status = (Status) getStatus();
if (status.intPageSize > 0 && (this.getIteration()+1) > status.intPageSize) {
return false;
}
if (status.resultIterator.hasNext()) {
status.currentObject = status.resultIterator.next();
try {
this.getTMLContext().setvar("index", new Integer(this.getIteration()), false);
}
catch (WGAPIException e) {
this.addWarning("Unable to set var 'index': " + e.getMessage(), false);
this.getCore().getLog().error("Unable to set var 'index'.", e);
}
if (status.currentObject instanceof WGContent) {
this.setChildTagContext(this.getTMLContextForDocument((WGContent) status.currentObject));
}
if (this.getCurrentvalue() != null) {
try {
this.getTMLContext().setvar(this.getCurrentvalue(), status.currentObject);
} catch (WGAPIException e) {
this.addWarning("Unable to set currentvalue to var '"+ this.getCurrentvalue() + "': " + e.getMessage(), false);
this.getCore().getLog().error("Unable to set currentvalue to var '"+ this.getCurrentvalue() + "'.", e);
}
}
return true;
}
else {
status.lastDisplayedRow = status.offset + getIteration();
status.resultSize = status.lastDisplayedRow;
status.pages = status.currentPage;
status.endReached = true;
return false;
}
}
/**
* Gets the count
* @return Returns a String
*/
public String getCount() {
return this.getTagAttributeValue("count", count, null);
}
/**
* Sets the count
* @param count The count to set
*/
public void setCount(String count) {
this.count = count;
}
/**
* Gets the item
* @return Returns a String
*/
public String getItem() {
return this.getTagAttributeValue("item", item, "");
}
/**
* Sets the item
* @param item The item to set
*/
public void setItem(String item) {
this.item = item;
}
/**
* Gets the pageSize
* @return Returns a String
*/
public String getPageSize() {
return this.getTagAttributeValue("pagesize", pageSize, null);
}
/**
* Sets the pageSize
* @param pageSize The pageSize to set
*/
public void setPagesize(String pageSize) {
this.pageSize = pageSize;
}
/**
* Gets the page
* @return Returns a String
*/
public String getPage() {
return this.getTagAttributeValue("page", page, null);
}
/**
* Sets the pageSize
* @param pageSize The pageSize to set
*/
public void setPage(String page) {
this.page = page;
}
/**
* Gets the type
* @return Returns a String
*/
public String getType() {
return this.getTagAttributeValue("type", type, null);
}
/**
* Sets the type
* @param type The type to set
*/
public void setType(String type) {
this.type = type;
}
/**
* Gets the sourceTag
* @return Returns a String
*/
public String getSourcetag() {
return this.getTagAttributeValue("sourcetag", sourceTag, null);
}
/**
* Sets the sourceTag
* @param sourceTag The sourceTag to set
*/
public void setSourcetag(String sourceTag) {
this.sourceTag = sourceTag;
}
/**
* @throws WGAPIException
* @see Base#tmlAfterBody(TMLContext)
*/
public void tmlAfterBody() throws TMLException, WGAPIException {
this.setEvalBody(this.proceedValues());
}
/**
* Gets the sortLanguage
* @return Returns a String
*/
public String getSortlanguage() {
return this.getTagAttributeValue("sortlanguage", sortLanguage, null);
}
public String getXplanguage() {
return this.getSortlanguage();
}
/**
* Sets the sortLanguage
* @param sortLanguage The sortLanguage to set
*/
public void setSortlanguage(String sortLanguage) {
this.sortLanguage = sortLanguage;
}
public void setXplanguage(String sortLanguage) {
this.setSortlanguage(sortLanguage);
}
/**
* Gets the sortExpression
* @return Returns a String
*/
public String getSortexpression() {
return this.getTagAttributeValue("sortexpression", sortExpression, null);
}
/**
* Sets the sortExpression
* @param sortExpression The sortExpression to set
*/
public void setSortexpression(String sortExpression) {
this.sortExpression = sortExpression;
}
/**
* Gets the sortOrder
* @return Returns a String
*/
public String getSortorder() {
return this.getTagAttributeValue("sortorder", sortOrder, null);
}
/**
* Sets the sortOrder
* @param sortOrder The sortOrder to set
*/
public void setSortorder(String sortOrder) {
this.sortOrder = sortOrder;
}
/**
* @see Base#tmlInitBody()
*/
public void tmlInitBody() throws TMLException {
Status status = (Status) getStatus();
try {
this.getTMLContext().setvar("index", new Integer(this.getIteration()), false);
if (this.getCurrentvalue() != null) {
this.getTMLContext().setvar(this.getCurrentvalue(), status.currentObject);
}
} catch (WGAPIException e) {
this.addWarning("Unable to init body. Setting var 'index' or currentvalue to var '"+ this.getCurrentvalue() + "' failed: " + e.getMessage(), false);
this.getCore().getLog().error("Unable to init body. Setting var 'index' or currentvalue to var '"+ this.getCurrentvalue() + "' failed.", e);
}
}
/**
* Gets the currentvalue
* @return Returns a String
*/
public String getCurrentvalue() {
return this.getTagAttributeValue("currentvalue", currentvalue, null);
}
/**
* Sets the currentvalue
* @param currentvalue The currentvalue to set
*/
public void setCurrentvalue(String currentvalue) {
this.currentvalue = currentvalue;
}
/**
* @throws WGAPIException
* @see de.innovationgate.wgpublisher.webtml.Base#tmlEndTag()
*/
public void tmlEndTag() throws TMLException, WGAPIException {
super.tmlEndTag();
Status status = (Status) getStatus();
status.currentObject = null;
status.resultIterator = null;
// restore tmlvariable with same name than currentvalue
if (getCurrentvalue() != null) {
if (status._varOverridden) {
getTMLContext().setvar(getCurrentvalue(), status._varOverriddenValue);
} else {
getTMLContext().removevar(getCurrentvalue());
}
}
}
/**
* Returns the filllastpage.
* @return String
*/
public String getFilllastpage() {
return this.getTagAttributeValue("filllastpage", filllastpage, "true");
}
/**
* Sets the filllastpage.
* @param filllastpage The filllastpage to set
*/
public void setFilllastpage(String filllastpage) {
this.filllastpage = filllastpage;
}
/**
* @param string
*/
public void setSortmeta(String string) {
sortmeta = string;
} /**
* @param string
*/
public void setSortitem(String string) {
sortitem = string;
} /**
* @return
*/
public String getSortmeta() {
return getTagAttributeValue("sortmeta", sortmeta, null);
} /**
* @return
*/
public String getSortitem() {
return getTagAttributeValue("sortitem", sortitem, null);
}
private void contentSort(List<Object> objects) {
// Determine collator based on content language
Collator collator = retrieveCollator();
Comparator comparator = null;
// Sort by expression
String sortExpression = getSortexpression();
if (sortExpression != null) {
de.innovationgate.wgpublisher.expressions.ExpressionEngine engine = null;
if (this.getSortlanguage() != null) {
engine = de.innovationgate.wgpublisher.expressions.ExpressionEngineFactory.getEngine(this.getSortlanguage());
}
comparator = new ExpressionComparator(this, engine, sortExpression, collator);
}
// Sort by item
String sortItem = getSortitem();
if (sortItem != null) {
comparator = new ContentComparator(this, false, sortItem, collator);
}
// Sort by meta
String sortMeta = getSortmeta();
if (sortMeta != null) {
comparator = new ContentComparator(this, true, sortMeta, collator);
}
if (comparator != null) {
java.util.Collections.sort(objects, comparator);
}
else {
addWarning("Unable to sort content because no sort item/meta/expression was specified", false);
}
}
private Collator retrieveCollator() {
Status status = (Status) getStatus();
Collator collator;
if (status.contentLanguage != null && status.contentLanguage != ResultSetTagStatus.MULTILANGUAGE_RESULT) {
collator = Collator.getInstance(getCore().languageCodeToLocale(status.contentLanguage));
}
else {
collator = Collator.getInstance(getTMLContext().getPreferredLanguageLocale());
}
return collator;
}
public String getOnlypublished() {
return getTagAttributeValue("onlypublished", onlypublished, "true");
}
public void setOnlypublished(String onlypublished) {
this.onlypublished = onlypublished;
}
public String getLinear() {
return getTagAttributeValue("linear", linear, "false");
}
public void setLinear(String linear) {
this.linear = linear;
}
public String getFilter() {
return getTagAttributeValue("filter", filter, null);
}
public void setFilter(String filter) {
this.filter = filter;
}
public String getRelationgroup() {
return getTagAttributeValue("group", relationgroup, null);
}
public void setRelationgroup(String group) {
this.relationgroup = group;
}
public String getOffset() {
return getTagAttributeValue("offset", offset, null);
}
public void setOffset(String offset) {
this.offset = offset;
}}