diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/SelectedLanguageUtil.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/SelectedLanguageUtil.java
new file mode 100644
index 000000000..9e005c042
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/SelectedLanguageUtil.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 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.authoring;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.kernel.KernelConfig;
+
+import java.util.Locale;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class SelectedLanguageUtil {
+
+ private SelectedLanguageUtil() {
+ //Nothing
+ }
+
+ public static final Locale selectedLocale(
+ final PageState state,
+ final StringParameter selectedLanguageParam) {
+
+ final String selectedLanguage = (String) state
+ .getValue(selectedLanguageParam);
+ if (selectedLanguage == null) {
+ return KernelConfig.getConfig().getDefaultLocale();
+ } else {
+ return new Locale(selectedLanguage);
+ }
+ }
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/multipartarticle/SectionTableModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/multipartarticle/SectionTableModel.java
new file mode 100644
index 000000000..500b224ef
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/multipartarticle/SectionTableModel.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2017 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.authoring.multipartarticle;
+
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.librecms.CmsConstants;
+import org.librecms.contenttypes.MultiPartArticle;
+import org.librecms.contenttypes.MultiPartArticleSection;
+
+import java.util.Iterator;
+import java.util.List;
+
+class SectionTableModel implements TableModel {
+
+ private final TableColumnModel columnModel;
+ private final SectionTable sectionTable;
+ private final PageState pageState;
+ private final SectionSelectionModel extends MultiPartArticleSection> moveSectionModel;
+
+ private final Iterator iterator;
+ private MultiPartArticleSection currentSection;
+
+ /**
+ * Constructor.
+ *
+ * @param sectionTable
+ * @param pageState
+ * @param article
+ * @param moveSectionModel
+ */
+ public SectionTableModel(
+ final Table sectionTable,
+ final PageState pageState,
+ final MultiPartArticle article,
+ final SectionSelectionModel extends MultiPartArticleSection> moveSectionModel) {
+
+ this.pageState = pageState;
+ this.sectionTable = (SectionTable) sectionTable;
+ this.moveSectionModel = moveSectionModel;
+
+ columnModel = sectionTable.getColumnModel();
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final MultiPartArticleSectionStepController controller = cdiUtil
+ .findBean(MultiPartArticleSectionStepController.class);
+
+ final List sections = controller
+ .retrieveSections(article);
+ iterator = sections.iterator();
+ }
+
+ /**
+ * Return the number of columns this TableModel has.
+ */
+ @Override
+ public int getColumnCount() {
+ return columnModel.size();
+ }
+
+ /**
+ * Move to the next row and return true if the model is now positioned on a
+ * valid row.
+ */
+ @Override
+ public boolean nextRow() {
+
+ if (iterator.hasNext()) {
+ currentSection = iterator.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return the data element for the given column and the current row.
+ */
+ @Override
+ public Object getElementAt(final int columnIndex) {
+
+ if (columnModel == null) {
+ return null;
+ }
+ switch (columnIndex) {
+ case SectionTable.COL_INDEX_TITLE:
+ return currentSection.getTitle();
+ case SectionTable.COL_INDEX_EDIT:
+ return new Label(new GlobalizedMessage(
+ "cms.contenttypes.ui.mparticle.section_table.link_edit",
+ CmsConstants.CMS_BUNDLE));
+ case SectionTable.COL_INDEX_DELETE:
+ return new Label(new GlobalizedMessage(
+ "cms.contenttypes.ui.mparticle.section_table.link_delete",
+ CmsConstants.CMS_BUNDLE));
+ case SectionTable.COL_INDEX_MOVE:
+ if (moveSectionModel.getSelectedKey(pageState) == null) {
+ return new Label(new GlobalizedMessage(
+ "cms.contenttypes.ui.mparticle.section_table.link_move",
+ CmsConstants.CMS_BUNDLE));
+ } else {
+ return new Label(new GlobalizedMessage(
+ "cms.contenttypes.ui.mparticle.section_table.link_move_below",
+ CmsConstants.CMS_BUNDLE));
+ }
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Return the key for the given column and the current row.
+ */
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return currentSection.getSectionId();
+ }
+
+}