diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeForm.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeForm.java
new file mode 100644
index 0000000..8a11f76
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeForm.java
@@ -0,0 +1,68 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.assets.ItemSearchWidget;
+import com.arsdigita.cms.ui.authoring.BasicItemForm;
+
+import org.scientificcms.publications.contenttypes.CollectedVolumeItem;
+
+/**
+ * Form for adding an association between an ArticleInCollectedVolume and a
+ * CollectedVolume.
+ *
+ * @author Jens Pelzetter
+ */
+public class ArticleInCollectedVolumeCollectedVolumeForm
+ extends BasicItemForm
+ implements FormProcessListener, FormInitListener {
+
+ private ItemSearchWidget itemSearch;
+
+ private final String ITEM_SEARCH = "collectedVolume";
+
+ public ArticleInCollectedVolumeCollectedVolumeForm(
+ final String formName,
+ final ItemSelectionModel itemSelectionModel,
+ final StringParameter selectedLanguageParam) {
+
+ super(formName, itemSelectionModel, selectedLanguageParam);
+ }
+
+ @Override
+ protected void addWidgets() {
+
+ itemSearch = new ItemSearchWidget(
+ ITEM_SEARCH,
+ CollectedVolumeItem.class
+ );
+ itemSearch.
+
+ itemSearch.setDefaultCreationFolder(config
+ .getDefaultCollectedVolumesFolder());
+ itemSearch.setLabel(PublicationGlobalizationUtil.globalize(
+ "publications.ui.articleInCollectedVolume.selectCollectedVolume"));
+ add(itemSearch);
+ }
+
+ @Override
+ public void init(final FormSectionEvent event) throws FormProcessException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void process(final FormSectionEvent event) throws
+ FormProcessException {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeSheet.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeSheet.java
new file mode 100644
index 0000000..0771f28
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeSheet.java
@@ -0,0 +1,308 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.security.PermissionChecker;
+import org.librecms.contentsection.privileges.ItemPrivileges;
+import org.scientificcms.publications.CollectedVolume;
+import org.scientificcms.publications.SciPublicationsConstants;
+import org.scientificcms.publications.contenttypes.ArticleInCollectedVolumeItem;
+
+import java.util.Locale;
+
+/**
+ * Sheet which displays the collected volume to which an article in a collected
+ * volume is associated to.
+ *
+ * @author Jens Pelzetter
+ */
+public class ArticleInCollectedVolumeCollectedVolumeSheet
+ extends Table
+ implements TableActionListener {
+
+ private final String TABLE_COL_EDIT = "table_col_edit";
+
+ private final String TABLE_COL_DEL = "table_col_del";
+
+ private ItemSelectionModel itemModel;
+
+ public ArticleInCollectedVolumeCollectedVolumeSheet(
+ final ItemSelectionModel itemModel,
+ final StringParameter selectedLangParam
+ ) {
+ super();
+ this.itemModel = itemModel;
+
+ setEmptyView(
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume.none",
+ SciPublicationsConstants.BUNDLE
+ )
+ )
+ );
+
+ final TableColumnModel colModel = getColumnModel();
+ colModel.add(
+ new TableColumn(
+ 0,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ TABLE_COL_EDIT
+ )
+ );
+ colModel.add(
+ new TableColumn(
+ 1,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume.remove",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ TABLE_COL_DEL
+ )
+ );
+
+ setModelBuilder(
+ new ArticleInCollectedVolumeCollectedVolumeSheetModelBuilder(
+ itemModel, selectedLangParam
+ )
+ );
+ colModel.get(0).setCellRenderer(new EditCellRenderer());
+ colModel.get(1).setCellRenderer(new DeleteCellRenderer());
+
+ addTableActionListener(this);
+
+ }
+
+ @Override
+ public void cellSelected(final TableActionEvent event)
+ throws FormProcessException {
+
+ final PageState state = event.getPageState();
+
+ final ArticleInCollectedVolumeItem articleItem
+ = (ArticleInCollectedVolumeItem) itemModel
+ .getSelectedObject(state);
+
+ final TableColumn column = getColumnModel().get(
+ event.getColumn().intValue()
+ );
+
+ if (column.getHeaderKey().toString().equals(TABLE_COL_EDIT)) {
+ // Nothing
+ } else if (column.getHeaderKey().toString().equals(TABLE_COL_DEL)) {
+ final ArticleInCollectedVolumeController controller = CdiUtil
+ .createCdiUtil()
+ .findBean(ArticleInCollectedVolumeController.class);
+ controller.unsetCollectedVolume(
+ articleItem.getPublication().getPublicationId()
+ );
+ }
+
+ }
+
+ @Override
+ public void headSelected(TableActionEvent event) {
+ // Nothing
+ }
+
+ private class ArticleInCollectedVolumeCollectedVolumeSheetModelBuilder
+ extends LockableImpl
+ implements TableModelBuilder {
+
+ private final ItemSelectionModel itemModel;
+ private final StringParameter selectedLangParam;
+
+ public ArticleInCollectedVolumeCollectedVolumeSheetModelBuilder(
+ final ItemSelectionModel itemModel,
+ final StringParameter selectedLangParam
+ ) {
+ this.itemModel = itemModel;
+ this.selectedLangParam = selectedLangParam;
+ }
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+ final ArticleInCollectedVolumeItem article
+ = (ArticleInCollectedVolumeItem) itemModel
+ .getSelectedObject(state);
+ return new ArticleInCollectedVolumeCollectedVolumeSheetModel(
+ table, state, article, selectedLangParam
+ );
+
+ }
+
+ }
+
+ private class ArticleInCollectedVolumeCollectedVolumeSheetModel
+ implements TableModel {
+
+ private final Table table;
+
+ private final String collectedVolumeTitle;
+
+ private final Long collectedVolumeId;
+
+ private boolean done;
+
+ public ArticleInCollectedVolumeCollectedVolumeSheetModel(
+ final Table table,
+ final PageState state,
+ final ArticleInCollectedVolumeItem articleItem,
+ final StringParameter selectedLangParam
+ ) {
+ this.table = table;
+ final CollectedVolume collectedVolume = articleItem
+ .getPublication()
+ .getCollectedVolume();
+ if (collectedVolume == null) {
+ done = false;
+ collectedVolumeTitle = null;
+ collectedVolumeId = null;
+ } else {
+ done = true;
+ final Locale selectedLang = SelectedLanguageUtil.selectedLocale(
+ state, selectedLangParam
+ );
+ collectedVolumeTitle = collectedVolume.getTitle().getValue(
+ selectedLang
+ );
+ collectedVolumeId = collectedVolume.getPublicationId();
+ }
+ }
+
+ @Override
+ public int getColumnCount() {
+ return table.getColumnModel().size();
+ }
+
+ @Override
+ public boolean nextRow() {
+ boolean ret;
+
+ if (done) {
+ ret = true;
+ done = false;
+ } else {
+ ret = false;
+ }
+
+ return ret;
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return collectedVolumeTitle;
+ case 1:
+ return new Label(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume.remove",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ default:
+ return null;
+ }
+ }
+
+ @Override
+ public Object getKeyAt(int columnIndex) {
+ return collectedVolumeId;
+ }
+
+ }
+
+ private class EditCellRenderer
+ extends LockableImpl
+ implements TableCellRenderer {
+
+ @Override
+ public Component getComponent(
+ final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column
+ ) {
+ return new Text((String) value);
+ }
+
+ }
+
+ private class DeleteCellRenderer
+ extends LockableImpl
+ implements TableCellRenderer {
+
+ @Override
+ public Component getComponent(
+ final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column
+ ) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final PermissionChecker permissionChecker = cdiUtil
+ .findBean(PermissionChecker.class);
+ final ArticleInCollectedVolumeItem articleItem
+ = (ArticleInCollectedVolumeItem) itemModel
+ .getSelectedObject(state);
+ final boolean canEdit = permissionChecker.isPermitted(
+ ItemPrivileges.EDIT, articleItem
+ );
+
+ if (canEdit) {
+ final ControlLink link = new ControlLink((Component) value);
+ link.setConfirmation(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume."
+ + "confirm_remove",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ return link;
+ } else {
+ return new Text("");
+ }
+ }
+
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeStep.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeStep.java
new file mode 100644
index 0000000..2da68f2
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeCollectedVolumeStep.java
@@ -0,0 +1,73 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.cms.ui.authoring.BasicItemForm;
+import com.arsdigita.cms.ui.authoring.SimpleEditStep;
+import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.scientificcms.publications.SciPublicationsConstants;
+
+/**
+ * /**
+ * Step for adding a association between a ArticleInCollectedVolume and a
+ * CollectedVolume.
+ *
+ * @author Jens Pelzetter
+ */
+public class ArticleInCollectedVolumeCollectedVolumeStep
+ extends SimpleEditStep {
+
+ private String ADD_COLLECTED_VOLUME_STEP = "addCollectedVolume";
+
+ public ArticleInCollectedVolumeCollectedVolumeStep(
+ final ItemSelectionModel itemModel,
+ final AuthoringKitWizard parent,
+ final StringParameter selectedLanguageParam
+ ) {
+ this(itemModel, parent, selectedLanguageParam, null);
+ }
+
+ public ArticleInCollectedVolumeCollectedVolumeStep(
+ final ItemSelectionModel itemSelectionModel,
+ final AuthoringKitWizard authoringKitWizard,
+ final StringParameter selectedLanguageParam,
+ final String parameterSuffix
+ ) {
+ super(itemSelectionModel,
+ authoringKitWizard,
+ selectedLanguageParam,
+ parameterSuffix);
+
+ final BasicItemForm addCollectedVolumeForm
+ = new ArticleInCollectedVolumeCollectedVolumeForm(
+ itemSelectionModel,
+ selectedLanguageParam
+ );
+
+ add(ADD_COLLECTED_VOLUME_STEP,
+ new GlobalizedMessage(
+ "publications.ui.collectedVolume.addCollectedVolume",
+ SciPublicationsConstants.BUNDLE
+ ),
+ new WorkflowLockedComponentAccess(
+ addCollectedVolumeForm,
+ itemSelectionModel
+ ),
+ addCollectedVolumeForm.getSaveCancelSection().getCancelButton());
+
+ final ArticleInCollectedVolumeCollectedVolumeSheet sheet
+ = new ArticleInCollectedVolumeCollectedVolumeSheet(
+ itemSelectionModel, selectedLanguageParam);
+ setDisplayComponent(sheet);
+
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeController.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeController.java
new file mode 100644
index 0000000..9faa71c
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumeController.java
@@ -0,0 +1,139 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import org.scientificcms.publications.ArticleInCollectedVolume;
+import org.scientificcms.publications.ArticleInCollectedVolumeManager;
+import org.scientificcms.publications.CollectedVolume;
+import org.scientificcms.publications.PublicationRepository;
+
+import java.util.Locale;
+import java.util.Map;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class ArticleInCollectedVolumeController {
+
+ public static final String START_PAGE = "startPage";
+
+ public static final String END_PAGE = "endPage";
+
+ public static final String CHAPTER = "chapter";
+
+ public static final String PEER_REVIEWED = "peerReviewed";
+
+ @Inject
+ private ArticleInCollectedVolumeManager articleManager;
+
+ @Inject
+ private PublicationRepository publicationRepository;
+
+ /**
+ * Save a changed {@link ArticleInCollectedVolume}.
+ *
+ * @param publicationId The ID of the article.
+ * @param selectedLocale The locale selected in the UI.
+ * @param data The data to set on the article.
+ */
+ @Transactional(Transactional.TxType.REQUIRED)
+ public void saveArticle(
+ final long publicationId,
+ final Locale selectedLocale,
+ final Map data
+ ) {
+ final ArticleInCollectedVolume article = publicationRepository
+ .findByIdAndType(publicationId, ArticleInCollectedVolume.class)
+ .orElseThrow(
+ () -> new IllegalArgumentException(
+ String.format(
+ "No ArticleInCollectedVolume with ID %d found.",
+ publicationId
+ )
+ )
+ );
+
+ if (data.get(START_PAGE) != null) {
+ final Integer startPage = (Integer) data.get(START_PAGE);
+ article.setStartPage(startPage);
+ }
+ if (data.get(END_PAGE) != null) {
+ final Integer endPage = (Integer) data.get(END_PAGE);
+ article.setEndPage(endPage);
+ }
+ if (data.get(CHAPTER) != null) {
+ final String chapter = (String) data.get(CHAPTER);
+ article.setChapter(chapter);
+ }
+ if (data.get(PEER_REVIEWED) != null) {
+ final Boolean peerReviewed = (Boolean) data.get(PEER_REVIEWED);
+ article.setPeerReviewed(peerReviewed);
+ }
+
+ publicationRepository.save(article);
+ }
+
+ /**
+ * Set the value of {@link ArticleInCollectedVolume#collectedVolume}
+ * property to a {@link CollectedVolume}.
+ *
+ * @param articleId The ID of the article to use.
+ * @param collectedVolumeId The ID of the collected volume to use.
+ */
+ @Transactional(Transactional.TxType.REQUIRED)
+ public void setCollectedVolume(
+ final long articleId, final long collectedVolumeId
+ ) {
+ final ArticleInCollectedVolume article = publicationRepository
+ .findByIdAndType(articleId, ArticleInCollectedVolume.class)
+ .orElseThrow(
+ () -> new IllegalArgumentException(
+ String.format(
+ "No ArticleInCollectedVolume with ID %d found",
+ articleId
+ )
+ )
+ );
+
+ final CollectedVolume collectedVolume = publicationRepository
+ .findByIdAndType(collectedVolumeId, CollectedVolume.class)
+ .orElseThrow(
+ () -> new IllegalArgumentException(
+ String.format(
+ "No CollectedVolume with ID %d found.",
+ collectedVolumeId
+ )
+ )
+ );
+
+ articleManager.setCollectedVolume(article, collectedVolume);
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public void unsetCollectedVolume(
+ final long articleId
+ ) {
+ final ArticleInCollectedVolume article = publicationRepository
+ .findByIdAndType(articleId, ArticleInCollectedVolume.class)
+ .orElseThrow(
+ () -> new IllegalArgumentException(
+ String.format(
+ "No ArticleInCollectedVolume with ID %d found",
+ articleId
+ )
+ )
+ );
+
+ articleManager.unsetCollectedVolume(article);
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertiesStep.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertiesStep.java
new file mode 100644
index 0000000..bf4c179
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertiesStep.java
@@ -0,0 +1,169 @@
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.AuthoringKitWizard;
+import com.arsdigita.cms.ui.authoring.BasicPageForm;
+import com.arsdigita.cms.ui.authoring.SimpleEditStep;
+import com.arsdigita.cms.ui.workflow.WorkflowLockedComponentAccess;
+import com.arsdigita.domain.DomainService;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.toolbox.ui.DomainObjectPropertySheet;
+
+import org.scientificcms.publications.SciPublicationsConstants;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class ArticleInCollectedVolumePropertiesStep
+ extends PublicationPropertiesStep {
+
+ private final StringParameter selectedLangParameter;
+
+ public ArticleInCollectedVolumePropertiesStep(
+ final ItemSelectionModel itemModel,
+ final AuthoringKitWizard parent,
+ final StringParameter selectedLangParameter
+ ) {
+ super(itemModel, parent, selectedLangParameter);
+ this.selectedLangParameter = selectedLangParameter;
+ }
+
+ public static Component getArticleInCollectedVolumePropertySheet(
+ final ItemSelectionModel itemModel,
+ final StringParameter selectedLanguageParam
+ ) {
+
+ final DomainObjectPropertySheet sheet
+ = (DomainObjectPropertySheet) PublicationPropertiesStep
+ .getPublicationPropertySheet(itemModel, selectedLanguageParam);
+
+ sheet.add(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.pages_from",
+ SciPublicationsConstants.BUNDLE
+ ),
+ ArticleInCollectedVolumeController.START_PAGE
+ );
+
+ sheet.add(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.pages_to",
+ SciPublicationsConstants.BUNDLE
+ ),
+ ArticleInCollectedVolumeController.END_PAGE
+ );
+
+ sheet.add(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.chapter",
+ SciPublicationsConstants.BUNDLE
+ ),
+ ArticleInCollectedVolumeController.CHAPTER
+ );
+
+ sheet.add(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.reviewed",
+ SciPublicationsConstants.BUNDLE
+ ),
+ ArticleInCollectedVolumeController.PEER_REVIEWED,
+ new ReviewedFormatter()
+ );
+
+ return sheet;
+ }
+
+ @Override
+ protected void addBasicProperties(
+ final ItemSelectionModel itemModel, final AuthoringKitWizard parent
+ ) {
+ final SimpleEditStep basicProperties = new SimpleEditStep(
+ itemModel, parent, selectedLangParameter, EDIT_SHEET_NAME
+ );
+
+ final BasicPageForm editBasicSheet
+ = new ArticleInCollectedVolumePropertyForm(
+ itemModel, this, selectedLangParameter
+ );
+
+ basicProperties.add(
+ EDIT_SHEET_NAME,
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.edit_basic_sheet",
+ SciPublicationsConstants.BUNDLE
+ ),
+ new WorkflowLockedComponentAccess(editBasicSheet, itemModel),
+ editBasicSheet.getSaveCancelSection().getCancelButton()
+ );
+
+ basicProperties.setDisplayComponent(
+ getArticleInCollectedVolumePropertySheet(
+ itemModel, selectedLangParameter
+ )
+ );
+
+ getSegmentedPanel().addSegment(
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.publication.basic_properties",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ basicProperties
+ );
+ }
+
+ @Override
+ protected void addSteps(
+ final ItemSelectionModel itemModel, final AuthoringKitWizard parent
+ ) {
+ super.addSteps(itemModel, parent);
+
+ addStep(
+ new ArticleInCollectedVolumeCollectedVolumeStep(
+ itemModel, parent, selectedLangParameter
+ ),
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.collectedVolume",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ }
+
+ private static class ReviewedFormatter
+ extends DomainService
+ implements DomainObjectPropertySheet.AttributeFormatter {
+
+ @Override
+ public String format(
+ final Object obj, final String attribute, final PageState state
+ ) {
+ final GlobalizedMessage msg;
+ if ((get(obj, attribute) instanceof Boolean)
+ && ((Boolean) get(obj, attribute) == true)) {
+ msg = new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.reviewed.yes",
+ SciPublicationsConstants.BUNDLE
+ );
+ } else {
+ msg = new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.reviewed.no",
+ SciPublicationsConstants.BUNDLE
+ );
+ }
+ return (String) msg.localize();
+ }
+
+ }
+
+ @Override
+ protected boolean isSeriesStepEnabled() {
+ return false;
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertyForm.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertyForm.java
new file mode 100644
index 0000000..7dbfaca
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/ArticleInCollectedVolumePropertyForm.java
@@ -0,0 +1,222 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.event.FormInitListener;
+import com.arsdigita.bebop.event.FormProcessListener;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.event.FormSubmissionListener;
+import com.arsdigita.bebop.form.CheckboxGroup;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.IntegerParameter;
+import com.arsdigita.bebop.parameters.ParameterModel;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.scientificcms.publications.ArticleInCollectedVolume;
+import org.scientificcms.publications.SciPublicationsConstants;
+import org.scientificcms.publications.contenttypes.ArticleInCollectedVolumeItem;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class ArticleInCollectedVolumePropertyForm
+ extends PublicationPropertyForm
+ implements FormProcessListener, FormInitListener, FormSubmissionListener {
+
+ public static final String ID = "ArticleInCollectedVolumeEdit";
+
+ private static final String REVIEWED = "reviewed";
+
+ private final ArticleInCollectedVolumePropertiesStep propertiesStep;
+
+ private final StringParameter selectedLangParam;
+
+ private CheckboxGroup reviewed;
+
+ public ArticleInCollectedVolumePropertyForm(
+ final ItemSelectionModel itemModel,
+ final StringParameter selectedLangParam
+ ) {
+ this(itemModel, null, selectedLangParam);
+ }
+
+ public ArticleInCollectedVolumePropertyForm(
+ final ItemSelectionModel itemModel,
+ final ArticleInCollectedVolumePropertiesStep step,
+ final StringParameter selectedLangParam
+ ) {
+ super(itemModel, step, selectedLangParam);
+ propertiesStep = step;
+ this.selectedLangParam = selectedLangParam;
+ addSubmissionListener(this);
+ }
+
+ @Override
+ protected void addWidgets() {
+
+ super.addWidgets();
+
+ final ParameterModel startPageParam = new IntegerParameter(
+ ArticleInCollectedVolumeController.START_PAGE);
+ final TextField startPage = new TextField(startPageParam);
+ startPage.setLabel(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.pages_from",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ add(startPage);
+
+ ParameterModel endPageParam = new IntegerParameter(
+ ArticleInCollectedVolumeController.END_PAGE
+ );
+ final TextField endPage = new TextField(endPageParam);
+ endPage.setLabel(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.pages_to",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ add(endPage);
+
+ ParameterModel chapterParam = new StringParameter(
+ ArticleInCollectedVolumeController.CHAPTER
+ );
+ final TextField chapter = new TextField(chapterParam);
+ chapter.setLabel(
+ new GlobalizedMessage(
+ "publications.ui.article_in_collected_volume.chapter",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ add(chapter);
+
+ reviewed = new CheckboxGroup("reviewedGroup");
+ reviewed.addOption(
+ new Option(
+ REVIEWED,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.reviewed",
+ SciPublicationsConstants.BUNDLE
+ )
+ )
+ )
+ );
+ reviewed.setLabel(
+ new GlobalizedMessage(
+ "publications.ui.articleInCollectedVolume.reviewed",
+ SciPublicationsConstants.BUNDLE
+ )
+ );
+ add(reviewed);
+ }
+
+ @Override
+ public void init(final FormSectionEvent event) throws FormProcessException {
+
+ super.init(event);
+
+ final FormData data = event.getFormData();
+ final ArticleInCollectedVolumeItem articleItem
+ = (ArticleInCollectedVolumeItem) initBasicWidgets(
+ event);
+
+ final ArticleInCollectedVolume article = articleItem.getPublication();
+
+ data.put(
+ ArticleInCollectedVolumeController.START_PAGE,
+ article.getStartPage()
+ );
+ data.put(
+ ArticleInCollectedVolumeController.END_PAGE,
+ article.getEndPage()
+ );
+ data.put(
+ ArticleInCollectedVolumeController.CHAPTER, article.getChapter()
+ );
+
+ if ((article.getPeerReviewed() != null)
+ && (article.getPeerReviewed())) {
+ reviewed.setValue(event.getPageState(), new String[]{REVIEWED});
+ } else {
+ reviewed.setValue(event.getPageState(), null);
+ }
+ }
+
+ @Override
+ public void process(final FormSectionEvent event)
+ throws FormProcessException {
+
+ super.process(event);
+
+ final FormData formData = event.getFormData();
+ final PageState state = event.getPageState();
+ final ArticleInCollectedVolumeItem articleItem
+ = (ArticleInCollectedVolumeItem) processBasicWidgets(
+ event);
+
+ if (articleItem != null
+ && getSaveCancelSection().getSaveButton().isSelected(state)) {
+
+ final Map data = new HashMap<>();
+
+ data.put(
+ ArticleInCollectedVolumeController.START_PAGE,
+ data.get(ArticleInCollectedVolumeController.START_PAGE)
+ );
+ data.put(
+ ArticleInCollectedVolumeController.END_PAGE,
+ data.get(ArticleInCollectedVolumeController.END_PAGE)
+ );
+ data.put(
+ ArticleInCollectedVolumeController.CHAPTER,
+ data.get(ArticleInCollectedVolumeController.CHAPTER)
+ );
+
+ if (reviewed.getValue(event.getPageState()) == null) {
+ data.put(
+ ArticleInCollectedVolumeController.PEER_REVIEWED,
+ Boolean.FALSE
+ );
+ } else {
+ data.put(
+ ArticleInCollectedVolumeController.PEER_REVIEWED,
+ Boolean.TRUE
+ );
+ }
+
+ final Locale selectedLocale = SelectedLanguageUtil.selectedLocale(
+ state, selectedLangParam
+ );
+
+ final ArticleInCollectedVolumeController controller = CdiUtil
+ .createCdiUtil()
+ .findBean(ArticleInCollectedVolumeController.class);
+ controller.saveArticle(
+ articleItem.getPublication().getPublicationId(),
+ selectedLocale,
+ data
+ );
+ }
+
+ }
+
+}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesPropertyStep.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesPropertyStep.java
index ccfa3a8..aa250c3 100644
--- a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesPropertyStep.java
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesPropertyStep.java
@@ -50,7 +50,7 @@ public class PublicationSeriesPropertyStep extends SimpleEditStep {
addSeriesSheet.getSaveCancelSection().getCancelButton());
final PublicationSeriesTable seriesTable = new PublicationSeriesTable(
- itemModel
+ itemModel, this, selectedLanguageParameter
);
setDisplayComponent(seriesTable);
}
diff --git a/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesTable.java b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesTable.java
new file mode 100644
index 0000000..f28f642
--- /dev/null
+++ b/sci-publications/src/main/java/com/arsdigita/cms/contenttypes/ui/PublicationSeriesTable.java
@@ -0,0 +1,357 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.arsdigita.cms.contenttypes.ui;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.cms.ItemSelectionModel;
+import com.arsdigita.cms.ui.authoring.SelectedLanguageUtil;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.l10n.LocalizedString;
+import org.libreccm.security.PermissionChecker;
+import org.librecms.contentsection.privileges.ItemPrivileges;
+import org.scientificcms.publications.SciPublicationsConstants;
+import org.scientificcms.publications.VolumeInSeries;
+import org.scientificcms.publications.contenttypes.PublicationItem;
+
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class PublicationSeriesTable
+ extends Table
+ implements TableActionListener {
+
+ private static final Logger LOGGER = LogManager.getLogger(
+ PublicationSeriesTable.class);
+
+ private final static String TABLE_COL_EDIT = "table_col_edit";
+
+ private final static String TABLE_COL_NUMBER = "table_col_num";
+
+ private final static String TABLE_COL_DEL = "table_col_del";
+
+ private final ItemSelectionModel itemModel;
+
+ private final PublicationSeriesPropertyStep editStep;
+
+ private final StringParameter selectedLangParam;
+
+ public PublicationSeriesTable(
+ final ItemSelectionModel itemModel,
+ final PublicationSeriesPropertyStep editStep,
+ final StringParameter selectedLangParam
+ ) {
+
+ super();
+ this.itemModel = itemModel;
+ this.editStep = editStep;
+ this.selectedLangParam = selectedLangParam;
+
+ setEmptyView(
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.series.none",
+ SciPublicationsConstants.BUNDLE
+ )
+ )
+ );
+
+ final TableColumnModel colModel = getColumnModel();
+ colModel.add(
+ new TableColumn(
+ 0,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.series.title",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ TABLE_COL_EDIT
+ )
+ );
+ colModel.add(
+ new TableColumn(
+ 1,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.series.number",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ TABLE_COL_NUMBER
+ )
+ );
+ colModel.add(
+ new TableColumn(
+ 2,
+ new Label(
+ new GlobalizedMessage(
+ "publications.ui.series.remove",
+ SciPublicationsConstants.BUNDLE
+ )
+ ),
+ TABLE_COL_DEL
+ )
+ );
+
+ setModelBuilder(
+ new PublicationSeriesTableModelBuilder(
+ itemModel, selectedLangParam
+ )
+ );
+
+ colModel.get(0).setCellRenderer(new EditCellRenderer());
+ colModel.get(1).setCellRenderer(new NumberCellRenderer());
+ colModel.get(2).setCellRenderer(new DeleteCellRenderer());
+
+ LOGGER.info("Adding table action listener...");
+ addTableActionListener(this);
+ }
+
+ @Override
+ public void cellSelected(final TableActionEvent event)
+ throws FormProcessException {
+
+ final PageState state = event.getPageState();
+ final PublicationItem> selected = (PublicationItem>) itemModel
+ .getSelectedItem(state);
+ final SciPublicationsController controller = CdiUtil
+ .createCdiUtil()
+ .findBean(SciPublicationsController.class);
+ final VolumeInSeries volumeInSeries = controller.findVolumeInSeries(
+ selected.getPublication().getPublicationId(),
+ event.getRowKey()
+ ).get();
+
+ final TableColumn column = getColumnModel().get(event.getColumn());
+
+ if (TABLE_COL_EDIT.equals(column.getHeaderKey().toString())) {
+ // Nothing for now
+ } else if (TABLE_COL_DEL.equals(column.getHeaderKey().toString())) {
+ controller.removeSeries(
+ selected.getPublication().getPublicationId(),
+ volumeInSeries.getVolumeId()
+ );
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+
+ // Nothing
+ }
+
+ private class PublicationSeriesTableModelBuilder
+ extends LockableImpl
+ implements TableModelBuilder {
+
+ private final ItemSelectionModel itemModel;
+
+ public PublicationSeriesTableModelBuilder(
+ final ItemSelectionModel itemModel,
+ final StringParameter selectedLangParam
+ ) {
+ this.itemModel = itemModel;
+ }
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+
+ table.getRowSelectionModel().clearSelection(state);
+ final PublicationItem> publication
+ = (PublicationItem>) itemModel
+ .getSelectedItem(state);
+ return new PublicationSeriesTableModel(
+ table, state, selectedLangParam, publication
+ );
+ }
+
+ }
+
+ private class PublicationSeriesTableModel implements TableModel {
+
+ private final Table table;
+
+ private final PageState state;
+
+ private final StringParameter selectedLangParam;
+
+ private final Iterator