CCM NG/ccm-cms: Progress for ItemLanguages and related classes (not finished yet)
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4454 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
681ba87a68
commit
582bcab967
|
|
@ -53,9 +53,6 @@ public class ItemSelectionModel extends CcmObjectSelectionModel<ContentItem> {
|
|||
|
||||
private Long typeId;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(
|
||||
ItemSelectionModel.class);
|
||||
|
||||
/**
|
||||
* Construct a new <code>ItemSelectionModel</code>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import com.arsdigita.bebop.Form;
|
|||
import com.arsdigita.bebop.FormProcessException;
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.bebop.event.FormProcessListener;
|
||||
import com.arsdigita.bebop.event.FormSectionEvent;
|
||||
import com.arsdigita.bebop.event.PrintEvent;
|
||||
|
|
@ -30,13 +31,17 @@ import com.arsdigita.bebop.event.PrintListener;
|
|||
import com.arsdigita.bebop.form.Option;
|
||||
import com.arsdigita.bebop.form.OptionGroup;
|
||||
import com.arsdigita.bebop.form.Submit;
|
||||
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentSection;
|
||||
import org.librecms.contentsection.ContentType;
|
||||
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.cms.ui.authoring.LanguageWidget;
|
||||
|
||||
import org.librecms.util.LanguageUtil;
|
||||
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
import com.arsdigita.toolbox.ui.ActionGroup;
|
||||
import com.arsdigita.toolbox.ui.LayoutPanel;
|
||||
|
|
@ -46,12 +51,17 @@ import com.arsdigita.util.Pair;
|
|||
import com.arsdigita.util.UncheckedWrapperException;
|
||||
import com.arsdigita.web.RedirectSignal;
|
||||
import com.arsdigita.web.URL;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.libreccm.workflow.Workflow;
|
||||
import org.libreccm.workflow.WorkflowTemplate;
|
||||
import org.librecms.contentsection.ContentItemL10NManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TooManyListenersException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Displays the "Language instances" pane, with all the language instances in
|
||||
|
|
@ -63,6 +73,7 @@ import java.util.TooManyListenersException;
|
|||
public class ItemLanguages extends LayoutPanel {
|
||||
|
||||
private final ItemSelectionModel selectionModel;
|
||||
private final SingleSelectionModel<String> selectedLanguage;
|
||||
private final LanguageWidget languageWidget;
|
||||
private final Submit changeSubmit;
|
||||
private final Submit createSubmit;
|
||||
|
|
@ -70,11 +81,15 @@ public class ItemLanguages extends LayoutPanel {
|
|||
/**
|
||||
* Constructs a new <code>ItemLanguages</code>.
|
||||
*
|
||||
* @param selectionModel the {@link ItemSelectionModel} which will supply
|
||||
* the current item
|
||||
* @param selectionModel the {@link ItemSelectionModel} which will supply
|
||||
* the current item
|
||||
* @param selectedLanguage {@link SingleSelectionModel} for the selected
|
||||
* language.
|
||||
*/
|
||||
public ItemLanguages(final ItemSelectionModel selectionModel) {
|
||||
public ItemLanguages(final ItemSelectionModel selectionModel,
|
||||
final SingleSelectionModel<String> selectedLanguage) {
|
||||
this.selectionModel = selectionModel;
|
||||
this.selectedLanguage = selectedLanguage;
|
||||
|
||||
final Section section = new Section(gz("cms.ui.item.languages"));
|
||||
setBody(section);
|
||||
|
|
@ -82,15 +97,17 @@ public class ItemLanguages extends LayoutPanel {
|
|||
final ActionGroup group = new ActionGroup();
|
||||
section.setBody(group);
|
||||
|
||||
group.setSubject(new ItemLanguagesTable(selectionModel));
|
||||
group.setSubject(new ItemLanguagesTable(selectionModel,
|
||||
selectedLanguage));
|
||||
|
||||
final Form form = new Form("newLanguage", new BoxPanel(
|
||||
BoxPanel.HORIZONTAL));
|
||||
group.addAction(form);
|
||||
|
||||
form.setRedirecting(true);
|
||||
languageWidget = new LanguageWidget(ContentItem.LANGUAGE) {
|
||||
languageWidget = new LanguageWidget("language_widget") {
|
||||
|
||||
@Override
|
||||
protected void setupOptions() {
|
||||
// Don't do anything.
|
||||
}
|
||||
|
|
@ -99,8 +116,8 @@ public class ItemLanguages extends LayoutPanel {
|
|||
|
||||
try {
|
||||
languageWidget.addPrintListener(new OptionPrinter());
|
||||
} catch (TooManyListenersException tmle) {
|
||||
new UncheckedWrapperException(tmle);
|
||||
} catch (TooManyListenersException ex) {
|
||||
throw new UncheckedWrapperException(ex);
|
||||
}
|
||||
|
||||
form.add(languageWidget);
|
||||
|
|
@ -116,16 +133,26 @@ public class ItemLanguages extends LayoutPanel {
|
|||
*/
|
||||
private class OptionPrinter implements PrintListener {
|
||||
|
||||
public final void prepare(final PrintEvent e) {
|
||||
final PageState state = e.getPageState();
|
||||
final OptionGroup optionGroup = (OptionGroup) e.getTarget();
|
||||
final ContentPage item = (ContentPage) selectionModel.
|
||||
getSelectedItem(state);
|
||||
final Collection languages = LanguageUtil.convertToG11N(
|
||||
LanguageUtil.getCreatableLanguages(item));
|
||||
@Override
|
||||
public final void prepare(final PrintEvent event) {
|
||||
final PageState state = event.getPageState();
|
||||
final OptionGroup optionGroup = (OptionGroup) event.getTarget();
|
||||
final ContentItem item = selectionModel.getSelectedItem(state);
|
||||
|
||||
for (Iterator iter = languages.iterator(); iter.hasNext();) {
|
||||
final Pair pair = (Pair) iter.next();
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final LanguageUtil languageUtil = cdiUtil.findBean(
|
||||
LanguageUtil.class);
|
||||
final ContentItemL10NManager l10NManager = cdiUtil.findBean(
|
||||
ContentItemL10NManager.class);
|
||||
|
||||
final List<String> creatableLangs = l10NManager.creatableLocales(
|
||||
item).stream()
|
||||
.map(locale -> locale.toString())
|
||||
.collect(Collectors.toList());
|
||||
final List<Pair> languages = languageUtil.convertToG11N(
|
||||
creatableLangs);
|
||||
|
||||
for(final Pair pair : languages) {
|
||||
final String langCode = (String) pair.getKey();
|
||||
final GlobalizedMessage langName
|
||||
= (GlobalizedMessage) pair
|
||||
|
|
@ -141,9 +168,10 @@ public class ItemLanguages extends LayoutPanel {
|
|||
*/
|
||||
private class ProcessListener implements FormProcessListener {
|
||||
|
||||
public final void process(final FormSectionEvent e)
|
||||
@Override
|
||||
public final void process(final FormSectionEvent event)
|
||||
throws FormProcessException {
|
||||
PageState state = e.getPageState();
|
||||
PageState state = event.getPageState();
|
||||
String lang = (String) languageWidget.getValue(state);
|
||||
ContentPage item = (ContentPage) selectionModel.getSelectedItem(
|
||||
state);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (C) 2016 LibreCCM Foundation.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.cms.ui.item;
|
||||
|
||||
import com.arsdigita.bebop.table.RowData;
|
||||
|
||||
import org.libreccm.l10n.GlobalizationHelper;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentItemL10NManager;
|
||||
import org.librecms.contentsection.ContentItemRepository;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.transaction.Transactional;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class ItemLanguagesController {
|
||||
|
||||
@Inject
|
||||
private ContentItemRepository itemRepo;
|
||||
|
||||
@Inject
|
||||
private ContentItemL10NManager itemL10NManager;
|
||||
|
||||
@Inject
|
||||
private GlobalizationHelper globalizationHelper;
|
||||
|
||||
public List<RowData<String>> retrieveLanguageVariants(final ContentItem item) {
|
||||
return retrieveLanguageVariants(item.getObjectId());
|
||||
}
|
||||
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public List<RowData<String>> retrieveLanguageVariants(final long itemId) {
|
||||
final Optional<ContentItem> item = itemRepo.findById(itemId);
|
||||
|
||||
if (!item.isPresent()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"No content item with id %d found.", itemId));
|
||||
}
|
||||
|
||||
final List<Locale> availableLangs = new ArrayList<>(itemL10NManager
|
||||
.availableLanguages(item.get()));
|
||||
availableLangs.sort((locale1, locale2) -> {
|
||||
return locale1.toString().compareTo(locale2.toString());
|
||||
});
|
||||
|
||||
return availableLangs.stream()
|
||||
.map(lang -> createRow(item.get(), lang))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private RowData<String> createRow(final ContentItem item,
|
||||
final Locale lang) {
|
||||
final RowData<String> row = new RowData<>(2);
|
||||
row.setRowKey(lang.toString());
|
||||
row.setColData(0, lang.getDisplayName(globalizationHelper.getNegotiatedLocale()));
|
||||
row.setColData(1, item.getTitle().getValue(lang));
|
||||
|
||||
return row;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -18,237 +18,162 @@
|
|||
*/
|
||||
package com.arsdigita.cms.ui.item;
|
||||
|
||||
import com.arsdigita.bebop.event.TableActionAdapter;
|
||||
import com.arsdigita.bebop.Component;
|
||||
import com.arsdigita.bebop.ControlLink;
|
||||
import com.arsdigita.bebop.FormProcessException;
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.Link;
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.SingleSelectionModel;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.bebop.event.TableActionEvent;
|
||||
import com.arsdigita.bebop.event.TableActionListener;
|
||||
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||
import com.arsdigita.bebop.table.TableColumn;
|
||||
import com.arsdigita.bebop.table.TableColumnModel;
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.cms.dispatcher.MultilingualItemResolver;
|
||||
import com.arsdigita.cms.ui.ContentItemPage;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
import org.librecms.contentsection.ContentItemL10NManager;
|
||||
import org.librecms.util.LanguageUtil;
|
||||
import com.arsdigita.toolbox.ui.DataTable;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
import com.arsdigita.web.RedirectSignal;
|
||||
import com.arsdigita.web.URL;
|
||||
import java.math.BigDecimal;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
/**
|
||||
* Displays a list of all language instances of an item.
|
||||
*
|
||||
*/
|
||||
public class ItemLanguagesTable extends DataTable {
|
||||
public class ItemLanguagesTable extends Table {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ItemLanguagesTable.class);
|
||||
private final ItemSelectionModel m_model;
|
||||
private final TableColumn m_deleteColumn;
|
||||
public static final int COL_LANGUAGE = 0;
|
||||
public static final int COL_TITLE = 1;
|
||||
public static final int COL_DELETE = 2;
|
||||
|
||||
private final ItemSelectionModel itemSelectionModel;
|
||||
private final SingleSelectionModel<String> langSelectionModel;
|
||||
// private final TableColumn deleteColumn;
|
||||
|
||||
/**
|
||||
* Construct a new
|
||||
* <code>ItemHistoryTable</code>
|
||||
* Construct a new {@code ItemLanguagesTable} which shows all language
|
||||
* variants of an item.
|
||||
*
|
||||
* @param model the ItemSelectionModel that supplies the current item
|
||||
* @param itemSelectionModel the ItemSelectionModel that supplies the
|
||||
* current item
|
||||
* @param langSelectionModel the single selection model which stores the
|
||||
* selected language.
|
||||
*/
|
||||
public ItemLanguagesTable(ItemSelectionModel model) {
|
||||
super(new LanguagesBuilder(model));
|
||||
m_model = model;
|
||||
public ItemLanguagesTable(final ItemSelectionModel itemSelectionModel,
|
||||
final SingleSelectionModel<String> langSelectionModel) {
|
||||
super();
|
||||
setIdAttr("item_languages_table");
|
||||
|
||||
addColumn("cms.ui.language.header",
|
||||
ContentPage.LANGUAGE,
|
||||
false,
|
||||
new LanguageCellRenderer(m_model));
|
||||
addColumn("cms.ui.title",
|
||||
ContentPage.TITLE);
|
||||
m_deleteColumn = addColumn("cms.ui.action", new ActionCellRenderer(
|
||||
m_model));
|
||||
setResourceBundle(GlobalizationUtil.getBundleName());
|
||||
addTableActionListener(new InstanceDeleter(m_model));
|
||||
}
|
||||
this.itemSelectionModel = itemSelectionModel;
|
||||
this.langSelectionModel = langSelectionModel;
|
||||
setModelBuilder(new ItemLanguagesTableModelBuilder(itemSelectionModel));
|
||||
|
||||
/**
|
||||
* Builds the query for all the language instances in the current Bundle
|
||||
*/
|
||||
private static class LanguagesBuilder extends LockableImpl
|
||||
implements DataQueryBuilder {
|
||||
final TableColumnModel columnModel = getColumnModel();
|
||||
columnModel.add(new TableColumn(COL_LANGUAGE,
|
||||
new Label(new GlobalizedMessage(
|
||||
"cms.ui.language.header",
|
||||
CmsConstants.CMS_BUNDLE))));
|
||||
columnModel.add(new TableColumn(COL_TITLE,
|
||||
new Label(new GlobalizedMessage(
|
||||
"cms.ui.language.title",
|
||||
CmsConstants.CMS_BUNDLE))));
|
||||
columnModel.add(new TableColumn(COL_DELETE,
|
||||
new Label(new GlobalizedMessage(
|
||||
"cms.ui.action",
|
||||
CmsConstants.CMS_BUNDLE))));
|
||||
|
||||
ItemSelectionModel m_model;
|
||||
columnModel.get(COL_LANGUAGE).setCellRenderer(new TableCellRenderer() {
|
||||
|
||||
public LanguagesBuilder(ItemSelectionModel model) {
|
||||
super();
|
||||
m_model = model;
|
||||
}
|
||||
@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) {
|
||||
|
||||
public DataQuery makeDataQuery(DataTable t, PageState s) {
|
||||
ContentPage multiLingual =
|
||||
(ContentPage) m_model.getSelectedObject(s);
|
||||
DataQuery q = SessionManager.getSession().retrieveQuery(
|
||||
"com.arsdigita.cms.getBundledItems");
|
||||
q.setParameter("bundleID", multiLingual.getContentBundle().getID());
|
||||
return q;
|
||||
}
|
||||
final Locale locale = new Locale((String) value);
|
||||
|
||||
public String getKeyColumn() {
|
||||
return ContentPage.ID;
|
||||
}
|
||||
}
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final LanguageUtil langUtil = cdiUtil.findBean(
|
||||
LanguageUtil.class);
|
||||
|
||||
/**
|
||||
* Renders the full language name.
|
||||
*/
|
||||
private static class LanguageCellRenderer implements TableCellRenderer {
|
||||
final Label label = new Label(langUtil.getLangFull(locale));
|
||||
|
||||
private ItemSelectionModel m_model;
|
||||
|
||||
public LanguageCellRenderer(ItemSelectionModel model) {
|
||||
m_model = model;
|
||||
}
|
||||
|
||||
public Component getComponent(Table table, PageState state, Object value,
|
||||
boolean isSelected, Object key,
|
||||
int row, int column) {
|
||||
|
||||
BigDecimal id = (BigDecimal) key;
|
||||
ContentPage cp;
|
||||
|
||||
try {
|
||||
cp = new ContentPage(id);
|
||||
} catch (DataObjectNotFoundException ex) {
|
||||
// Content item was not found, return nothing
|
||||
return new Label();
|
||||
}
|
||||
|
||||
ContentBundle bundle = cp.getContentBundle();
|
||||
|
||||
if (bundle != null
|
||||
&& !(cp instanceof LanguageInvariantContentItem
|
||||
&& ((LanguageInvariantContentItem) cp).isLanguageInvariant())) {
|
||||
|
||||
StringBuilder fontWeight = new StringBuilder(2);
|
||||
StringBuilder classes = new StringBuilder(20);
|
||||
|
||||
if (cp.isLive()) {
|
||||
fontWeight.append(Label.BOLD);
|
||||
classes.append("live ");
|
||||
}
|
||||
if (bundle.getPrimaryInstance().equals(cp)) {
|
||||
fontWeight.append(Label.ITALIC);
|
||||
classes.append("primaryInstance");
|
||||
}
|
||||
|
||||
String target = ContentItemPage.getItemURL(cp, ContentItemPage.AUTHORING_TAB);
|
||||
Label langLabel = new Label(LanguageUtil.getLangFull((String) value));
|
||||
|
||||
langLabel.setFontWeight(fontWeight.toString().trim());
|
||||
langLabel.setClassAttr(classes.toString().trim());
|
||||
|
||||
if (m_model.getSelectedKey(state).equals(key)) {
|
||||
// Current instance: no link
|
||||
return langLabel;
|
||||
if (langSelectionModel.getSelectedKey(state).equals(key)) {
|
||||
// Current variant, no link
|
||||
return label;
|
||||
} else {
|
||||
return new Link(langLabel, target);
|
||||
final String target = ContentItemPage.getItemURL(
|
||||
itemSelectionModel.getSelectedItem(state),
|
||||
ContentItemPage.AUTHORING_TAB);
|
||||
return new Link(label, target);
|
||||
}
|
||||
}
|
||||
|
||||
return new Label();
|
||||
}
|
||||
);
|
||||
columnModel.get(COL_DELETE).setCellRenderer(new 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 ControlLink link = new ControlLink(new Label(
|
||||
new GlobalizedMessage("cms.ui.delete",
|
||||
CmsConstants.CMS_BUNDLE)));
|
||||
link.setConfirmation(new GlobalizedMessage(
|
||||
"cms.ui.delete.confirmation", CmsConstants.CMS_BUNDLE));
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
addTableActionListener(new TableActionListener() {
|
||||
|
||||
@Override
|
||||
public void cellSelected(final TableActionEvent event)
|
||||
throws FormProcessException {
|
||||
|
||||
if (event.getColumn() != COL_DELETE) {
|
||||
//Nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
final PageState state = event.getPageState();
|
||||
final ContentItem item = itemSelectionModel
|
||||
.getSelectedItem(state);
|
||||
final String selectedLang = (String) event.getRowKey();
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ContentItemL10NManager l10nManager = cdiUtil.findBean(
|
||||
ContentItemL10NManager.class);
|
||||
|
||||
l10nManager.removeLangauge(item, new Locale(selectedLang));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void headSelected(final TableActionEvent event) {
|
||||
//Nothing
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete language instance action link.
|
||||
*/
|
||||
private static class ActionCellRenderer implements TableCellRenderer {
|
||||
|
||||
private static final Logger logger =
|
||||
Logger.getLogger(ActionCellRenderer.class);
|
||||
private static final Label s_noAction;
|
||||
private static final Label s_primary;
|
||||
private static final ControlLink s_link;
|
||||
|
||||
static {
|
||||
logger.debug("Static initializer is starting...");
|
||||
s_noAction = new Label(" ", false);
|
||||
s_noAction.lock();
|
||||
s_primary = new Label(GlobalizationUtil.globalize(
|
||||
"cms.ui.primary_instance"), false);
|
||||
s_primary.lock();
|
||||
s_link = new ControlLink(new Label(GlobalizationUtil.globalize(
|
||||
"cms.ui.delete")));
|
||||
s_link.setConfirmation(GlobalizationUtil.globalize(
|
||||
"cms.ui.delete_confirmation"));
|
||||
logger.debug("Static initalizer finished.");
|
||||
}
|
||||
private ItemSelectionModel m_model;
|
||||
|
||||
public ActionCellRenderer(ItemSelectionModel model) {
|
||||
m_model = model;
|
||||
}
|
||||
|
||||
public Component getComponent(Table table, PageState state, Object value,
|
||||
boolean isSelected, Object key,
|
||||
int row, int column) {
|
||||
// check if primary instance
|
||||
BigDecimal id = new BigDecimal(key.toString());
|
||||
OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
|
||||
try {
|
||||
ContentPage item = (ContentPage) DomainObjectFactory.newInstance(oid);
|
||||
if (item.getLanguage().equals(
|
||||
item.getContentBundle().getDefaultLanguage())) {
|
||||
return s_primary;
|
||||
} else if (item.isLive()) {
|
||||
return s_noAction;
|
||||
}
|
||||
} catch (DataObjectNotFoundException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not get item with id " + id);
|
||||
}
|
||||
return s_noAction;
|
||||
}
|
||||
return s_link;
|
||||
}
|
||||
}
|
||||
|
||||
// delete one language instance
|
||||
private class InstanceDeleter extends TableActionAdapter {
|
||||
|
||||
private ItemSelectionModel m_model;
|
||||
|
||||
public InstanceDeleter(ItemSelectionModel model) {
|
||||
m_model = model;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cellSelected(TableActionEvent e) {
|
||||
int col = e.getColumn().intValue();
|
||||
|
||||
if (m_deleteColumn != getColumn(col)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PageState s = e.getPageState();
|
||||
BigDecimal id = new BigDecimal(e.getRowKey().toString());
|
||||
|
||||
OID oid = new OID(ContentPage.BASE_DATA_OBJECT_TYPE, id);
|
||||
try {
|
||||
ContentPage item =
|
||||
(ContentPage) DomainObjectFactory.newInstance(oid);
|
||||
ContentBundle bundle = item.getContentBundle();
|
||||
bundle.removeInstance(item);
|
||||
item.delete();
|
||||
|
||||
if (m_model.getSelectedKey(s).equals(id)) {
|
||||
throw new RedirectSignal(
|
||||
URL.there((new MultilingualItemResolver()
|
||||
.generateItemURL(s,
|
||||
bundle.getPrimaryInstance(),
|
||||
bundle.getContentSection(),
|
||||
ContentItem.DRAFT)),
|
||||
null),
|
||||
true);
|
||||
}
|
||||
} catch (com.arsdigita.domain.DataObjectNotFoundException ex) {
|
||||
// Object not found is ok, it has probably been deleted already
|
||||
}
|
||||
((Table) e.getSource()).clearSelection(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (C) 2016 LibreCCM Foundation.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.cms.ui.item;
|
||||
|
||||
import com.arsdigita.bebop.Label;
|
||||
import com.arsdigita.bebop.table.RowData;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.globalization.GlobalizedMessage;
|
||||
|
||||
import org.librecms.CmsConstants;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class ItemLanguagesTableModel implements TableModel {
|
||||
|
||||
private final Iterator<RowData<String>> iterator;
|
||||
private RowData<String> curentRow;
|
||||
|
||||
protected ItemLanguagesTableModel(final List<RowData<String>> rows) {
|
||||
iterator = rows.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColumnCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean nextRow() {
|
||||
if (iterator.hasNext()) {
|
||||
curentRow = iterator.next();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getElementAt(final int columnIndex) {
|
||||
switch (columnIndex) {
|
||||
case ItemLanguagesTable.COL_LANGUAGE:
|
||||
return curentRow.getColData(0);
|
||||
case ItemLanguagesTable.COL_TITLE:
|
||||
return curentRow.getColData(1);
|
||||
case ItemLanguagesTable.COL_DELETE:
|
||||
return new Label(new GlobalizedMessage("cms.ui.delete",
|
||||
CmsConstants.CMS_BUNDLE));
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid column index.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getKeyAt(final int columnIndex) {
|
||||
return curentRow.getRowKey();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (C) 2016 LibreCCM Foundation.
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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 this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
package com.arsdigita.cms.ui.item;
|
||||
|
||||
import com.arsdigita.bebop.PageState;
|
||||
import com.arsdigita.bebop.Table;
|
||||
import com.arsdigita.bebop.table.RowData;
|
||||
import com.arsdigita.bebop.table.TableModel;
|
||||
import com.arsdigita.bebop.table.TableModelBuilder;
|
||||
import com.arsdigita.cms.ItemSelectionModel;
|
||||
import com.arsdigita.util.LockableImpl;
|
||||
|
||||
import org.libreccm.cdi.utils.CdiUtil;
|
||||
import org.librecms.contentsection.ContentItem;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||
*/
|
||||
class ItemLanguagesTableModelBuilder
|
||||
extends LockableImpl
|
||||
implements TableModelBuilder {
|
||||
|
||||
private final ItemSelectionModel itemSelectionModel;
|
||||
|
||||
protected ItemLanguagesTableModelBuilder(
|
||||
final ItemSelectionModel itemSelectionModel) {
|
||||
this.itemSelectionModel = itemSelectionModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableModel makeModel(final Table table, final PageState state) {
|
||||
final ContentItem item = itemSelectionModel.getSelectedItem(state);
|
||||
|
||||
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
|
||||
final ItemLanguagesController controller = cdiUtil.findBean(ItemLanguagesController.class);
|
||||
final List<RowData<String>> rows = controller.retrieveLanguageVariants(
|
||||
item);
|
||||
|
||||
return new ItemLanguagesTableModel(rows);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import com.arsdigita.util.UncheckedWrapperException;
|
|||
import org.libreccm.configuration.ConfigurationManager;
|
||||
import org.libreccm.l10n.LocalizedString;
|
||||
import org.libreccm.security.AuthorizationRequired;
|
||||
import org.libreccm.security.PermissionChecker;
|
||||
import org.libreccm.security.RequiresPrivilege;
|
||||
import org.librecms.CmsConstants;
|
||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
||||
|
|
@ -34,9 +35,11 @@ import java.beans.PropertyDescriptor;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
|
@ -60,6 +63,9 @@ public class ContentItemL10NManager {
|
|||
@Inject
|
||||
private ContentItemRepository itemRepo;
|
||||
|
||||
@Inject
|
||||
private PermissionChecker permissionChecker;
|
||||
|
||||
private Locale defaultLocale;
|
||||
private List<Locale> supportedLocales;
|
||||
|
||||
|
|
@ -112,6 +118,50 @@ public class ContentItemL10NManager {
|
|||
return locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for reading methods in this class for verifying that the
|
||||
* current user is permitted to read the item.
|
||||
*
|
||||
* If the provided {@code item} is a live item
|
||||
* ({@link ContentItem#getVersion()} returns
|
||||
* {@link ContentItemVersion#LIVE}) the current user needs the a permission
|
||||
* which grants the {@link ItemPrivileges#VIEW_PUBLISHED} privilege for the
|
||||
* provided {@code item}. If the item is a draft item
|
||||
* ({@link ContentItem#getVersion()} returns
|
||||
* {@link ContentItemVersion#DRAFT}, {@link ContentItemVersion#PENDING} or
|
||||
* {@link ContentItemVersion#PUBLISHING} the user needs a permission which
|
||||
* grants the {@link ItemPrivileges#PREVIEW} privilege for the provided
|
||||
* {@code item}.
|
||||
*
|
||||
* @param item The item for which the read permission is verified.
|
||||
*/
|
||||
private void checkReadPermission(final ContentItem item) {
|
||||
final String requiredPrivilege;
|
||||
if (ContentItemVersion.LIVE == item.getVersion()) {
|
||||
requiredPrivilege = ItemPrivileges.VIEW_PUBLISHED;
|
||||
} else {
|
||||
requiredPrivilege = ItemPrivileges.PREVIEW;
|
||||
}
|
||||
|
||||
permissionChecker.checkPermission(requiredPrivilege, item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all languages in which content item is available.
|
||||
*
|
||||
* @param item The item.
|
||||
*
|
||||
* @return A (unmodifiable) {@link Set} containing all languages in which
|
||||
* the item is available.
|
||||
*/
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Set<Locale> availableLanguages(
|
||||
final ContentItem item) {
|
||||
|
||||
checkReadPermission(item);
|
||||
return Collections.unmodifiableSet(collectLanguages(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an content item has data for particular language.
|
||||
*
|
||||
|
|
@ -121,8 +171,13 @@ public class ContentItemL10NManager {
|
|||
* @return {@link true} if the item has data for the language, {@code false}
|
||||
* if not.
|
||||
*/
|
||||
@AuthorizationRequired
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public boolean hasLanguage(final ContentItem item, final Locale locale) {
|
||||
public boolean hasLanguage(
|
||||
@RequiresPrivilege(ItemPrivileges.VIEW_PUBLISHED)
|
||||
final ContentItem item,
|
||||
final Locale locale) {
|
||||
|
||||
if (item == null) {
|
||||
throw new IllegalArgumentException("Can't check if item null has a"
|
||||
+ "specific locale.");
|
||||
|
|
@ -132,14 +187,27 @@ public class ContentItemL10NManager {
|
|||
throw new IllegalArgumentException("Can't check for locale null.");
|
||||
}
|
||||
|
||||
checkReadPermission(item);
|
||||
|
||||
return collectLanguages(item).contains(locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} containing the locales for which the item does not
|
||||
* yet have a variant.
|
||||
*
|
||||
* @param item The item.
|
||||
*
|
||||
* @return A {@link Set} with the locales for which the item does not have a
|
||||
* variant.
|
||||
*/
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
public Set<Locale> creatableLocales(final ContentItem item) {
|
||||
checkReadPermission(item);
|
||||
|
||||
return supportedLocales.stream()
|
||||
.filter(locale -> hasLanguage(item, locale))
|
||||
.collect(Collectors.toSet());
|
||||
.filter(locale -> hasLanguage(item, locale))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -149,7 +217,11 @@ public class ContentItemL10NManager {
|
|||
* configured in {@link KernelConfig}. If a field does not have an entry for
|
||||
* the default language the first value found is used.
|
||||
*
|
||||
* @param item The item to which the language variant is added.
|
||||
* @param item The item to which the language variant is added. The item
|
||||
* <strong>must be</strong> the <strong>draft version</strong>
|
||||
* of the item! If a <em>live version</em> or a
|
||||
* <em>pending version</em> is provided the method will throw an
|
||||
* {@link IllegalArgumentException}!
|
||||
* @param locale The locale of the language variant to add.
|
||||
*/
|
||||
@AuthorizationRequired
|
||||
|
|
@ -160,7 +232,14 @@ public class ContentItemL10NManager {
|
|||
final Locale locale) {
|
||||
|
||||
if (item == null) {
|
||||
throw new IllegalArgumentException("Can't add language to item null.");
|
||||
throw new IllegalArgumentException(
|
||||
"Can't add language to item null.");
|
||||
}
|
||||
|
||||
if (ContentItemVersion.DRAFT != item.getVersion()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"The provided item %s is not the draft version of an item.",
|
||||
Objects.toString(item)));
|
||||
}
|
||||
|
||||
if (locale == null) {
|
||||
|
|
@ -220,7 +299,11 @@ public class ContentItemL10NManager {
|
|||
* the entry for the provided locale if the field has an entry for that
|
||||
* locale.
|
||||
*
|
||||
* @param item The item from which the language variant is removed.
|
||||
* @param item The item from which the language variant is removed. The
|
||||
* item <strong>must be</strong> the <strong>draft
|
||||
* version</strong> of the item! If a <em>live version</em> or
|
||||
* a <em>pending version</em> is provided the method will
|
||||
* throw an {@link IllegalArgumentException}!
|
||||
* @param locale The locale of the language variant to remove.
|
||||
*/
|
||||
@AuthorizationRequired
|
||||
|
|
@ -235,6 +318,12 @@ public class ContentItemL10NManager {
|
|||
"Can't remove language from item null.");
|
||||
}
|
||||
|
||||
if (ContentItemVersion.DRAFT != item.getVersion()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"The provided item %s is not the draft version of an item.",
|
||||
Objects.toString(item)));
|
||||
}
|
||||
|
||||
if (locale == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't remove language null from an item.");
|
||||
|
|
@ -268,7 +357,10 @@ public class ContentItemL10NManager {
|
|||
* {@link LocalizedString} has an entry for every language in the set. If
|
||||
* not an entry for the language is added.
|
||||
*
|
||||
* @param item The item to normalise.
|
||||
* @param item The item to normalise. The item <strong>must be</strong> the
|
||||
* <strong>draft version</strong> of the item! If a <em>live
|
||||
* version</em> or a <em>pending version</em> is provided the
|
||||
* method will throw an {@link IllegalArgumentException}!
|
||||
*/
|
||||
@AuthorizationRequired
|
||||
@Transactional(Transactional.TxType.REQUIRED)
|
||||
|
|
@ -280,6 +372,12 @@ public class ContentItemL10NManager {
|
|||
throw new IllegalArgumentException("Can't normalise item null.");
|
||||
}
|
||||
|
||||
if (ContentItemVersion.DRAFT != item.getVersion()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"The provided item %s is not the draft version of an item.",
|
||||
Objects.toString(item)));
|
||||
}
|
||||
|
||||
final Set<Locale> languages = collectLanguages(item);
|
||||
|
||||
findLocalizedStringProperties(item)
|
||||
|
|
|
|||
Loading…
Reference in New Issue