diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatException.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatException.java
new file mode 100644
index 0000000000..fd2fd60bc9
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.caveat;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+
+/**
+ * Generic class for any runtime exception to do with caveats.
+ *
+ * @author Tom Page
+ * @since 2.4.a
+ */
+public class CaveatException extends AlfrescoRuntimeException
+{
+ /** serial version uid */
+ private static final long serialVersionUID = -1678248996340040195L;
+
+ public CaveatException(String msgId)
+ {
+ super(msgId);
+ }
+
+ public CaveatException(String msgId, Throwable cause)
+ {
+ super(msgId, cause);
+ }
+
+ /** The supplied caveat mark id was not found in the configured list. */
+ public static class CaveatMarkNotFound extends CaveatException
+ {
+ /** serial version uid */
+ private static final long serialVersionUID = -7605943340899129129L;
+
+ public CaveatMarkNotFound(String caveatMarkId)
+ {
+ super("Could not find caveat mark with id " + caveatMarkId);
+ }
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOInterface.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOInterface.java
new file mode 100644
index 0000000000..d25ed58faf
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOInterface.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.caveat.dao;
+
+import java.util.Map;
+
+import org.alfresco.module.org_alfresco_module_rm.caveat.scheme.CaveatGroup;
+
+/**
+ * An object responsible for providing access to the configured caveat groups and marks.
+ *
+ * @author Tom Page
+ * @since 2.4.a
+ */
+public interface CaveatDAOInterface
+{
+ /**
+ * Gets a map of all the available caveat groups keyed by id.
+ */
+ Map getCaveatGroups();
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java
new file mode 100644
index 0000000000..d7d7ba980d
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.caveat.scheme;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+import org.alfresco.module.org_alfresco_module_rm.caveat.CaveatException.CaveatMarkNotFound;
+import org.alfresco.module.org_alfresco_module_rm.util.CoreServicesExtras;
+
+/**
+ * A group of related caveat marks and metadata describing how they are related.
+ *
+ * @author Tom Page
+ * @since 2.4.a
+ */
+public class CaveatGroup
+{
+ /** The unique id of the caveat group. */
+ private String id;
+ /** The key to retrieve the I18n'ed display label for the caveat group. */
+ private String displayLabelKey;
+ /** The key to retrieve the I18n'ed description of the caveat group. */
+ private String descriptionKey;
+ /** The relationship between marks in the group. */
+ private CaveatGroupType caveatGroupType;
+ /** The marks that are contained in this group. */
+ private ImmutableList caveatMarks;
+
+ /**
+ * Constructor for the caveat group. This sets the group id of all the caveat marks that are supplied.
+ *
+ * @param id The unique id of the caveat group.
+ * @param displayLabelKey The key to retrieve the I18n'ed display label for the caveat group.
+ * @param descriptionKey The key to retrieve the I18n'ed description of the caveat group.
+ * @param caveatGroupType The relationship between marks in the group.
+ * @param caveatMarks The marks that are contained in this group.
+ */
+ public CaveatGroup(String id, String displayLabelKey, String descriptionKey, CaveatGroupType caveatGroupType,
+ List caveatMarks)
+ {
+ this.id = id;
+ this.displayLabelKey = displayLabelKey;
+ this.descriptionKey = descriptionKey;
+ this.caveatGroupType = caveatGroupType;
+ this.caveatMarks = ImmutableList.copyOf(caveatMarks);
+ for (CaveatMark caveatMark : caveatMarks)
+ {
+ caveatMark.setGroupId(id);
+ }
+ }
+
+ /**
+ * Gets the unique id of the caveat group.
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Gets the I18n'ed display label for the caveat group.
+ */
+ public String getDisplayLabel()
+ {
+ return CoreServicesExtras.getI18NMessageOrKey(displayLabelKey);
+ }
+
+ /**
+ * Gets the I18n'ed description of the caveat group.
+ */
+ public String getDescription()
+ {
+ return CoreServicesExtras.getI18NMessageOrKey(descriptionKey);
+ }
+
+ /**
+ * Indicates how the marks in the caveat groups are related.
+ */
+ public CaveatGroupType getCaveatGroupType()
+ {
+ return caveatGroupType;
+ }
+
+ /**
+ * Get caveat marks in ordered list with first being the most inclusive.
+ */
+ public ImmutableList getCaveatMarks()
+ {
+ return caveatMarks;
+ }
+
+ /**
+ * Indicates whether a mark exists in this caveat group or not.
+ *
+ * @param The identifier of the mark.
+ */
+ public boolean hasCaveatMark(String markId)
+ {
+ for (CaveatMark caveatMark : caveatMarks)
+ {
+ if (caveatMark.getId().equals(markId)) { return true; }
+ }
+ return false;
+ }
+
+ /**
+ * Get caveat mark by identifier.
+ *
+ * @param markId The identified of the mark.
+ * @throws CaveatMarkNotFound If the supplied id does not match a mark in this group.
+ */
+ public CaveatMark getCaveatMark(String markId)
+ {
+ for (CaveatMark caveatMark : caveatMarks)
+ {
+ if (caveatMark.getId().equals(markId)) { return caveatMark; }
+ }
+ throw new CaveatMarkNotFound(markId);
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroupType.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroupType.java
new file mode 100644
index 0000000000..4b26049a2a
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroupType.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.caveat.scheme;
+
+/**
+ * An enumeration of the type of caveat groups.
+ *
+ * @author Tom Page
+ * @since 2.4.a
+ */
+public enum CaveatGroupType
+{
+ /** Each mark in the group implies all earlier marks also apply. */
+ HIERACHICAL,
+ /** Each mark in the group implies that no other mark applies. */
+ EXCLUSIVE,
+ /** Each mark in the group has no bearing on the applicability of any other mark. */
+ INDEPENDENT
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java
new file mode 100644
index 0000000000..8ea1896bc9
--- /dev/null
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2005-2015 Alfresco Software Limited.
+ *
+ * This file is part of Alfresco
+ *
+ * Alfresco 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Alfresco 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 Alfresco. If not, see .
+ */
+
+package org.alfresco.module.org_alfresco_module_rm.caveat.scheme;
+
+import org.alfresco.module.org_alfresco_module_rm.util.CoreServicesExtras;
+
+/**
+ * A marking from a caveat group that can be applied to content to restrict access to users who have a corresponding
+ * mark.
+ *
+ * @author Tom Page
+ * @since 2.4.a
+ */
+public class CaveatMark
+{
+ /** The id of the group that this mark belongs to. */
+ private String groupId;
+ /** The id for this mark. */
+ private String id;
+ /** The I18N key for the display label of this mark. */
+ private String displayLabelKey;
+
+ /**
+ * Constructor for the caveat group.
+ *
+ * @param groupId The id of the group that this mark belongs to.
+ * @param id The id for this mark.
+ * @param displayLabelKey The I18N key for the display label of this mark.
+ */
+ public CaveatMark(String groupId, String id, String displayLabelKey)
+ {
+ this.groupId = groupId;
+ this.id = id;
+ this.displayLabelKey = displayLabelKey;
+ }
+
+ /**
+ * Constructor for a caveat group that does not yet belong to a group.
+ *
+ * @param id The id for this mark.
+ * @param displayLabelKey The I18N key for the display label of this mark.
+ */
+ public CaveatMark(String id, String displayLabelKey)
+ {
+ this.id = id;
+ this.displayLabelKey = displayLabelKey;
+ }
+
+ /**
+ * Get the identifier for the group that this mark belongs to.
+ */
+ public String getGroupId()
+ {
+ return groupId;
+ }
+
+ /**
+ * Set the identifier of the group that this mark belongs to.
+ */
+ public void setGroupId(String groupId)
+ {
+ this.groupId = groupId;
+ }
+
+ /**
+ * Get the identifier for the mark.
+ */
+ public String getId()
+ {
+ return id;
+ }
+
+ /**
+ * Get the display label for the mark.
+ */
+ public String getDisplayLabel()
+ {
+ return CoreServicesExtras.getI18NMessageOrKey(displayLabelKey);
+ }
+}
diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/CoreServicesExtras.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/CoreServicesExtras.java
index dfaa4e3aa9..d6cc6bc9c9 100644
--- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/CoreServicesExtras.java
+++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/CoreServicesExtras.java
@@ -19,6 +19,10 @@
package org.alfresco.module.org_alfresco_module_rm.util;
import static org.alfresco.util.collections.CollectionUtils.filterKeys;
+import static org.apache.commons.lang.StringUtils.isNotBlank;
+
+import java.io.Serializable;
+import java.util.Map;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryException;
@@ -28,9 +32,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.collections.Function;
-
-import java.io.Serializable;
-import java.util.Map;
+import org.springframework.extensions.surf.util.I18NUtil;
/**
* Provides additional methods of general use that could (in principle) be moved to the core services.
@@ -82,4 +84,17 @@ public class CoreServicesExtras
nodeService.addProperties(to, relevantPropVals);
return relevantPropVals;
}
+
+ /**
+ * Use the {@link I18NUtil} to look up a key and return the localised message. If no entry for the current language
+ * is found then return the key.
+ *
+ * @param i18nKey The message key.
+ * @return The message if one exists, or the key. Never returns null (unless null is supplied as the key).
+ */
+ public static String getI18NMessageOrKey(String i18nKey)
+ {
+ String message = I18NUtil.getMessage(i18nKey);
+ return (isNotBlank(message) ? message : i18nKey);
+ }
}