diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/AbstractContactableEntityForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/AbstractContactableEntityForm.java
new file mode 100644
index 000000000..54b1a3f55
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/AbstractContactableEntityForm.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2019 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.assets.forms;
+
+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.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.form.TextField;
+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.ui.assets.AbstractAssetForm;
+import com.arsdigita.cms.ui.assets.AssetPane;
+import com.arsdigita.cms.ui.assets.AssetSearchWidget;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.librecms.CmsConstants;
+import org.librecms.assets.ContactEntry;
+import org.librecms.assets.ContactableEntity;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ * @param
+ */
+public abstract class AbstractContactableEntityForm
+ extends AbstractAssetForm {
+
+ private static final int COL_CONTACT_ENTRIES_KEY = 0;
+
+ private static final int COL_CONTACT_ENTRIES_VALUE = 1;
+
+ private static final int COL_CONTACT_ENTRIES_REMOVE = 2;
+
+ private Table contactEntriesTable;
+
+ private SingleSelect contactEntryKeySelect;
+
+ private TextField contactEntryValueField;
+
+ private AssetSearchWidget postalAddressSearchWidget;
+
+ public AbstractContactableEntityForm(final AssetPane assetPane) {
+ super(assetPane);
+ }
+
+ @Override
+ protected void addWidgets() {
+
+ contactEntriesTable = buildContactEntriesTable();
+
+ }
+
+ private Table buildContactEntriesTable() {
+
+ final Table table = new Table();
+ final TableColumnModel columnModel = table.getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_CONTACT_ENTRIES_KEY,
+ new Label(
+ new GlobalizedMessage(
+ "cms.ui.authoring.assets.contactable.contactentries.key",
+ CmsConstants.CMS_BUNDLE
+ )
+ )
+ ));
+ columnModel.add(new TableColumn(
+ COL_CONTACT_ENTRIES_VALUE,
+ new Label(
+ new GlobalizedMessage(
+ "cms.ui.authoring.assets.contactable.contactentries.value",
+ CmsConstants.CMS_BUNDLE
+ )
+ )
+ ));
+ columnModel.add(new TableColumn(
+ COL_CONTACT_ENTRIES_REMOVE,
+ new Label(
+ new GlobalizedMessage(
+ "cms.ui.authoring.assets.contactable.contactentries.remove",
+ CmsConstants.CMS_BUNDLE
+ )
+ )
+ ));
+
+ table.setModelBuilder(new ContactEntriesTableModelBuilder());
+
+ table
+ .getColumn(COL_CONTACT_ENTRIES_REMOVE)
+ .setCellRenderer(new ContactEntryRemoveCellRenderer());
+
+ table.setEmptyView(
+ new Label(
+ new GlobalizedMessage(
+ "cms.ui.authoring.assets.contactable.contactentries.none",
+ CmsConstants.CMS_BUNDLE
+ )
+ )
+ );
+
+ table.addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event)
+ throws FormProcessException {
+
+ final Integer rowKey = (Integer) event.getRowKey();
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final ContactableEntityFormController controller = cdiUtil
+ .findBean(ContactableEntityFormController.class);
+ final Optional selected = getSelectedAsset(event
+ .getPageState());
+ if (selected.isPresent()) {
+ controller.removeContactEntry(selected.get(), rowKey);
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+
+ // Nothing
+ }
+
+ });
+
+ return table;
+ }
+
+ private class ContactEntriesTableModelBuilder
+ extends LockableImpl implements TableModelBuilder {
+
+ private final ContactableEntity contactableEntity;
+
+ public ContactEntriesTableModelBuilder(
+ final ContactableEntity contactableEntity) {
+
+ this.contactableEntity = contactableEntity;
+ }
+
+ @Override
+ public TableModel makeModel(final Table table,
+ final PageState state) {
+
+ final List contactEntries = contactableEntity
+ .getContactEntries();
+ return new ContactEntriesTableModel(contactEntries);
+ }
+
+ }
+
+ private class ContactEntriesTableModel implements TableModel {
+
+ private final Iterator contactEntries;
+
+ private ContactEntry currentContactEntry;
+
+ public ContactEntriesTableModel(
+ final List contactEntries) {
+
+ this.contactEntries = contactEntries.iterator();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public boolean nextRow() {
+
+ if (contactEntries.hasNext()) {
+ currentContactEntry = contactEntries.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+
+ switch (columnIndex) {
+ case COL_CONTACT_ENTRIES_KEY:
+ return currentContactEntry.getKey();
+ case COL_CONTACT_ENTRIES_VALUE:
+ return currentContactEntry.getValue();
+ case COL_CONTACT_ENTRIES_REMOVE:
+ return new Label(
+ new GlobalizedMessage(
+ "cms.ui.authoring.assets.contactable"
+ + ".contactentries.remove",
+ CmsConstants.CMS_BUNDLE
+ )
+ );
+ default:
+ throw new IllegalArgumentException(String.format(
+ "Illegal column index %d.", columnIndex));
+
+ }
+ }
+
+ @Override
+ public Object getKeyAt(int columnIndex) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ }
+
+ private class ContactEntryRemoveCellRenderer 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 ControlLink((Component) value);
+ }
+
+ }
+
+}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/ContactableEntityFormController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/ContactableEntityFormController.java
new file mode 100644
index 000000000..27a639a1b
--- /dev/null
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/forms/ContactableEntityFormController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.assets.forms;
+
+import org.librecms.assets.ContactEntry;
+import org.librecms.assets.ContactableEntity;
+import org.librecms.assets.ContactableEntityManager;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+public class ContactableEntityFormController {
+
+ @Inject
+ private ContactableEntityManager contactableEntityManager;
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public void addContactEntry(final ContactEntry contactEntry,
+ final ContactableEntity toContactableEntity) {
+
+ contactableEntityManager
+ .addContactEntryToContactableEntity(contactEntry,
+ toContactableEntity);
+
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public void removeContactEntry(final ContactableEntity contactableEntity,
+ final int index) {
+
+ if (contactableEntity.getContactEntries().size() > index) {
+
+ final ContactEntry contactEntry = contactableEntity
+ .getContactEntries()
+ .get(index);
+ contactableEntityManager.removeContactEntryFromContactableEntity(
+ contactEntry, contactableEntity);
+ }
+
+ }
+
+}
diff --git a/ccm-cms/src/main/java/org/librecms/Cms.java b/ccm-cms/src/main/java/org/librecms/Cms.java
index 4f9e7abf0..bb03e40a7 100644
--- a/ccm-cms/src/main/java/org/librecms/Cms.java
+++ b/ccm-cms/src/main/java/org/librecms/Cms.java
@@ -33,6 +33,9 @@ import org.librecms.assets.ExternalVideoAsset;
import org.librecms.assets.FileAsset;
import org.librecms.assets.Image;
import org.librecms.assets.LegalMetadata;
+import org.librecms.assets.Organization;
+import org.librecms.assets.Person;
+import org.librecms.assets.PostalAddress;
import org.librecms.assets.SideNote;
import org.librecms.assets.VideoAsset;
@@ -69,8 +72,7 @@ import java.util.Properties;
descBundle = CmsConstants.CONTENT_CENTER_DESC_BUNDLE,
creator = ContentCenterAppCreator.class,
servlet = ContentCenterServlet.class
- )
- ,
+ ),
@ApplicationType(
name = CmsConstants.CONTENT_SECTION_APP_TYPE,
applicationClass = ContentSection.class,
@@ -79,8 +81,7 @@ import java.util.Properties;
descBundle = CmsConstants.CONTENT_SECTION_DESC_BUNDLE,
creator = ContentSectionCreator.class,
servletPath = "/templates/servlet/content-section"
- )
- ,
+ ),
@ApplicationType(
name = "org.librecms.pages.Pages",
applicationClass = Pages.class,
@@ -100,16 +101,14 @@ import java.util.Properties;
titleKey
= "cms.ui.pagemodel.components.categorized_item_component.title",
descKey
- = "cms.ui.pagemodel.components.categorized_item_component.desc")
- ,
+ = "cms.ui.pagemodel.components.categorized_item_component.desc"),
@PageModelComponentModel(
modelClass = CategoryTreeComponent.class,
editor = CategoryTreeComponentForm.class,
descBundle = CmsConstants.CMS_BUNDLE,
titleKey
= "cms.ui.pagemodel.components.category_tree_component.title",
- descKey = "cms.ui.pagemodel.components.category_tree_component.desc")
- ,
+ descKey = "cms.ui.pagemodel.components.category_tree_component.desc"),
@PageModelComponentModel(
modelClass = FixedContentItemComponent.class,
editor = FixedContentItemComponentForm.class,
@@ -117,16 +116,14 @@ import java.util.Properties;
titleKey
= "cms.ui.pagemodel.components.fixed_contentitem_component.title",
descKey
- = "cms.ui.pagemodel.components.fixed_contentitem_component.desc")
- ,
+ = "cms.ui.pagemodel.components.fixed_contentitem_component.desc"),
@PageModelComponentModel(
modelClass = GreetingItemComponent.class,
editor = GreetingItemComponentForm.class,
descBundle = CmsConstants.CMS_BUNDLE,
titleKey
= "cms.ui.pagemodel.components.greetingitem_component.title",
- descKey = "cms.ui.pagemodel.components.greetingitem_component.desc")
- ,
+ descKey = "cms.ui.pagemodel.components.greetingitem_component.desc"),
@PageModelComponentModel(
modelClass = ItemListComponent.class,
editor = ItemListComponentForm.class,
@@ -138,7 +135,8 @@ import java.util.Properties;
@ContentTypes({Article.class,
Event.class,
MultiPartArticle.class,
- News.class})
+ News.class
+})
@AssetTypes({AudioAsset.class,
VideoAsset.class,
Bookmark.class,
@@ -147,7 +145,11 @@ import java.util.Properties;
FileAsset.class,
Image.class,
LegalMetadata.class,
- SideNote.class})
+ Organization.class,
+ Person.class,
+ PostalAddress.class,
+ SideNote.class
+})
public class Cms implements CcmModule {
private static final Logger LOGGER = LogManager.getLogger(Cms.class);
diff --git a/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java b/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java
index 6ceb8a555..c6ea3f393 100644
--- a/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java
+++ b/ccm-cms/src/main/java/org/librecms/assets/ContactableEntity.java
@@ -37,7 +37,7 @@ import javax.persistence.Table;
import static org.librecms.CmsConstants.*;
/**
- * Base class for contactable entities.
+ * Base class for contactable entities. Not for public use
*
* @author Jens Pelzetter
*/
diff --git a/ccm-cms/src/main/java/org/librecms/assets/Person.java b/ccm-cms/src/main/java/org/librecms/assets/Person.java
index bd94b04be..98b064e15 100644
--- a/ccm-cms/src/main/java/org/librecms/assets/Person.java
+++ b/ccm-cms/src/main/java/org/librecms/assets/Person.java
@@ -18,6 +18,8 @@
*/
package org.librecms.assets;
+import org.hibernate.envers.Audited;
+
import java.time.LocalDate;
import java.util.Objects;
@@ -26,6 +28,7 @@ import javax.persistence.Entity;
import javax.persistence.Table;
import static org.librecms.CmsConstants.*;
+import static org.librecms.assets.AssetConstants.*;
/**
* An asset representing a person.
@@ -34,6 +37,12 @@ import static org.librecms.CmsConstants.*;
*/
@Entity
@Table(name = "PERSONS", schema = DB_SCHEMA)
+@Audited
+//@AssetType(assetForm = PersonForm.class,
+// labelBundle = ASSETS_BUNDLE,
+// labelKey = "person.label",
+// descriptionBundle = ASSETS_BUNDLE,
+// descriptionKey = "person.description")
public class Person extends ContactableEntity {
private static final long serialVersionUID = 1L;