diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java
index 95b1ed29c..718faddbb 100755
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowser.java
@@ -58,6 +58,7 @@ import org.librecms.contentsection.ContentSectionManager;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.dispatcher.ItemResolver;
+import java.util.Date;
import java.util.List;
import java.util.Locale;
@@ -126,13 +127,16 @@ public class FolderBrowser extends Table {
nameColumn = getColumn(0);
nameColumn.setCellRenderer(new NameCellRenderer());
-// nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
+ nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
getColumn(1).setCellRenderer(new LanguagesCellRenderer());
-// getColumn(2).setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_TITLE));
-// getColumn(5).setHeaderRenderer(new HeaderCellRenderer(
-// SORT_KEY_CREATION_DATE));
-// getColumn(6).setHeaderRenderer(new HeaderCellRenderer(
-// SORT_KEY_LAST_MODIFIED_DATE));
+ getColumn(4).setHeaderRenderer(new HeaderCellRenderer(
+ SORT_KEY_CREATION_DATE));
+
+ getColumn(4).setCellRenderer(new DateCellRenderer());
+ getColumn(5).setCellRenderer(new DateCellRenderer());
+ getColumn(5).setHeaderRenderer(new HeaderCellRenderer(
+ SORT_KEY_LAST_MODIFIED_DATE));
+
deleteColumn = getColumn(6);
deleteColumn.setCellRenderer(new ActionCellRenderer());
deleteColumn.setAlign("center");
@@ -239,6 +243,14 @@ public class FolderBrowser extends Table {
return (String) state.getValue(atozFilterParameter);
}
+ protected String getSortType(final PageState state) {
+ return (String) state.getValue(sortTypeParameter);
+ }
+
+ protected String getSortDirection(final PageState state) {
+ return (String) state.getValue(sortDirectionParameter);
+ }
+
private class HeaderCellRenderer
extends com.arsdigita.cms.ui.util.DefaultTableCellRenderer {
@@ -273,7 +285,7 @@ public class FolderBrowser extends Table {
final ControlLink link = new ControlLink(new Label(headerName)) {
@Override
- public void setControlEvent(PageState ps) {
+ public void setControlEvent(final PageState state) {
String sortDirectionAction;
// by default, everything sorts "up" unless it
// is the current key and it is already pointing up
@@ -283,9 +295,9 @@ public class FolderBrowser extends Table {
} else {
sortDirectionAction = SORT_ACTION_UP;
}
- ps.setControlEvent(table,
- sortDirectionAction,
- headerKey);
+ state.setControlEvent(table,
+ sortDirectionAction,
+ headerKey);
}
};
@@ -431,6 +443,28 @@ public class FolderBrowser extends Table {
}
+ private class DateCellRenderer 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) {
+ if (value instanceof Date) {
+ final Date date = (Date) value;
+ return new Text(String.format("%1$TF %1$TT", date));
+ } else if (value == null) {
+ return new Text("");
+ } else {
+ return new Text(value.toString());
+ }
+ }
+
+ }
+
/**
* Produce delete links for items and non-empty folders.
*/
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java
index 79ebb687f..0ce23171a 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserController.java
@@ -20,14 +20,11 @@ package com.arsdigita.cms.ui.folder;
import com.arsdigita.kernel.KernelConfig;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
import org.libreccm.categorization.Categorization;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository;
import org.libreccm.l10n.GlobalizationHelper;
-import org.libreccm.l10n.LocalizedString;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemL10NManager;
@@ -55,24 +52,25 @@ import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
-import org.hibernate.envers.AuditReader;
+
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Path;
/**
+ * The {@code FolderBrowserController} wraps all database operations (queries)
+ * required by the {@link FolderBrowser}, the
+ * {@link FolderBrowserTableModelBuilder} and the
+ * {@link FolderBrowserTableModel}.
*
* @author Jens Pelzetter
*/
@RequestScoped
public class FolderBrowserController {
- private static final Logger LOGGER = LogManager.getLogger(
- FolderBrowserController.class);
-
@Inject
private EntityManager entityManager;
- @Inject
- private AuditReader auditReader;
-
@Inject
private CcmObjectRepository objectRepo;
@@ -90,189 +88,296 @@ public class FolderBrowserController {
private Locale defaultLocale;
+ /**
+ * Initialisation method called by the CDI-Container after an instance of
+ * this class has be created by the container. Sets the
+ * {@link #defaultLocale} property using the the value from the
+ * {@link KernelConfig}.
+ */
@PostConstruct
private void init() {
final KernelConfig kernelConfig = confManager.findConfiguration(
- KernelConfig.class);
+ KernelConfig.class);
defaultLocale = kernelConfig.getDefaultLocale();
}
- public List findObjects(final Folder folder, final String orderBy) {
- return findObjects(folder, orderBy, -1, -1);
- }
-
- public List findObjects(final Folder folder,
- final String orderBy,
- final int first,
- final int maxResults) {
- return findObjects(folder, "%", orderBy, first, maxResults);
- }
-
- public List findObjects(final Folder folder,
- final String filterTerm,
- final String orderBy) {
- return findObjects(folder, filterTerm, orderBy, -1, -1);
- }
-
- public List findObjects(final Folder folder,
- final String filterTerm,
- final String orderBy,
- final int first,
- final int maxResults) {
-
- Objects.requireNonNull(folder);
- LOGGER.debug("Trying to find objects in folder {}...",
- Objects.toString(folder));
-
- final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
- final CriteriaQuery criteriaQuery = builder
- .createQuery(CcmObject.class);
- final Root from = criteriaQuery.from(CcmObject.class);
-
- return entityManager.createQuery(
- criteriaQuery
- .select(from)
- .where(builder.or(
- from.in(findSubFolders(folder, filterTerm)),
- from.in(findItemsInFolder(folder, filterTerm))))
- .orderBy(builder.asc(from.get("displayName"))))
- .setFirstResult(first)
- .setMaxResults(maxResults)
- .getResultList();
- }
-
+ /**
+ * Count the objects (subfolders and content items) in the provided folder.
+ *
+ * @param folder The folder.
+ *
+ * @return The number of objects (subfolders and content items) in the
+ * provided {@code folder}.
+ */
public long countObjects(final Folder folder) {
return countObjects(folder, "%");
}
+ /**
+ * Count all objects (subfolders and content items) in the provided folder
+ * which match the provided filter term.
+ *
+ * @param folder The folder.
+ * @param filterTerm The filter term.
+ *
+ * @return The number of objects (subfolders and content items) in the
+ * provided {@code folder} which match the provided
+ * {@code filterTerm}.
+ */
public long countObjects(final Folder folder,
final String filterTerm) {
+ Objects.requireNonNull(folder, "Can't count objects in Folder null.");
+ Objects.requireNonNull(filterTerm, "Can't filter for 'null'.");
+
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
- final CriteriaQuery criteriaQuery = builder.createQuery(
- Long.class);
+ CriteriaQuery criteriaQuery = builder.createQuery(Long.class);
final Root from = criteriaQuery.from(CcmObject.class);
- return entityManager
- .createQuery(
- criteriaQuery
- .select(builder.count(from))
- .where(builder.or(
- from.in(findSubFolders(folder,
- filterTerm)),
- from.in(findItemsInFolder(folder,
- filterTerm))))).
- getSingleResult();
- }
-
- @Transactional(Transactional.TxType.REQUIRED)
- List getObjectRows(final Folder folder,
- final String orderBy) {
- final List objects = findObjects(folder, orderBy);
-
- return objects.stream()
- .map(object -> buildRow(object))
- .collect(Collectors.toList());
- }
-
- @Transactional(Transactional.TxType.REQUIRED)
- List getObjectRows(final Folder folder,
- final String filterTerm,
- final String orderBy) {
- final List objects = findObjects(folder,
- filterTerm,
- orderBy);
-
- return objects.stream()
- .map(object -> buildRow(object))
- .collect(Collectors.toList());
+ criteriaQuery = criteriaQuery.select(builder.count(from));
+
+ final List subFolders = findSubFolders(folder,
+ filterTerm,
+ FolderBrowser.SORT_KEY_NAME,
+ FolderBrowser.SORT_ACTION_UP,
+ -1,
+ -1);
+ final List items = findItemsInFolder(folder,
+ filterTerm,
+ FolderBrowser.SORT_KEY_NAME,
+ FolderBrowser.SORT_ACTION_UP,
+ -1,
+ -1);
+ if (subFolders.isEmpty() && items.isEmpty()) {
+ return 0;
+ } else if (subFolders.isEmpty() && !items.isEmpty()) {
+ criteriaQuery = criteriaQuery.where(from.in(items));
+ } else if (!subFolders.isEmpty() && items.isEmpty()) {
+ criteriaQuery = criteriaQuery.where(from.in(subFolders));
+ } else {
+ criteriaQuery = criteriaQuery.where(builder.or(
+ from.in(subFolders),
+ from.in(items)));
+ }
+
+ return entityManager.createQuery(criteriaQuery).getSingleResult();
}
+ /**
+ * Create {@link FolderBrowserTableRow} objects for all objects in the
+ * provided folder.
+ *
+ * @param folder The folder which contains the objects.
+ * @param orderBy The field used to order the objects.
+ * @param orderDirection The direction for ordering the objects.
+ *
+ * @return A list with {@link FolderBrowserTableRow} objects for each object
+ * in the provided {@code folder} ordered by the provided field and
+ * in the provided direction.
+ */
@Transactional(Transactional.TxType.REQUIRED)
List getObjectRows(final Folder folder,
final String orderBy,
- final int first,
- final int maxResults) {
- final List objects = findObjects(folder,
- orderBy,
- first,
- maxResults);
-
- return objects.stream()
- .map(object -> buildRow(object))
- .collect(Collectors.toList());
+ final String orderDirection) {
+ return getObjectRows(folder, "%", orderBy, orderDirection, -1, -1);
}
+ /**
+ * Create {@link FolderBrowserTableRow} objects for all objects in the
+ * provided folder which match provided filter term.
+ *
+ * @param folder The folder which contains the objects.
+ * @param filterTerm The filter term.
+ * @param orderBy The field used to order the objects.
+ * @param orderDirection The direction for ordering the objects.
+ *
+ * @return A list with {@link FolderBrowserTableRow} objects for each object
+ * in the provided {@code folder} which matches the provided
+ * {@code filterTerm}, ordered by the provided field and in the
+ * provided direction.
+ */
@Transactional(Transactional.TxType.REQUIRED)
List getObjectRows(final Folder folder,
final String filterTerm,
final String orderBy,
- final int first,
- final int maxResults) {
- final List objects = findObjects(folder,
- filterTerm,
- orderBy,
- first,
- maxResults);
-
- return objects.stream()
- .map(object -> buildRow(object))
- .collect(Collectors.toList());
+ final String orderDirection) {
+ return getObjectRows(folder,
+ filterTerm,
+ orderBy,
+ orderDirection,
+ -1,
+ -1);
}
- private FolderBrowserTableRow buildRow(final CcmObject object) {
+ /**
+ * Create {@link FolderBrowserTableRow} objects for the objects in the
+ * provided folder which are in the range provided by {@code firstResult}
+ * and {@code maxResult}
+ *
+ * @param folder The folder which contains the objects.
+ * @param orderBy The field used to order the objects.
+ * @param orderDirection The direction for ordering the objects.
+ * @param firstResult The index of the first object to use.
+ * @param maxResults The maximum number of objects to retrieve.
+ *
+ * @return A list with {@link FolderBrowserTableRow} objects for each object
+ * in the provided {@code folder} ordered by the provided field and
+ * in the provided direction. The list will start with the object
+ * with index provided as {@code firstResult} and contain at most
+ * {@code maxResults} items.
+ */
+ @Transactional(Transactional.TxType.REQUIRED)
+ List getObjectRows(final Folder folder,
+ final String orderBy,
+ final String orderDirection,
+ final int firstResult,
+ final int maxResults) {
+ return getObjectRows(folder,
+ "%",
+ orderBy,
+ orderDirection,
+ firstResult,
+ maxResults);
+ }
+
+ /**
+ * Create {@link FolderBrowserTableRow} objects for the objects in the
+ * provided folder which match the provided filter term and which are in the
+ * range provided by {@code firstResult} and {@code maxResult}
+ *
+ * @param folder The folder which contains the objects.
+ * @param filterTerm The filter term.
+ * @param orderBy The field used to order the objects.
+ * @param orderDirection The direction for ordering the objects.
+ * @param firstResult The index of the first object to use.
+ * @param maxResults The maximum number of objects to retrieve.
+ *
+ * @return A list with {@link FolderBrowserTableRow} objects for each object
+ * in the provided {@code folder} which matches the provided
+ * {@code filterTerm}, ordered by the provided field and in the
+ * provided direction. The list will start with the object with
+ * index provided as {@code firstResult} and contain at most
+ * {@code maxResults} items.
+ */
+ @Transactional(Transactional.TxType.REQUIRED)
+ List getObjectRows(final Folder folder,
+ final String filterTerm,
+ final String orderBy,
+ final String orderDirection,
+ final int firstResult,
+ final int maxResults) {
+ final List subFolders = findSubFolders(folder,
+ filterTerm,
+ orderBy,
+ orderDirection,
+ firstResult,
+ maxResults);
+ final List subFolderRows = subFolders.stream()
+ .map(subFolder -> buildRow(subFolder))
+ .collect(Collectors.toList());
+
+ if (subFolders.size() > maxResults) {
+ return subFolderRows;
+ } else {
+ final int maxItems = maxResults - subFolders.size();
+ final int firstItem = firstResult - subFolders.size();
+
+ final List items = findItemsInFolder(folder,
+ filterTerm,
+ orderBy,
+ orderDirection,
+ firstItem,
+ maxItems);
+ final List itemRows = items.stream()
+ .map(item -> buildRow(item))
+ .collect(Collectors.toList());
+
+ final ArrayList rows = new ArrayList<>();
+ rows.addAll(subFolderRows);
+ rows.addAll(itemRows);
+
+ return rows;
+ }
+ }
+
+ /**
+ * Helper method for building a {@link FolderBrowserTableRow} from a
+ * {@link Folder}.
+ *
+ * @param folder The {@link Folder} to use for building the
+ * {@link FolderBrowserTableRow}.
+ *
+ * @return A {@link FolderBrowserTableRow} containing the data needed by the
+ * {@link FolderBrowser} to display the provided {@code folder}.
+ */
+ private FolderBrowserTableRow buildRow(final Folder folder) {
+
final FolderBrowserTableRow row = new FolderBrowserTableRow();
- if (object instanceof Folder) {
- final Folder folder = (Folder) object;
- row.setObjectId(folder.getObjectId());
- row.setObjectUuid(folder.getUuid());
- row.setName(folder.getName());
- row.setLanguages(Collections.emptyList());
- if (folder.getTitle().hasValue(globalizationHelper
- .getNegotiatedLocale())) {
- row.setTitle(folder.getTitle().getValue(globalizationHelper
- .getNegotiatedLocale()));
- } else {
- row.setTitle(folder.getTitle().getValue(defaultLocale));
- }
- row.setFolder(true);
- } else if (object instanceof ContentItem) {
- final ContentItem item = (ContentItem) object;
- row.setObjectId(item.getObjectId());
- row.setObjectUuid(item.getItemUuid());
- row.setName(item.getName().getValue(defaultLocale));
- final List languages = new ArrayList<>(itemL10NManager
- .availableLanguages(item));
- languages.sort((lang1, lang2) -> lang1.toString().compareTo(
- lang2.toString()));
- row.setLanguages(languages);
- if (item.getTitle().hasValue(globalizationHelper
- .getNegotiatedLocale())) {
- row.setTitle(item.getTitle().getValue(globalizationHelper
- .getNegotiatedLocale()));
- } else {
- row.setTitle(item.getTitle().getValue(defaultLocale));
- }
- final ContentType type = item.getContentType();
- final ContentTypeInfo typeInfo = typesManager.getContentTypeInfo(
- type);
- row.setTypeLabelBundle(typeInfo.getLabelBundle());
- row.setTypeLabelKey(typeInfo.getLabelKey());
- row.setFolder(false);
+ row.setObjectId(folder.getObjectId());
+ row.setObjectUuid(folder.getUuid());
+ row.setName(folder.getName());
+ row.setLanguages(Collections.emptyList());
+ if (folder.getTitle().hasValue(globalizationHelper
+ .getNegotiatedLocale())) {
+ row.setTitle(folder.getTitle().getValue(globalizationHelper
+ .getNegotiatedLocale()));
} else {
- row.setObjectId(object.getObjectId());
- row.setObjectUuid(object.getUuid());
- row.setName("???");
- row.setLanguages(Collections.emptyList());
- final LocalizedString title = new LocalizedString();
- title.addValue(globalizationHelper.getNegotiatedLocale(), "???");
- row.setFolder(false);
+ row.setTitle(folder.getTitle().getValue(defaultLocale));
}
+ row.setFolder(true);
return row;
}
+ /**
+ * Helper method for building a {@link FolderBrowserTableRow} from a
+ * {@link ContentItem}.
+ *
+ * @param item The {@link ContentItem} to use for building the
+ * {@link FolderBrowserTableRow}.
+ *
+ * @return A {@link FolderBrowserTableRow} containing the data needed by the
+ * {@link FolderBrowser} to display the provided {@code item}.
+ */
+ private FolderBrowserTableRow buildRow(final ContentItem item) {
+
+ final FolderBrowserTableRow row = new FolderBrowserTableRow();
+
+ row.setObjectId(item.getObjectId());
+ row.setObjectUuid(item.getItemUuid());
+ row.setName(item.getName().getValue(defaultLocale));
+ final List languages = new ArrayList<>(itemL10NManager
+ .availableLanguages(item));
+ languages.sort((lang1, lang2) -> lang1.toString().compareTo(
+ lang2.toString()));
+ row.setLanguages(languages);
+ if (item.getTitle().hasValue(globalizationHelper
+ .getNegotiatedLocale())) {
+ row.setTitle(item.getTitle().getValue(globalizationHelper
+ .getNegotiatedLocale()));
+ } else {
+ row.setTitle(item.getTitle().getValue(defaultLocale));
+ }
+ final ContentType type = item.getContentType();
+ final ContentTypeInfo typeInfo = typesManager.getContentTypeInfo(
+ type);
+ row.setTypeLabelBundle(typeInfo.getLabelBundle());
+ row.setTypeLabelKey(typeInfo.getLabelKey());
+
+ row.setCreated(item.getCreationDate());
+ row.setLastModified(item.getLastModified());
+
+ row.setFolder(false);
+
+ return row;
+ }
+
+ /**
+ * Called by the {@link FolderBrowser} to delete an object.
+ *
+ * @param objectId
+ */
@Transactional(Transactional.TxType.REQUIRED)
protected void deleteObject(final long objectId) {
final Optional object = objectRepo.findById(objectId);
@@ -283,55 +388,150 @@ public class FolderBrowserController {
}
/**
- * Creates a Criteria Query
+ * Retrieves all subfolders of a folder matching the provided filter term.
+ * Because {@link Folder} does not have any of the fields despite the name
+ * which can be used to order the objects ordering is done as follows:
*
- * @param folder
- * @param filterTerm
+ * If {@code orderBy} has any value other than
+ * {@link FolderBrowser#SORT_KEY_NAME} the subfolders are ordered in
+ * ascending order by their name. If {@code orderBy} is
+ * {@link FolderBrowser#SORT_KEY_NAME} the subfolders are ordered by their
+ * name in ascending and descending order depending on the value of
+ * {@code orderDirection}.
*
- * @return
+ * @param folder The folder which contains the subfolders.
+ * @param filterTerm The filter term.
+ * @param orderBy Field to use for ordering. If the value is negative
+ * the parameter is ignored.
+ * @param orderDirection Direction for ordering. If the value is negative
+ * the parameter is ignored.
+ * @param firstResult Index of the first result to retrieve.
+ * @param maxResults Maxium number of results to retrieve.
+ *
+ *
+ * @return A list of the subfolders of the provided {@code folder} which
+ * match the provided {@code filterTerm}. The list is ordered as
+ * described above. The list will contain at most {@code maxResults}
+ * starting with the result with the index provided as
+ * {@code firstResult}.
*/
private List findSubFolders(final Folder folder,
- final String filterTerm) {
+ final String filterTerm,
+ final String orderBy,
+ final String orderDirection,
+ final int firstResult,
+ final int maxResults) {
final CriteriaBuilder builder = entityManager
- .getCriteriaBuilder();
+ .getCriteriaBuilder();
- final CriteriaQuery query = builder.createQuery(
- Folder.class);
- final Root from = query.from(Folder.class);
+ final CriteriaQuery criteria = builder.createQuery(
+ Folder.class);
+ final Root from = criteria.from(Folder.class);
- return entityManager.createQuery(
- query.where(builder.and(
- builder.equal(from.get("parentCategory"), folder),
- builder.
- like(builder.lower(from.get("name")), filterTerm)))).
- getResultList();
+ final Order order;
+ if (FolderBrowser.SORT_KEY_NAME.equals(orderBy)
+ && FolderBrowser.SORT_ACTION_DOWN.equals(orderDirection)) {
+ order = builder.desc(from.get("name"));
+ } else {
+ order = builder.asc(from.get("name"));
+ }
+ final TypedQuery query = entityManager.createQuery(
+ criteria.where(builder.and(
+ builder.equal(from.get("parentCategory"), folder),
+ builder
+ .like(builder.lower(from.get("name")), filterTerm)))
+ .orderBy(order));
+
+ if (firstResult >= 0) {
+ query.setFirstResult(firstResult);
+ }
+ if (maxResults >= 0) {
+ query.setMaxResults(maxResults);
+ }
+
+ return query.getResultList();
}
- private List findItemsInFolder(
- final Folder folder,
- final String filterTerm) {
+ /**
+ * Retrieves all items of a folder matching the provided filter term.
+ *
+ * @param folder The folder which contains the subfolders.
+ * @param filterTerm The filter term.
+ * @param orderBy Field to use for ordering. If the value is negative
+ * the parameter is ignored.
+ * @param orderDirection Direction for ordering. If the value is negative
+ * the parameter is ignored.
+ * @param firstResult Index of the first result to retrieve.
+ * @param maxResults Maxium number of results to retrieve.
+ *
+ *
+ * @return A list of the subfolders of the provided {@code folder} which
+ * match the provided {@code filterTerm}. The list is ordered the
+ * field provided as {@code orderBy} in the direction provided by
+ * {@code orderDirection}. The list will contain at most
+ * {@code maxResults} starting with the result with the index
+ * provided as {@code firstResult}.
+ */
+ private List findItemsInFolder(final Folder folder,
+ final String filterTerm,
+ final String orderBy,
+ final String orderDirection,
+ final int firstResult,
+ final int maxResults) {
final CriteriaBuilder builder = entityManager
- .getCriteriaBuilder();
+ .getCriteriaBuilder();
- final CriteriaQuery query = builder.createQuery(
- ContentItem.class);
- final Root fromItem = query.from(ContentItem.class);
+ final CriteriaQuery criteria = builder.createQuery(
+ ContentItem.class);
+ final Root fromItem = criteria.from(ContentItem.class);
final Join join = fromItem.join(
- "categories");
+ "categories");
- return entityManager.createQuery(query
- .select(fromItem)
- .where(builder.and(
- builder.equal(join.get("category"), folder),
- builder.equal(join.get("type"),
- CmsConstants.CATEGORIZATION_TYPE_FOLDER),
- builder.equal(fromItem.get("version"),
- ContentItemVersion.DRAFT),
- builder.like(fromItem.get("displayName"),
- filterTerm))))
- .getResultList();
+ final Path> orderPath;
+ switch (orderBy) {
+ case FolderBrowser.SORT_KEY_NAME:
+ orderPath = fromItem.get("displayName");
+ break;
+ case FolderBrowser.SORT_KEY_CREATION_DATE:
+ orderPath = fromItem.get("creationDate");
+ break;
+ case FolderBrowser.SORT_KEY_LAST_MODIFIED_DATE:
+ orderPath = fromItem.get("lastModified");
+ break;
+ default:
+ orderPath = fromItem.get("displayName");
+ break;
+ }
+
+ final Order order;
+ if (FolderBrowser.SORT_ACTION_DOWN.equals(orderDirection)) {
+ order = builder.desc(orderPath);
+ } else {
+ order = builder.asc(orderPath);
+ }
+
+ final TypedQuery query = entityManager.createQuery(criteria
+ .select(fromItem)
+ .where(builder.and(
+ builder.equal(join.get("category"), folder),
+ builder.equal(join.get("type"),
+ CmsConstants.CATEGORIZATION_TYPE_FOLDER),
+ builder.equal(fromItem.get("version"),
+ ContentItemVersion.DRAFT),
+ builder.like(fromItem.get("displayName"),
+ filterTerm)))
+ .orderBy(order));
+
+ if (firstResult >= 0) {
+ query.setFirstResult(firstResult);
+ }
+ if (maxResults >= 0) {
+ query.setMaxResults(maxResults);
+ }
+
+ return query.getResultList();
}
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModel.java
index e6e1e57d1..3e3693ad1 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModel.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModel.java
@@ -26,7 +26,6 @@ import org.librecms.CmsConstants;
import java.util.Iterator;
import java.util.List;
-import javax.ws.rs.DELETE;
/**
* Table model for the {@link FolderBrowser}.
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModelBuilder.java
index 92976b3b4..742e3072f 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModelBuilder.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableModelBuilder.java
@@ -33,7 +33,8 @@ import org.librecms.contentsection.Folder;
import java.util.List;
/**
- *
+ * Creates the {@link TableModel} for the {@link FolderBrowser}.
+ *
* @author Jens Pelzetter
*/
class FolderBrowserTableModelBuilder extends LockableImpl
@@ -62,15 +63,27 @@ class FolderBrowserTableModelBuilder extends LockableImpl
final FolderBrowserController controller = cdiUtil.findBean(
FolderBrowserController.class);
final String filter = folderBrowser.getFilter(state);
+ final String orderBy;
+ if (folderBrowser.getSortType(state) == null) {
+ orderBy = FolderBrowser.SORT_KEY_NAME;
+ } else {
+ orderBy = folderBrowser.getSortType(state);
+ }
+ final String orderDirection;
+ if (folderBrowser.getSortDirection(state) == null) {
+ orderDirection = FolderBrowser.SORT_ACTION_UP;
+ } else {
+ orderDirection = folderBrowser.getSortDirection(state);
+ }
final String atozFilter = folderBrowser.getAtoZfilter(state);
final int first = paginator.getFirst(state);
final int pageSize = paginator.getPageSize(state);
final String filterTerm;
if (filter != null && !filter.trim().isEmpty()) {
- filterTerm = filter.trim();
+ filterTerm = String.format("%s%%", filter.trim());
} else if (atozFilter != null && !atozFilter.trim().isEmpty()) {
- filterTerm = atozFilter.trim();
+ filterTerm = String.format("%s%%", atozFilter.trim());
} else {
filterTerm = null;
}
@@ -80,13 +93,15 @@ class FolderBrowserTableModelBuilder extends LockableImpl
final List rows;
if (filterTerm == null) {
rows = controller.getObjectRows(folder,
- "name",
+ orderBy,
+ orderDirection,
first - 1,
pageSize);
} else {
rows = controller.getObjectRows(folder,
- filter,
- "name",
+ filterTerm,
+ orderBy,
+ orderDirection,
first - 1,
pageSize);
}
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableRow.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableRow.java
index 3cc523812..bcf58b128 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableRow.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderBrowserTableRow.java
@@ -18,13 +18,16 @@
*/
package com.arsdigita.cms.ui.folder;
-
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
/**
+ * A simple data transfer object containing the data required by the
+ * {@link FolderBrowser} to display its rows. Used by the
+ * {@link FolderBrowserTableModelBuilder} to transfer the data from the
+ * {@link FolderBrowserController} to the {@link FolderBrowserTableModel}.
*
* @author Jens Pelzetter
*/
@@ -85,11 +88,11 @@ class FolderBrowserTableRow {
public String getTypeLabelBundle() {
return typeLabelBundle;
}
-
+
protected void setTypeLabelBundle(final String typeLabelBundle) {
this.typeLabelBundle = typeLabelBundle;
}
-
+
public String getTypeLabelKey() {
return typeLabelKey;
}
@@ -137,11 +140,11 @@ class FolderBrowserTableRow {
protected void setDeletable(final boolean deletable) {
this.deletable = deletable;
}
-
+
public boolean isFolder() {
return folder;
}
-
+
protected void setFolder(final boolean folder) {
this.folder = folder;
}
diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java
index 4c73fe6f1..752502399 100644
--- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java
+++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItem.java
@@ -311,7 +311,7 @@ public class ContentItem extends CcmObject implements Serializable {
*
* Please note that there is no grantee that the user still exists.
*/
- @Column(name = "LAST_MODIFING_USER_NAME")
+ @Column(name = "LAST_MODIFYING_USER_NAME")
@NotAudited
private String lastModifyingUserName;
diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java
index 36da3116b..75b55817e 100644
--- a/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java
+++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentItemRepository.java
@@ -18,7 +18,10 @@
*/
package org.librecms.contentsection;
+import org.apache.shiro.subject.Subject;
+
import java.util.Date;
+
import org.libreccm.auditing.AbstractAuditedEntityRepository;
import org.libreccm.categorization.Category;
import org.libreccm.core.CcmObject;
@@ -32,8 +35,8 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
+
import org.libreccm.security.Shiro;
-import org.libreccm.security.User;
import org.libreccm.workflow.Workflow;
/**
@@ -50,7 +53,7 @@ public class ContentItemRepository
@Inject
private FolderRepository folderRepo;
-
+
@Inject
private Shiro shiro;
@@ -352,26 +355,20 @@ public class ContentItemRepository
return Optional.empty();
}
}
-
+
@Override
public void save(final ContentItem item) {
final Date now = new Date();
- final Optional user = shiro.getUser();
- final String userName;
- if (user.isPresent()) {
- userName = user.get().getName();
- } else {
- userName = "--unknown--";
- }
-
+ final Subject subject = shiro.getSubject();
+ final String userName = subject.getPrincipal().toString();
+
if (isNew(item)) {
item.setCreationDate(now);
item.setCreationUserName(userName);
- } else {
- item.setLastModified(now);
- item.setLastModifyingUserName(userName);
}
-
+ item.setLastModified(now);
+ item.setLastModifyingUserName(userName);
+
super.save(item);
}
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_10__add_item_auditing_data.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_10__add_item_auditing_data.sql
index 9c0e5944d..a58f33a37 100644
--- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_10__add_item_auditing_data.sql
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/h2/V7_0_0_10__add_item_auditing_data.sql
@@ -8,5 +8,5 @@ alter table CCM_CMS.CONTENT_ITEMS
add column LAST_MODIFIED timestamp;
alter table CCM_CMS.CONTENT_ITEMS
- add column LAST_MODIFING_USER_NAME varchar(255);
+ add column LAST_MODIFYING_USER_NAME varchar(255);
diff --git a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_10__add_item_auditing_data.sql b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_10__add_item_auditing_data.sql
index 9c0e5944d..a58f33a37 100644
--- a/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_10__add_item_auditing_data.sql
+++ b/ccm-cms/src/main/resources/db/migrations/org/librecms/ccm_cms/pgsql/V7_0_0_10__add_item_auditing_data.sql
@@ -8,5 +8,5 @@ alter table CCM_CMS.CONTENT_ITEMS
add column LAST_MODIFIED timestamp;
alter table CCM_CMS.CONTENT_ITEMS
- add column LAST_MODIFING_USER_NAME varchar(255);
+ add column LAST_MODIFYING_USER_NAME varchar(255);
diff --git a/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql b/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql
index 35e1f953c..44734c60c 100644
--- a/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql
+++ b/ccm-cms/src/test/resources-wildfly-remote-h2-mem/scripts/create_ccm_cms_schema.sql
@@ -274,7 +274,7 @@ create schema CCM_CORE;
CREATION_USER_NAME varchar(255),
ITEM_UUID varchar(255) not null,
LAST_MODIFIED timestamp,
- LAST_MODIFING_USER_NAME varchar(255),
+ LAST_MODIFYING_USER_NAME varchar(255),
LAUNCH_DATE date,
VERSION varchar(255),
OBJECT_ID bigint not null,
diff --git a/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql b/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql
index d617a3845..1749b92db 100644
--- a/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql
+++ b/ccm-cms/src/test/resources-wildfly-remote-pgsql/scripts/create_ccm_cms_schema.sql
@@ -274,7 +274,7 @@ create schema CCM_CORE;
CREATION_USER_NAME varchar(255),
ITEM_UUID varchar(255) not null,
LAST_MODIFIED timestamp,
- LAST_MODIFING_USER_NAME varchar(255),
+ LAST_MODIFYING_USER_NAME varchar(255),
LAUNCH_DATE date,
VERSION varchar(255),
OBJECT_ID int8 not null,
diff --git a/ccm-cms/src/test/resources/datasets/create_ccm_cms_schema.sql b/ccm-cms/src/test/resources/datasets/create_ccm_cms_schema.sql
index a4bccdde2..50b3900c5 100644
--- a/ccm-cms/src/test/resources/datasets/create_ccm_cms_schema.sql
+++ b/ccm-cms/src/test/resources/datasets/create_ccm_cms_schema.sql
@@ -274,7 +274,7 @@ create schema CCM_CORE;
CREATION_USER_NAME varchar(255),
ITEM_UUID varchar(255) not null,
LAST_MODIFIED timestamp,
- LAST_MODIFING_USER_NAME varchar(255),
+ LAST_MODIFYING_USER_NAME varchar(255),
LAUNCH_DATE date,
VERSION varchar(255),
OBJECT_ID bigint not null,
diff --git a/ccm-core/src/main/java/org/libreccm/auditing/CcmRevisionListener.java b/ccm-core/src/main/java/org/libreccm/auditing/CcmRevisionListener.java
index aec9891be..952717b5f 100644
--- a/ccm-core/src/main/java/org/libreccm/auditing/CcmRevisionListener.java
+++ b/ccm-core/src/main/java/org/libreccm/auditing/CcmRevisionListener.java
@@ -18,37 +18,35 @@
*/
package org.libreccm.auditing;
-import java.util.Optional;
+import org.apache.shiro.subject.Subject;
+
+
import org.hibernate.envers.RevisionListener;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Shiro;
-import org.libreccm.security.User;
-
/**
* {@link RevisionListener} setting the user for the {@link CcmRevision} entity.
- *
+ *
* @author Jens Pelzetter
*/
public class CcmRevisionListener implements RevisionListener {
@Override
public void newRevision(final Object revisionEntity) {
-
+
if (!(revisionEntity instanceof CcmRevision)) {
throw new IllegalArgumentException(String.format(
"Provided revision entity is not an instance of class \"%s\".",
CcmRevision.class.getName()));
}
final CcmRevision revision = (CcmRevision) revisionEntity;
-
+
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Shiro shiro = cdiUtil.findBean(Shiro.class);
-
- final Optional user = shiro.getUser();
- if (user.isPresent()) {
- revision.setUserName(user.get().getName());
- }
+
+ final Subject subject = shiro.getSubject();
+ revision.setUserName(subject.getPrincipal().toString());
}
}
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java
index 4452732af..c15513709 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java
@@ -84,20 +84,8 @@ import javax.xml.bind.annotation.XmlRootElement;
name = "Category.withSubCategoriesAndObjects",
attributeNodes = {
@NamedAttributeNode(value = "subCategories"
- //,
- // subgraph = "subCategories"
- ), //@NamedAttributeNode(value = "objects")
+ ),
}
- // ,
- // subgraphs = {
- // @NamedSubgraph(
- // name = "subCategories",
- // attributeNodes = {
- // @NamedAttributeNode("subCategories"),
- // @NamedAttributeNode("objects")
- // }
- // )
- // }
)
})
@XmlRootElement(name = "category", namespace = CAT_XML_NS)
diff --git a/ccm-core/src/main/java/org/libreccm/security/RoleMembershipMarshaller.java b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipMarshaller.java
index d691f3e5e..26d90fb70 100644
--- a/ccm-core/src/main/java/org/libreccm/security/RoleMembershipMarshaller.java
+++ b/ccm-core/src/main/java/org/libreccm/security/RoleMembershipMarshaller.java
@@ -47,20 +47,27 @@ public class RoleMembershipMarshaller extends AbstractMarshaller
}
@Override
- @Transactional(Transactional.TxType.REQUIRED)
- protected void insertIntoDb(RoleMembership portableObject) {
+// @Transactional(Transactional.TxType.REQUIRED)
+ protected void insertIntoDb(final RoleMembership portableObject) {
// if (portableObject.getMembershipId() == 0) {
portableObject.setMembershipId(0);
// portableObject.setMembershipId(portableObject.getMembershipId() * -1);
- entityManager.persist(portableObject);
+// entityManager.persist(portableObject);
// entityManager.merge(portableObject);
- entityManager.flush();
+// entityManager.flush();
+ final RoleMembership roleMembership = save(portableObject);
LOGGER.debug("Saved RoleMembership with id {}.",
- portableObject.getMembershipId());
+ roleMembership.getMembershipId());
// } else {
// entityManager.merge(portableObject);
// }
}
+
+ @Transactional(Transactional.TxType.REQUIRES_NEW)
+ protected RoleMembership save(final RoleMembership membership) {
+ entityManager.persist(membership);
+ return membership;
+ }
}