/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* FenixEdu Academic 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.ui.renderers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.fenixedu.academic.domain.CompetenceCourse;
import org.fenixedu.academic.domain.Department;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.degreeStructure.CurricularStage;
import org.fenixedu.academic.domain.organizationalStructure.CompetenceCourseGroupUnit;
import org.fenixedu.academic.domain.organizationalStructure.DepartmentUnit;
import org.fenixedu.academic.domain.organizationalStructure.ScientificAreaUnit;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import pt.ist.fenixWebFramework.renderers.CollectionRenderer.TableLink;
import pt.ist.fenixWebFramework.renderers.OutputRenderer;
import pt.ist.fenixWebFramework.renderers.components.Face;
import pt.ist.fenixWebFramework.renderers.components.HtmlBlockContainer;
import pt.ist.fenixWebFramework.renderers.components.HtmlComponent;
import pt.ist.fenixWebFramework.renderers.components.HtmlInlineContainer;
import pt.ist.fenixWebFramework.renderers.components.HtmlList;
import pt.ist.fenixWebFramework.renderers.components.HtmlListItem;
import pt.ist.fenixWebFramework.renderers.components.HtmlTable;
import pt.ist.fenixWebFramework.renderers.components.HtmlTableCell;
import pt.ist.fenixWebFramework.renderers.components.HtmlTableRow;
import pt.ist.fenixWebFramework.renderers.components.HtmlText;
import pt.ist.fenixWebFramework.renderers.layouts.Layout;
import pt.ist.fenixWebFramework.renderers.utils.RenderUtils;
public class CompetenceCourseVersionList extends OutputRenderer {
private String approvedClass;
private String draftClass;
private String publishedClass;
private String tableClasses;
private String scientificAreaNameClasses;
private String groupNameClasses;
private String courseNameClasses;
private String filterBy;
private final Map<String, TableLink> links;
private final List<TableLink> sortedLinks;
private boolean groupLinks;
private String linkGroupSeparator;
private boolean showOldCompetenceCourses;
private String messageClass;
public String getFilterBy() {
return filterBy;
}
public void setFilterBy(String filterBy) {
this.filterBy = filterBy;
}
public String getCourseNameClasses() {
return courseNameClasses;
}
public void setCourseNameClasses(String courseNameClasses) {
this.courseNameClasses = courseNameClasses;
}
public String getScientificAreaNameClasses() {
return scientificAreaNameClasses;
}
public void setScientificAreaNameClasses(String scientificAreaNameClasses) {
this.scientificAreaNameClasses = scientificAreaNameClasses;
}
public String getTableClasses() {
return tableClasses;
}
public void setTableClasses(String tableClasses) {
this.tableClasses = tableClasses;
}
public String getApprovedClass() {
return approvedClass;
}
public void setApprovedClass(String approvedClass) {
this.approvedClass = approvedClass;
}
public String getDraftClass() {
return draftClass;
}
public void setDraftClass(String draftClass) {
this.draftClass = draftClass;
}
public String getMessageClass() {
return messageClass;
}
public void setMessageClass(String messageClass) {
this.messageClass = messageClass;
}
public String getPublishedClass() {
return publishedClass;
}
public void setPublishedClass(String publishedClass) {
this.publishedClass = publishedClass;
}
private TableLink getTableLink(String name) {
TableLink tableLink = this.links.get(name);
if (tableLink == null) {
tableLink = new TableLink(name);
this.links.put(name, tableLink);
this.sortedLinks.add(tableLink);
}
return tableLink;
}
private TableLink getTableLink(int order) {
Collections.sort(this.sortedLinks);
return this.sortedLinks.get(order);
}
public String getLink(String name) {
return getTableLink(name).getLink();
}
/**
* The link property indicates the page to were the control link will point.
* All params will be appended to this link.
*
*/
public void setLink(String name, String value) {
getTableLink(name).setLink(value);
}
public String getModule(String name) {
return getTableLink(name).getModule();
}
/**
* By default the link property will be mapped to the current module. You
* can override that with this property.
*
*/
public void setModule(String name, String value) {
getTableLink(name).setModule(value);
}
public String getParam(String name) {
return getTableLink(name).getParam();
}
/**
* The <code>param</code> property allows you to indicate will values of the
* object shown in a given row should be used to configure the link
* specified.
*
* <p>
* Imagine you want to add and link that sends you to a page were you can edit the object. The link forwards to an action and
* that action needs to know which is the object you want ot edit. Supposing that each object as an <code>id</code> you may
* have a configuration similar to:
*
* <pre>
* link(edit) = "/edit.do"
* param(edit) = "id"
* </pre>
*
* The result will be a link that will point to <code><module>/edit.do?id=<object id></code> were the id param
* will be different for each object shown in the table.
*
* <p>
* The <code>param</code> property supports two more features. It allows you to choose the name of the link parameter and
* explicitly give new parameters. You can specify several parameters by separating the with a comma. The full syntax of the
* <code>param</code> property is:
*
* <pre>
* <slot>[/<name>]?[=<value>]?
* </pre>
*
* <dl>
* <dt><code>slot</code></dt>
* <dd>specifies the name of the object's slot from were the value will be retrieved. In the example above each object needed
* to have a <code>getId()</code> method.</dd>
*
* <dt><code>name</code></dt>
* <dd>specifies the name of the parameters that will appended to the link. If this parts is not given the slot name will be
* used.</dd>
*
* <dt><code>value</code></dt>
* <dd>allows you to override the value of the parameters. If you specify this part then <code>slot</code> does not need to be
* a real slot of the object.</dd>
* </dl>
*
*/
public void setParam(String name, String value) {
getTableLink(name).setParam(value);
}
public String getKey(String name) {
return getTableLink(name).getKey();
}
/**
* The resource key that will be used to find the link name, that is, the
* name that will appear in the table.
*
*/
public void setKey(String name, String value) {
getTableLink(name).setKey(value);
}
public String getBundle(String name) {
return getTableLink(name).getBundle();
}
/**
* If the module's default bundle is not to be used you can indicate the
* alternative bundle with this property.
*
*/
public void setBundle(String name, String value) {
getTableLink(name).setBundle(value);
}
public String getText(String name) {
return getTableLink(name).getText();
}
/**
* An alternative to the {@link #setKey(String, String) key} property is
* specifying the text to appear directly. Oviously this approach does not
* work well with internationalized interfaces.
*
*/
public void setText(String name, String value) {
getTableLink(name).setText(value);
}
public String getOrder(String name) {
return getTableLink(name).getOrder();
}
/**
* As the container make no guarantees about the order properties are set in
* the implementation we can't rely on the order links appear defined in the
* page. You can use this attribute to explicitly indicate the order link
* should appear. The value is not important and it's only used for an
* alfabethic comparison. Both the following examples indicate that the
* links should appear in the order: a, c, b.
* <p>
* Example 1:
*
* <pre>
* order(a) = "1"
* order(b) = "3"
* order(c) = "2"
* </pre>
*
* <p>
* Example 2:
*
* <pre>
* order(a) = "first"
* order(b) = "second"
* order(c) = "third"
* </pre>
*
*/
public void setOrder(String name, String value) {
getTableLink(name).setOrder(value);
}
public boolean isExcludedFromFirst(String name) {
return getTableLink(name).isExcludeFromFirst();
}
/**
* This property allows you to exclude a control link from appearing in the
* first line of the generated table.
*
*/
public void setExcludedFromFirst(String name, String value) {
getTableLink(name).setExcludeFromFirst(new Boolean(value));
}
public boolean isExcludedFromLast(String name) {
return getTableLink(name).isExcludeFromLast();
}
/**
* Specifies the name of the property that will consulted to determine if
* the link should be visible or not. By default all links are visible.
* <p>
* This can be used to have some links that depend on domain logic.
*
*/
public void setVisibleIf(String name, String value) {
getTableLink(name).setVisibleIf(value);
}
public String getVisibleIf(String name) {
return getTableLink(name).getVisibleIf();
}
/**
* This property does the same work as visibleIf but does the opposite
* logic. If <code>true</code> then the link will not be shown.
*
*/
public void setVisibleIfNot(String name, String value) {
getTableLink(name).setVisibleIfNot(value);
}
public String getVisibleIfNot(String name) {
return getTableLink(name).getVisibleIfNot();
}
/**
* This property allows you to exclude a control link from appearing in the
* last line of the generated table.
*
*/
public void setExcludedFromLast(String name, String value) {
getTableLink(name).setExcludeFromLast(new Boolean(value));
}
public boolean isGroupLinks() {
return groupLinks;
}
/**
* Specifies if the control links ares grouped in a single cell of the
* table. The linkGroupSeparator will be used to separate the control links.
*
*/
public void setGroupLinks(boolean groupLinks) {
this.groupLinks = groupLinks;
}
public String getLinkGroupSeparator() {
return linkGroupSeparator;
}
/**
* Specifies the separator between links when these are grouped
*
*/
public void setLinkGroupSeparator(String linkGroupSeparator) {
this.linkGroupSeparator = linkGroupSeparator;
}
public boolean isShowOldCompetenceCourses() {
return showOldCompetenceCourses;
}
/**
* Indicates whether or not to show old competence courses
*
*/
public void setShowOldCompetenceCourses(boolean showOldCompetenceCourses) {
this.showOldCompetenceCourses = showOldCompetenceCourses;
}
public String getLinkFormat(String name) {
return getTableLink(name).getLinkFormat();
}
/**
* The linkFormat property indicates the format of the control link. The
* params should be inserted in format. When this property is set, the link
* and param properties are ignored
*
* <p>
* Example 1:
*
* <pre>
* someAction.do?method=viewDetails&externalId=${externalId}
* </pre>
*
* <p>
* Example 2:
*
* <pre>
* someAction/${someProperty}/${otherProperty}
* </pre>
*
*/
public void setLinkFormat(String name, String value) {
getTableLink(name).setLinkFormat(value);
}
public String getCustomLink(String name) {
return getTableLink(name).getCustom();
}
/**
* If this property is specified all the others are ignored. This property
* allows you to specify the exact content to show as a link. Then content
* will be parsed with the same rules that apply to {@link #setLinkFormat(String, String) linkFormat}.
*
*/
public void setCustomLink(String name, String value) {
getTableLink(name).setCustom(value);
}
public String getContextRelative(String name) {
return Boolean.toString(getTableLink(name).isContextRelative());
}
/**
* The contextRelative property indicates if the specified link is relative
* to the current context or is an external link (e.g.
* https://anotherserver.com/anotherScript)
*
*/
public void setContextRelative(String name, String value) {
getTableLink(name).setContextRelative(Boolean.parseBoolean(value));
}
public CompetenceCourseVersionList() {
this.links = new Hashtable<String, TableLink>();
this.sortedLinks = new ArrayList<TableLink>();
}
@Override
protected Layout getLayout(Object object, Class type) {
return new ComputerCourseVersionLayout();
}
private class ComputerCourseVersionLayout extends Layout {
private static final String CAPTION_CLASSES = "mtop15 mbottom05";
private boolean futureDepartmentMessageShown = false;
private boolean futureGroupMessageShown = false;
private boolean futureTransferMessageShown = false;
private boolean oldDepartmentMessageShown = false;
private void setFutureDepartmentMessageShown(boolean futureDepartmentMessageShown) {
this.futureDepartmentMessageShown = futureDepartmentMessageShown;
}
private boolean isFutureDepartmentMessageShown() {
return futureDepartmentMessageShown;
}
private void setFutureGroupMessageShown(boolean futureGroupMessageShown) {
this.futureGroupMessageShown = futureGroupMessageShown;
}
private boolean isFutureGroupMessageShown() {
return futureGroupMessageShown;
}
private void setFutureTransferMessageShown(boolean futureTransferMessageShown) {
this.futureTransferMessageShown = futureTransferMessageShown;
}
private boolean isFutureTransferMessageShown() {
return futureTransferMessageShown;
}
private void setOldDepartmentMessageShown(boolean oldDepartmentMessageShown) {
this.oldDepartmentMessageShown = oldDepartmentMessageShown;
}
private boolean isOldDepartmentMessageShown() {
return oldDepartmentMessageShown;
}
@Override
public HtmlComponent createComponent(Object object, Class type) {
Department department = (Department) object;
HtmlBlockContainer listContainer = new HtmlBlockContainer();
for (ScientificAreaUnit scientificArea : department.getDepartmentUnit().getScientificAreaUnits()) {
HtmlText areaName = new HtmlText(scientificArea.getNameI18n().getContent());
if (getScientificAreaNameClasses() != null) {
areaName.setClasses(getScientificAreaNameClasses());
}
HtmlList list = new HtmlList();
CurricularStage stage = null;
if (getFilterBy() != null) {
stage = CurricularStage.valueOf(getFilterBy());
}
for (CompetenceCourseGroupUnit group : scientificArea.getCompetenceCourseGroupUnits()) {
HtmlListItem item = list.createItem();
HtmlBlockContainer courseContainer = new HtmlBlockContainer();
HtmlText groupName = new HtmlText(group.getPresentationName());
if (getGroupNameClasses() != null) {
groupName.setClasses(getGroupNameClasses());
}
courseContainer.addChild(groupName);
HtmlTable table = new HtmlTable();
for (CompetenceCourse course : group.getCurrentOrFutureCompetenceCourses()) {
if (course.getCurricularStage().equals(stage)) {
HtmlTableRow courseRow = table.createRow();
HtmlComponent coursePresentation =
getCurrentOrFutureCoursePresentation(course, group, department.getDepartmentUnit());
if (getCourseNameClasses() != null) {
coursePresentation.setClasses(getCourseNameClasses());
}
courseRow.createCell().setBody(coursePresentation);
HtmlTableCell cell = courseRow.createCell();
cell.setBody(getLinks(course));
cell.setClasses("aright");
}
}
if (isShowOldCompetenceCourses()) {
for (CompetenceCourse course : group.getOldCompetenceCourses()) {
if (course.getCurricularStage().equals(stage)) {
HtmlTableRow courseRow = table.createRow();
HtmlComponent coursePresentation = getOldCoursePresentation(course);
if (getCourseNameClasses() != null) {
coursePresentation.setClasses(getCourseNameClasses());
}
courseRow.createCell().setBody(coursePresentation);
HtmlTableCell cell = courseRow.createCell();
cell.setBody(getLinks(course));
cell.setClasses("aright");
}
}
}
courseContainer.addChild(table);
if (getTableClasses() != null) {
table.setClasses(getTableClasses());
}
item.setBody(courseContainer);
}
listContainer.addChild(areaName);
listContainer.addChild(list);
}
HtmlBlockContainer container = new HtmlBlockContainer();
container.addChild(getCaptionPresentation());
container.addChild(listContainer);
return container;
}
protected HtmlComponent getLinks(CompetenceCourse course) {
HtmlInlineContainer container = new HtmlInlineContainer();
int total = sortedLinks.size();
for (int i = 0; i < total; i++) {
TableLink tableLink = getTableLink(i);
container.addChild(tableLink.generateLink(course));
if (i + 1 < total) {
container.addChild(new HtmlText(getLinkGroupSeparator()));
}
}
container.setIndented(false);
return container;
}
private HtmlComponent getCurrentOrFutureCoursePresentation(CompetenceCourse course, CompetenceCourseGroupUnit group,
DepartmentUnit department) {
HtmlInlineContainer container = new HtmlInlineContainer();
if (!StringUtils.isEmpty(course.getCode())) {
container.addChild(new HtmlText(course.getCode()));
container.addChild(new HtmlText(" - "));
}
container.addChild(new HtmlText(course.getName()));
container.addChild(new HtmlText(" ("));
container.addChild(new HtmlText(course.getAcronym()));
container.addChild(new HtmlText(") "));
container.addChild(getStage(course.getCurricularStage()));
if (course.getCompetenceCourseGroupUnit() != group) {
container.addChild(new HtmlText(" ("));
container.addChild(getFutureTransferMessage(course));
container.addChild(new HtmlText(") "));
} else if (course.getDepartmentUnit(ExecutionSemester.readLastExecutionSemester()) != department) {
container.addChild(new HtmlText(" ("));
container.addChild(getFutureDepartmentMessage(course));
container.addChild(new HtmlText(") "));
} else if (course.getCompetenceCourseGroupUnit(ExecutionSemester.readLastExecutionSemester()) != group) {
container.addChild(new HtmlText(" ("));
container.addChild(getFutureGroupMessage(course));
container.addChild(new HtmlText(") "));
}
container.setIndented(false);
return container;
}
private HtmlComponent getFutureDepartmentMessage(CompetenceCourse course) {
setFutureDepartmentMessageShown(true);
HtmlText text =
new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.department") + ": "
+ course.getDepartmentUnit(ExecutionSemester.readLastExecutionSemester()).getAcronym());
text.setClasses(getMessageClass());
return text;
}
private HtmlComponent getFutureGroupMessage(CompetenceCourse course) {
setFutureGroupMessageShown(true);
HtmlText text =
new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.group") + ": "
+ course.getCompetenceCourseGroupUnit(ExecutionSemester.readLastExecutionSemester()).getName());
text.setClasses(getMessageClass());
return text;
}
private HtmlComponent getFutureTransferMessage(CompetenceCourse course) {
setFutureTransferMessageShown(true);
HtmlText text = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.transfer"));
text.setClasses(getMessageClass());
return text;
}
private HtmlComponent getOldCoursePresentation(CompetenceCourse course) {
HtmlInlineContainer container = new HtmlInlineContainer();
if (!StringUtils.isEmpty(course.getCode())) {
container.addChild(new HtmlText(course.getCode()));
container.addChild(new HtmlText(" - "));
}
container.addChild(new HtmlText(course.getName()));
container.addChild(new HtmlText(" ("));
container.addChild(new HtmlText(course.getAcronym()));
container.addChild(new HtmlText(") "));
container.addChild(getStage(course.getCurricularStage()));
container.addChild(new HtmlText(" ("));
container.addChild(getOldDepartmentMessage(course));
container.addChild(new HtmlText(")"));
container.setIndented(false);
return container;
}
private HtmlComponent getOldDepartmentMessage(CompetenceCourse course) {
setOldDepartmentMessageShown(true);
HtmlText text =
new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "current.department") + ": "
+ course.getDepartmentUnit().getAcronym());
text.setClasses(getMessageClass());
return text;
}
private HtmlComponent getCaptionPresentation() {
HtmlBlockContainer container = new HtmlBlockContainer();
if (isFutureDepartmentMessageShown() || isFutureGroupMessageShown() || isFutureTransferMessageShown()
|| isOldDepartmentMessageShown()) {
HtmlText caption = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "caption"));
caption.setClasses(CAPTION_CLASSES);
caption.setFace(Face.STRONG);
container.addChild(caption);
HtmlList list = new HtmlList();
if (isOldDepartmentMessageShown()) {
HtmlListItem item = list.createItem();
HtmlInlineContainer messageLine = new HtmlInlineContainer();
HtmlText message = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "current.department") + ":");
message.setFace(Face.EMPHASIS);
messageLine.addChild(message);
messageLine.addChild(new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "current.department.caption")));
item.addChild(messageLine);
}
if (isFutureDepartmentMessageShown()) {
HtmlListItem item = list.createItem();
HtmlInlineContainer messageLine = new HtmlInlineContainer();
HtmlText message = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.department") + ":");
message.setFace(Face.EMPHASIS);
messageLine.addChild(message);
messageLine.addChild(new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.department.caption")));
item.addChild(messageLine);
}
if (isFutureGroupMessageShown()) {
HtmlListItem item = list.createItem();
HtmlInlineContainer messageLine = new HtmlInlineContainer();
HtmlText message = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.group") + ":");
message.setFace(Face.EMPHASIS);
messageLine.addChild(message);
messageLine.addChild(new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.group.caption")));
item.addChild(messageLine);
}
if (isFutureTransferMessageShown()) {
HtmlListItem item = list.createItem();
HtmlInlineContainer messageLine = new HtmlInlineContainer();
HtmlText message = new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.transfer") + ":");
message.setFace(Face.EMPHASIS);
messageLine.addChild(message);
messageLine.addChild(new HtmlText(BundleUtil.getString(Bundle.BOLONHA, "future.transfer.caption")));
item.addChild(messageLine);
}
container.addChild(list);
}
return container;
}
private HtmlComponent getStage(CurricularStage curricularStage) {
HtmlText text = new HtmlText(RenderUtils.getEnumString(curricularStage));
switch (curricularStage) {
case DRAFT:
text.setClasses(getDraftClass());
break;
case PUBLISHED:
text.setClasses(getPublishedClass());
break;
case APPROVED:
text.setClasses(getApprovedClass());
break;
}
return text;
}
}
public String getGroupNameClasses() {
return groupNameClasses;
}
public void setGroupNameClasses(String groupNameClasses) {
this.groupNameClasses = groupNameClasses;
}
}