From 103d3ee5ce3965953c2c8cebe16edccb79328690 Mon Sep 17 00:00:00 2001
From: jensp
Date: Fri, 23 Mar 2018 19:19:52 +0000
Subject: [PATCH] CCM NG: Form etc for editing FlexLayoutComponent and some
other things
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5357 8810af33-2d31-482b-a856-94f89814c4df
---
.../ui/pagemodel/ItemListComponentForm.java | 22 +-
.../main/java/com/arsdigita/bebop/List.java | 436 ++++++++++--------
.../java/com/arsdigita/bebop/ListPanel.java | 51 +-
.../layout/ui/FlexLayoutComponentForm.java | 71 ---
.../AbstractComponentModelForm.java | 28 +-
.../layout/FlexLayoutComponentForm.java | 411 +++++++++++++++++
.../core/AbstractEntityRepository.java | 2 +-
.../main/java/org/libreccm/core/CcmCore.java | 2 +-
.../pagemodel/ComponentModelRepository.java | 80 +++-
.../libreccm/pagemodel/layout/FlexBox.java | 1 +
.../libreccm/pagemodel/layout/FlexLayout.java | 3 +-
.../pagemodel/layout/FlexLayoutRenderer.java | 2 +-
.../java/org/libreccm/theming/ThemeFiles.java | 2 +-
.../org/libreccm/theming/ThemeFilesDav.java | 106 +++++
.../org/libreccm/theming/ThemesService.java | 1 +
.../java/org/libreccm/webdav/Headers.java | 179 +++++++
.../org/libreccm/webdav/ResponseStatus.java | 131 ++++++
.../org/libreccm/webdav/methods/COPY.java | 49 ++
.../org/libreccm/webdav/methods/LOCK.java | 49 ++
.../org/libreccm/webdav/methods/MKCOL.java | 47 ++
.../org/libreccm/webdav/methods/MOVE.java | 47 ++
.../org/libreccm/webdav/methods/PROPFIND.java | 47 ++
.../libreccm/webdav/methods/PROPPATCH.java | 47 ++
.../org/libreccm/webdav/methods/UNLOCK.java | 47 ++
.../libreccm/webdav/methods/package-info.java | 22 +
.../org/libreccm/webdav/package-info.java | 29 ++
26 files changed, 1610 insertions(+), 302 deletions(-)
delete mode 100644 ccm-core/src/main/java/com/arsdigita/pagemodel/layout/ui/FlexLayoutComponentForm.java
create mode 100644 ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/layout/FlexLayoutComponentForm.java
create mode 100644 ccm-core/src/main/java/org/libreccm/theming/ThemeFilesDav.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/Headers.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/ResponseStatus.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/COPY.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/LOCK.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/MKCOL.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/MOVE.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/PROPFIND.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/PROPPATCH.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/UNLOCK.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/methods/package-info.java
create mode 100644 ccm-core/src/main/java/org/libreccm/webdav/package-info.java
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/pagemodel/ItemListComponentForm.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/pagemodel/ItemListComponentForm.java
index b02f12f2b..06f89bc05 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/pagemodel/ItemListComponentForm.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/pagemodel/ItemListComponentForm.java
@@ -32,6 +32,8 @@ import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.pagemodels.AbstractComponentModelForm;
import com.arsdigita.ui.admin.pagemodels.PageModelsTab;
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.pagemodel.ComponentModelRepository;
import org.librecms.CmsConstants;
import org.librecms.pagemodel.ItemListComponent;
@@ -133,8 +135,7 @@ public class ItemListComponentForm
}
@Override
- public void init(final FormSectionEvent event)
- throws FormProcessException {
+ public void init(final FormSectionEvent event) throws FormProcessException {
super.init(event);
@@ -144,7 +145,7 @@ public class ItemListComponentForm
if (component == null) {
pageSizeField.setValue(state, "30");
- }else {
+ } else {
final Object[] descendingValue;
if (component.isDescending()) {
descendingValue = new Object[]{DESCENDING};
@@ -163,6 +164,21 @@ public class ItemListComponentForm
}
}
+ @Override
+ protected ItemListComponent loadSelectedComponent(final long componentId) {
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final ComponentModelRepository componentModelRepo = cdiUtil
+ .findBean(ComponentModelRepository.class);
+
+ return componentModelRepo.findById(componentId,
+ ItemListComponent.class,
+ new String[]{"listOrder"})
+ .orElseThrow(() -> new IllegalArgumentException(String
+ .format("No ComponentModel with ID %d in the database.",
+ componentId)));
+ }
+
@Override
public void validate(final FormSectionEvent event)
throws FormProcessException {
diff --git a/ccm-core/src/main/java/com/arsdigita/bebop/List.java b/ccm-core/src/main/java/com/arsdigita/bebop/List.java
index 32e74865a..0047ec30f 100755
--- a/ccm-core/src/main/java/com/arsdigita/bebop/List.java
+++ b/ccm-core/src/main/java/com/arsdigita/bebop/List.java
@@ -39,24 +39,23 @@ import com.arsdigita.bebop.util.BebopConstants;
import com.arsdigita.xml.Element;
-
/**
- * A List, similar to a javax.swing.JList, that
- * keeps track of a sequence of items and selections of one or more of
- * these items. A separate model, {@link ListModel}, is used to represent
- * the items in the list.
+ * A List, similar to a javax.swing.JList, that keeps
+ * track of a sequence of items and selections of one or more of these items. A
+ * separate model, {@link ListModel}, is used to represent the items in the
+ * list.
*
* @see ListModel
* @see ListModelBuilder
* @see com.arsdigita.bebop.list.ListCellRenderer
- * @author David Lutterkort
+ * @author David Lutterkort
* @version $Id: List.java 287 2005-02-22 00:29:02Z sskracic $
*/
public class List extends SimpleComponent implements BebopConstants {
/**
- * The name of the StringParameter that the list uses to keep track of
- * which item is selected.
+ * The name of the StringParameter that the list uses to keep track of which
+ * item is selected.
*/
public static final String SELECTED = "sel";
@@ -67,8 +66,9 @@ public class List extends SimpleComponent implements BebopConstants {
public static final String SELECT_EVENT = "s";
/**
- * The model builder for this list. Is used to produce a new model for
- * each request served by this List.
+ * The model builder for this list. Is used to produce a new model for each
+ * request served by this List.
+ *
* @see #setListModelBuilder
* @see ArrayListModelBuilder
* @see MapListModelBuilder
@@ -79,6 +79,7 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* The renderer used to format list items.
+ *
* @see DefaultListCellRenderer
*/
private ListCellRenderer m_renderer;
@@ -93,27 +94,28 @@ public class List extends SimpleComponent implements BebopConstants {
private boolean m_stateParamsAreRegistered;
-
/**
- * Vertical List layout.
- **/
+ *
+ * Vertical List layout.
+ *
+ */
public static final int VERTICAL = 0;
-
/**
- * Horizontal List layout.
- **/
+ *
+ * Horizontal List layout.
+ *
+ */
public static final int HORIZONTAL = 1;
-
private int m_layout = VERTICAL;
/**
- * Creates a new List that uses the specified
- * list model builder to generate
- * per-request {@link ListModel ListModels}.
+ * Creates a new List that uses the specified list model
+ * builder to generate per-request {@link ListModel ListModels}.
*
* @param b the model builder used for this list
+ *
* @pre b != null
*/
public List(ListModelBuilder b) {
@@ -128,8 +130,8 @@ public class List extends SimpleComponent implements BebopConstants {
public List() {
// Force the use of the 'right' constructor
this((SingleSelectionModel) null);
- m_selection =
- new ParameterSingleSelectionModel(new StringParameter(SELECTED));
+ m_selection = new ParameterSingleSelectionModel(new StringParameter(
+ SELECTED));
}
/**
@@ -150,14 +152,14 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* Creates a new List from an array of objects. Uses an
- * internal {@link ListModelBuilder}. Each {@link ListModel} that is
- * built will
- * iterate through the entries of the object, returning the objects from
- * calls to {@link ListModel#getElement} and the corresponding index,
+ * internal {@link ListModelBuilder}. Each {@link ListModel} that is built
+ * will iterate through the entries of the object, returning the objects
+ * from calls to {@link ListModel#getElement} and the corresponding index,
* which is converted to a String from calls to {@link
* ListModel#getKey}.
*
* @param values an array of items
+ *
* @pre values != null
* @see #setListData(Object[] v)
*/
@@ -173,10 +175,11 @@ public class List extends SimpleComponent implements BebopConstants {
* returned by map.entrySet().iterator(). Calls to {@link
* ListModel#getElement} return one value in map. Calls to
* {@link ListModel#getElement} return the corresponding key, which is
- * converted
- * to a String by calling toString() on the key.
+ * converted to a String by calling toString() on
+ * the key.
*
* @param map a key-value mapping for the list items
+ *
* @pre map != null
*/
public List(Map map) {
@@ -189,12 +192,13 @@ public class List extends SimpleComponent implements BebopConstants {
* specified page.
*
* @param p the page this list is contained in
+ *
* @pre p != null
* @pre ! isLocked()
*/
public void register(Page p) {
Assert.isUnlocked(this);
- if ( m_selection.getStateParameter() != null ) {
+ if (m_selection.getStateParameter() != null) {
p.addComponentStateParam(this, m_selection.getStateParameter());
}
}
@@ -204,11 +208,13 @@ public class List extends SimpleComponent implements BebopConstants {
* component. Calls to this method should only be made through links
* generated by this list.
*
- * Determines the new selected element and fires a {@link
+ *
+ * Determines the new selected element and fires a {@link
* ChangeEvent} if it has changed. After that, fires an {@link
* ActionEvent}.
*
* @param state the state of the current request
+ *
* @throws ServletException if the control event is unknown.
* @pre state != null
* @see #fireStateChanged fireStateChanged
@@ -217,7 +223,7 @@ public class List extends SimpleComponent implements BebopConstants {
public void respond(PageState state) throws ServletException {
String event = state.getControlEventName();
- if ( SELECT_EVENT.equals(event) ) {
+ if (SELECT_EVENT.equals(event)) {
setSelectedKey(state, state.getControlEventValue());
} else {
throw new ServletException("Unknown event '" + event + "'");
@@ -226,11 +232,33 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Generates XML representing the items in the list. The items are
- * formatted using a {@link ListCellRenderer}. generateXML
- * is called on each component returned by the renderer.
+ * Allow subclasses to override how the layout is determined.
*
- *
The XML that is generated has the following form:
+ * @param list
+ */
+ protected void exportLayoutAttribute(final Element list) {
+ if (m_layout == VERTICAL) {
+ list.addAttribute("layout", "vertical");
+ } else {
+ list.addAttribute("layout", "horizontal");
+ }
+ }
+
+ protected String getTagName() {
+ return BEBOP_LIST;
+ }
+
+ protected String getTagXMLNS() {
+ return BEBOP_XML_NS;
+ }
+
+ /**
+ * Generates XML representing the items in the list. The items are formatted
+ * using a {@link ListCellRenderer}. generateXML is called on
+ * each component returned by the renderer.
+ *
+ *
+ * The XML that is generated has the following form:
*
* <bebop:list mode="single" %bebopAttr;>
* <bebop:cell [selected="selected"] key="itemKey">
@@ -239,43 +267,43 @@ public class List extends SimpleComponent implements BebopConstants {
* ... more <bebop:cell> elements, one for each list item ...
* </bebop:list>
*
- * @param state the state of the current request
+ * @param state the state of the current request
* @param parent the element into which XML is generated
+ *
* @pre state != null
* @pre parent != null
* @see com.arsdigita.bebop.list.ListCellRenderer
*/
public void generateXML(PageState state, Element parent) {
- if ( ! isVisible(state) ) {
+ if (!isVisible(state)) {
return;
}
ListModel m = getModel(state);
// Check if there are items in the list
- if(m.next()) {
+ if (m.next()) {
// The list has items
-
- Element list = parent.newChildElement(BEBOP_LIST, BEBOP_XML_NS);
+ Element list = parent.newChildElement(getTagName(), getTagXMLNS());
exportAttributes(list);
- if (m_layout == VERTICAL) {
- list.addAttribute("layout", "vertical");
- } else {
- list.addAttribute("layout", "horizontal");
- }
+// if (m_layout == VERTICAL) {
+// list.addAttribute("layout", "vertical");
+// } else {
+// list.addAttribute("layout", "horizontal");
+// }
+ exportLayoutAttribute(list);
Component c;
Object selKey;
- if(getStateParamsAreRegistered())
- {
- selKey = getSelectedKey(state);
- }
- else
+ if (getStateParamsAreRegistered()) {
+ selKey = getSelectedKey(state);
+ } else {
selKey = null;
+ }
int i = 0;
do {
@@ -286,24 +314,25 @@ public class List extends SimpleComponent implements BebopConstants {
// Converting both keys to String for comparison
// since ListModel.getKey returns a String
- boolean selected = (selKey != null) &&
- key.equals(selKey.toString());
+ boolean selected = (selKey != null) && key.equals(selKey
+ .toString());
item.addAttribute("key", key);
- if ( selected ) {
+ if (selected) {
item.addAttribute("selected", "selected");
}
- if(getStateParamsAreRegistered())
+ if (getStateParamsAreRegistered()) {
state.setControlEvent(this, SELECT_EVENT, key);
+ }
c = getCellRenderer().getComponent(this, state, m.getElement(),
key, i, selected);
c.generateXML(state, item);
i += 1;
- } while (m.next());
+ } while (m.next());
} else {
// The list has no items
- if(m_emptyView != null) {
+ if (m_emptyView != null) {
// Display the empty view
m_emptyView.generateXML(state, parent);
} else {
@@ -317,42 +346,42 @@ public class List extends SimpleComponent implements BebopConstants {
state.clearControlEvent();
}
-
/**
- * Retrieve the current List layout.
+ *
+ * Retrieve the current List layout.
*
* @return List.VERTICAL or List.HORIZONTAL
- **/
+ *
+ */
public int getLayout() {
return m_layout;
}
/**
- * Set the current List layout.
+ *
+ * Set the current List layout.
*
* @param layout New layout value, must be List.VERTICAL or List.HORIZONTAL
- **/
+ *
+ */
public void setLayout(int layout) {
Assert.isUnlocked(this);
Assert.isTrue((layout == VERTICAL) || (layout == HORIZONTAL),
- "Invalid layout code passed to setLayout");
+ "Invalid layout code passed to setLayout");
m_layout = layout;
}
/**
- * This method is part of a mechanism to freakishly allow
- * List's to be used as parent classes for components
- * that do not have their state params registered with the
- * page. An example of a situation like this is Form ErrorDisplay
- * being used in a Metaform
+ * This method is part of a mechanism to freakishly allow List's to be used
+ * as parent classes for components that do not have their state params
+ * registered with the page. An example of a situation like this is Form
+ * ErrorDisplay being used in a Metaform
*/
- public void setStateParamsAreRegistered(boolean val)
- {
+ public void setStateParamsAreRegistered(boolean val) {
m_stateParamsAreRegistered = val;
}
- public boolean getStateParamsAreRegistered()
- {
+ public boolean getStateParamsAreRegistered() {
return m_stateParamsAreRegistered;
}
@@ -360,6 +389,7 @@ public class List extends SimpleComponent implements BebopConstants {
* Returns the renderer currently used for rendering list items.
*
* @return the current list cell renderer.
+ *
* @see #setCellRenderer setCellRenderer
* @see com.arsdigita.bebop.list.ListCellRenderer
*/
@@ -368,10 +398,11 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Sets the cell renderer to be used when generating output with
- * or {@link #generateXML generateXML}.
+ * Sets the cell renderer to be used when generating output with or
+ * {@link #generateXML generateXML}.
*
* @param r a ListCellRenderer value
+ *
* @pre r != null
* @pre ! isLocked()
* @see com.arsdigita.bebop.list.ListCellRenderer
@@ -386,6 +417,7 @@ public class List extends SimpleComponent implements BebopConstants {
* {@link ListModel}.
*
* @return a ListModelBuilder value.
+ *
* @see #setModelBuilder setModelBuilder
* @see ListModelBuilder
*/
@@ -398,6 +430,7 @@ public class List extends SimpleComponent implements BebopConstants {
* {@link ListModel}.
*
* @param b a ListModelBuilder value
+ *
* @pre ! isLocked()
* @see ListModelBuilder
*/
@@ -407,9 +440,9 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Sets the empty view component, which is
- * shown if there are no items in the list. This component must
- * be stateless. For example, it could be an Image or a Label.
+ * Sets the empty view component, which is shown if there are no items in
+ * the list. This component must be stateless. For example, it could be an
+ * Image or a Label.
*
* @param c the new empty view component
*/
@@ -419,25 +452,27 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Gets the empty view component. The empty view component is
- * shown if there are no items in the list.
+ * Gets the empty view component. The empty view component is shown if there
+ * are no items in the list.
+ *
* @return the empty view component.
*/
public final Component getEmptyView() {
return m_emptyView;
}
-
/**
- * Initialize the private m_model variable. The initial
- * value is what the model builder returns for the state.
+ * Initialize the private m_model variable. The initial value
+ * is what the model builder returns for the state.
*/
private void initListModel() {
m_model = new RequestLocal() {
- protected Object initialValue(PageState s) {
- return getModelBuilder().makeModel(List.this, s);
- }
- };
+
+ protected Object initialValue(PageState s) {
+ return getModelBuilder().makeModel(List.this, s);
+ }
+
+ };
}
/**
@@ -445,8 +480,9 @@ public class List extends SimpleComponent implements BebopConstants {
* state.
*
* @param state the state of the current request
+ *
* @return the list model used in processing the request represented by
- * state.
+ * state.
*/
public ListModel getModel(PageState state) {
return (ListModel) m_model.get(state);
@@ -455,11 +491,12 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* Sets the list to use for the values in values. Each {@link
* ListModel} that is built will iterate through the entries of the object,
- * returning the objects from calls to {@link ListModel#getElement} and
- * the corresponding index, which is converted to a String
- * from calls to {@link ListModel#getKey}.
+ * returning the objects from calls to {@link ListModel#getElement} and the
+ * corresponding index, which is converted to a String from
+ * calls to {@link ListModel#getKey}.
*
* @param values an array of items
+ *
* @pre values != null
* @pre ! isLocked()
*/
@@ -475,9 +512,11 @@ public class List extends SimpleComponent implements BebopConstants {
* map.entrySet().iterator(). Calls to {@link
* ListModel#getElement} return one value in map. Calls to
* {@link ListModel#getElement} return the corresponding key, which is
- * converted to a String by calling toString()
- * on the key.
+ * converted to a String by calling toString() on
+ * the key.
+ *
* @param map a key-value mapping for the list items
+ *
* @pre map != null
* @pre ! isLocked()
*/
@@ -492,7 +531,7 @@ public class List extends SimpleComponent implements BebopConstants {
* programmatically.
*
* @return the model used by the list to keep track of the selected list
- * item.
+ * item.
*/
public final SingleSelectionModel getSelectionModel() {
return m_selection;
@@ -503,12 +542,13 @@ public class List extends SimpleComponent implements BebopConstants {
* currently selected list item.
*
* @param m the new selection model
+ *
* @pre m != null
* @pre ! isLocked()
*/
public final void setSelectionModel(SingleSelectionModel m) {
Assert.isUnlocked(this);
- if ( m_changeListener != null ) {
+ if (m_changeListener != null) {
// Transfer the change listener
m_selection.removeChangeListener(m_changeListener);
m.addChangeListener(m_changeListener);
@@ -517,12 +557,13 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Gets the key for the selected list item. This will only
- * be a valid key
- * if {@link #isSelected isSelected} is true.
+ * Gets the key for the selected list item. This will only be a valid key if
+ * {@link #isSelected isSelected} is true.
*
* @param state the state of the current request
+ *
* @return the key for the selected list item.
+ *
* @pre isSelected(state)
*/
public Object getSelectedKey(PageState state) {
@@ -530,12 +571,13 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Sets the selection to the one with the specified key. If
- * key was not already selected, fires the {@link
+ * Sets the selection to the one with the specified key. If key
+ * was not already selected, fires the {@link
* ChangeEvent}.
*
* @param state the state of the current request
- * @param key the key for the selected list item
+ * @param key the key for the selected list item
+ *
* @see #fireStateChanged fireStateChanged
*/
public void setSelectedKey(PageState state, String key) {
@@ -546,8 +588,9 @@ public class List extends SimpleComponent implements BebopConstants {
* Returns true if one of the list items is currently selected.
*
* @param state the state of the current request
+ *
* @return true if one of the list items is selected
- * false otherwise.
+ * false otherwise.
*/
public boolean isSelected(PageState state) {
return m_selection.isSelected(state);
@@ -557,6 +600,7 @@ public class List extends SimpleComponent implements BebopConstants {
* Clears the selection in the request represented by state.
*
* @param state the state of the current request
+ *
* @post ! isSelected(state)
*/
public void clearSelection(PageState state) {
@@ -565,19 +609,20 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* Creates the change listener that is used for forwarding change events
- * fired by
- * the selection model to change listeners registered with the list. The
- * returned change listener refires the event with the list,
+ * fired by the selection model to change listeners registered with the
+ * list. The returned change listener refires the event with the list,
* rather than the selection model, as source.
*
* @return the change listener used internally by the list.
*/
protected ChangeListener createChangeListener() {
return new ChangeListener() {
- public void stateChanged(ChangeEvent e) {
- fireStateChanged(e.getPageState());
- }
- };
+
+ public void stateChanged(ChangeEvent e) {
+ fireStateChanged(e.getPageState());
+ }
+
+ };
}
/**
@@ -585,13 +630,14 @@ public class List extends SimpleComponent implements BebopConstants {
* list item changes during the processing of a request. The change event
* that listeners receive names the list as the source.
*
- * @param l the change listener to run when the selected item changes in
- * a request
+ * @param l the change listener to run when the selected item changes in a
+ * request
+ *
* @pre ! isLocked()
*/
public void addChangeListener(ChangeListener l) {
Assert.isUnlocked(this);
- if ( m_changeListener == null ) {
+ if (m_changeListener == null) {
m_changeListener = createChangeListener();
m_selection.addChangeListener(m_changeListener);
}
@@ -599,10 +645,9 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Removes a change listener. The listener should have been previously
- * added with {@link #addChangeListener addChangeListener}, although no
- * error is signalled if the change listener is not found among the
- * list's listeners.
+ * Removes a change listener. The listener should have been previously added
+ * with {@link #addChangeListener addChangeListener}, although no error is
+ * signalled if the change listener is not found among the list's listeners.
*
* @param l the change listener to remove from the list
*/
@@ -612,19 +657,18 @@ public class List extends SimpleComponent implements BebopConstants {
}
/**
- * Fires a change event to signal that the selected list item has changed
- * in the request represented by state. The source of the
- * event is the list.
+ * Fires a change event to signal that the selected list item has changed in
+ * the request represented by state. The source of the event is
+ * the list.
*
* @param state the state of the current request
*/
protected void fireStateChanged(PageState state) {
- Iterator
- i=m_listeners.getListenerIterator(ChangeListener.class);
+ Iterator i = m_listeners.getListenerIterator(ChangeListener.class);
ChangeEvent e = null;
while (i.hasNext()) {
- if ( e == null ) {
+ if (e == null) {
e = new ChangeEvent(this, state);
}
((ChangeListener) i.next()).stateChanged(e);
@@ -633,9 +677,10 @@ public class List extends SimpleComponent implements BebopConstants {
// Action events
/**
- * Adds an action listener. This method is run whenever {@link #respond respond} is
- * called on the list. This gives clients a way to track mouse clicks
- * received by the list.
+ * Adds an action listener. This method is run whenever
+ * {@link #respond respond} is called on the list. This gives clients a way
+ * to track mouse clicks received by the list.
+ *
* @param 1 the action listener to add
*
* @pre l != null
@@ -649,6 +694,7 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* Removes a previously added action listener.
+ *
* @param 1 the action listener to remove
*
* @see #addActionListener addActionListener
@@ -660,20 +706,20 @@ public class List extends SimpleComponent implements BebopConstants {
/**
* Fires an action event signalling that the list received the request
- * submission. All registered action listeners are run. The source of
- * the event is the list.
+ * submission. All registered action listeners are run. The source of the
+ * event is the list.
+ *
* @param state the state of the current request
*
* @pre state != null
* @see #respond respond
*/
protected void fireActionEvent(PageState state) {
- Iterator
- i=m_listeners.getListenerIterator(ActionListener.class);
+ Iterator i = m_listeners.getListenerIterator(ActionListener.class);
ActionEvent e = null;
while (i.hasNext()) {
- if ( e == null ) {
+ if (e == null) {
e = new ActionEvent(this, state);
}
((ActionListener) i.next()).actionPerformed(e);
@@ -681,7 +727,6 @@ public class List extends SimpleComponent implements BebopConstants {
}
// ListModelBuilder for maps
-
/**
* Build list models from a map. The list models use the result of
* toString() called on the key of the map entries as their
@@ -689,6 +734,7 @@ public class List extends SimpleComponent implements BebopConstants {
* the list model iterates over.
*/
private static class MapListModelBuilder implements ListModelBuilder {
+
private Map m_map;
private boolean m_locked;
@@ -702,36 +748,38 @@ public class List extends SimpleComponent implements BebopConstants {
public ListModel makeModel(List l, PageState state) {
return new ListModel() {
- private Iterator i = m_map.entrySet().iterator();
- private Map.Entry e = null;
- public boolean next() {
- if ( ! i.hasNext() ) {
- e = null;
- return false;
- }
- e = (Map.Entry) i.next();
- return true;
+ private Iterator i = m_map.entrySet().iterator();
+ private Map.Entry e = null;
+
+ public boolean next() {
+ if (!i.hasNext()) {
+ e = null;
+ return false;
}
+ e = (Map.Entry) i.next();
+ return true;
+ }
- public Object getElement() {
- checkState();
- return e.getValue();
+ public Object getElement() {
+ checkState();
+ return e.getValue();
+ }
+
+ public String getKey() {
+ checkState();
+ return e.getKey().toString();
+ }
+
+ private void checkState() {
+ if (e == null) {
+ throw new IllegalStateException(
+ "No valid current item. "
+ + "Model is either before first item or after last item");
}
+ }
- public String getKey() {
- checkState();
- return e.getKey().toString();
- }
-
- private void checkState() {
- if ( e == null ) {
- throw new IllegalStateException("No valid current item. "
- + "Model is either before first item or after last item");
- }
- }
-
- };
+ };
}
public void lock() {
@@ -741,16 +789,17 @@ public class List extends SimpleComponent implements BebopConstants {
public final boolean isLocked() {
return m_locked;
}
+
}
// ListModelBuilder for arrays
-
/**
- * Build list models from an array of values. The list models use the
- * index of the array entries, converted to a String, as the
- * key for the list items and the array values as their elements.
+ * Build list models from an array of values. The list models use the index
+ * of the array entries, converted to a String, as the key for
+ * the list items and the array values as their elements.
*/
private static class ArrayListModelBuilder implements ListModelBuilder {
+
private Object[] m_values;
private boolean m_locked;
@@ -764,33 +813,36 @@ public class List extends SimpleComponent implements BebopConstants {
public ListModel makeModel(List l, PageState state) {
return new ListModel() {
- private int i = -1;
- public boolean next() {
- i += 1;
- return ( i < m_values.length );
- }
+ private int i = -1;
- public Object getElement() {
- checkState();
- return m_values[i];
- }
+ public boolean next() {
+ i += 1;
+ return (i < m_values.length);
+ }
- public String getKey() {
- checkState();
- return String.valueOf(i);
- }
+ public Object getElement() {
+ checkState();
+ return m_values[i];
+ }
- private void checkState() {
- if ( i < 0 ) {
- throw new IllegalStateException
- ("Before first item. Call next() first.");
- }
- if ( i >= m_values.length ) {
- throw new IllegalStateException("After last item. Model exhausted.");
- }
+ public String getKey() {
+ checkState();
+ return String.valueOf(i);
+ }
+
+ private void checkState() {
+ if (i < 0) {
+ throw new IllegalStateException(
+ "Before first item. Call next() first.");
}
- };
+ if (i >= m_values.length) {
+ throw new IllegalStateException(
+ "After last item. Model exhausted.");
+ }
+ }
+
+ };
}
public void lock() {
@@ -800,22 +852,26 @@ public class List extends SimpleComponent implements BebopConstants {
public final boolean isLocked() {
return m_locked;
}
+
}
/**
* A {@link ListModel} that has no rows.
*/
public static final ListModel EMPTY_MODEL = new ListModel() {
- public boolean next() {
- return false;
- }
- public String getKey() {
- throw new IllegalStateException("ListModel is empty");
- }
+ public boolean next() {
+ return false;
+ }
+
+ public String getKey() {
+ throw new IllegalStateException("ListModel is empty");
+ }
+
+ public Object getElement() {
+ throw new IllegalStateException("ListModel is empty");
+ }
+
+ };
- public Object getElement() {
- throw new IllegalStateException("ListModel is empty");
- }
- };
}
diff --git a/ccm-core/src/main/java/com/arsdigita/bebop/ListPanel.java b/ccm-core/src/main/java/com/arsdigita/bebop/ListPanel.java
index bca4357e6..d51f0d5ec 100644
--- a/ccm-core/src/main/java/com/arsdigita/bebop/ListPanel.java
+++ b/ccm-core/src/main/java/com/arsdigita/bebop/ListPanel.java
@@ -26,26 +26,29 @@ import com.arsdigita.xml.Element;
/**
* A container that outputs its components in a <list>. Each child is
- * printed in its own list item. The components are put into the list
- * in the order in which they were added to the
- * ListPanel, progressing from top to bottom.
+ * printed in its own list item. The components are put into the list in the
+ * order in which they were added to the ListPanel, progressing
+ * from top to bottom.
*
- * ListPanels can be ordered or unordered.
+ *
+ * ListPanels can be ordered or unordered.
*
* @author Christian Brechbühler (christian@arsdigita.com)
*
* @version $Id$
- * */
-public class ListPanel extends SimpleContainer {
+ *
+ */
+public class ListPanel extends SimpleContainer {
- public static final boolean ORDERED = true ;
+ public static final boolean ORDERED = true;
public static final boolean UNORDERED = false;
private boolean m_ordered;
/**
* Creates a simple list.
+ *
* @param ordered true is an ordered (numbered) list;
- * false is an unordered (bulleted) list
+ * false is an unordered (bulleted) list
*
*/
public ListPanel(boolean ordered) {
@@ -54,32 +57,36 @@ public class ListPanel extends SimpleContainer {
/**
* Adds child components as a subtree under list-item nodes.
- * Generates a DOM fragment:
- *
+ *
+ * Generates a DOM fragment:
+ *
+ *
* <bebop:listPanel>
* <bebop:cell> ... cell contents </bebop:cell>
* <bebop:cell> ... cell contents </bebop:cell>
* ...
* </bebop:list>
- * @param state the state of the current request
+ *
+ * @param state the state of the current request
* @param parent the node under which this subtree will be added
*/
public void generateXML(PageState state, Element parent) {
- if ( ! isVisible(state) ) {
- return;
- }
+ if (isVisible(state)) {
- Element list = parent.newChildElement("bebop:listPanel", BEBOP_XML_NS);
- list.addAttribute("ordered", String.valueOf(m_ordered));
- exportAttributes(list);
+ Element list = parent.newChildElement("bebop:listPanel",
+ BEBOP_XML_NS);
+ list.addAttribute("ordered", String.valueOf(m_ordered));
+ exportAttributes(list);
- // generate XML for children
- for (Iterator i = children(); i.hasNext(); ) {
- Component c = (Component) i.next();
+ // generate XML for children
+ for (Iterator i = children(); i.hasNext();) {
+ Component c = (Component) i.next();
- Element item = list.newChildElement("bebop:cell", BEBOP_XML_NS);
- c.generateXML(state, item);
+ Element item = list.newChildElement("bebop:cell", BEBOP_XML_NS);
+ c.generateXML(state, item);
+ }
}
}
+
}
diff --git a/ccm-core/src/main/java/com/arsdigita/pagemodel/layout/ui/FlexLayoutComponentForm.java b/ccm-core/src/main/java/com/arsdigita/pagemodel/layout/ui/FlexLayoutComponentForm.java
deleted file mode 100644
index f953ea6d1..000000000
--- a/ccm-core/src/main/java/com/arsdigita/pagemodel/layout/ui/FlexLayoutComponentForm.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2018 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.pagemodel.layout.ui;
-
-import com.arsdigita.bebop.BoxPanel;
-import com.arsdigita.bebop.FormData;
-import com.arsdigita.bebop.PageState;
-import com.arsdigita.bebop.ParameterSingleSelectionModel;
-import com.arsdigita.ui.admin.pagemodels.AbstractComponentModelForm;
-import com.arsdigita.ui.admin.pagemodels.PageModelsTab;
-
-import org.libreccm.pagemodel.layout.FlexLayout;
-
-/**
- *
- * @author Jens Pelzetter
- */
-public class FlexLayoutComponentForm
- extends AbstractComponentModelForm {
-
- public FlexLayoutComponentForm(
- final PageModelsTab pageModelsTab,
- final ParameterSingleSelectionModel selectedModelId,
- final ParameterSingleSelectionModel selectedComponentId) {
-
-
- super("FlexLayoutComponentForm",
- pageModelsTab,
- selectedModelId,
- selectedComponentId);
- }
-
- @Override
- protected void addWidgets() {
-
- final BoxPanel horizontalPanel = new BoxPanel(BoxPanel.HORIZONTAL);
-
- add(horizontalPanel);
- }
-
- @Override
- protected FlexLayout createComponentModel() {
- return new FlexLayout();
- }
-
- @Override
- protected void updateComponentModel(final FlexLayout componentModel,
- final PageState state,
- final FormData data) {
- throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
- }
-
-
-
-}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/AbstractComponentModelForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/AbstractComponentModelForm.java
index 83c56ec7a..e8eb8b33b 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/AbstractComponentModelForm.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/AbstractComponentModelForm.java
@@ -29,6 +29,7 @@ import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormValidationListener;
import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.AdminUiConstants;
@@ -239,6 +240,7 @@ public abstract class AbstractComponentModelForm
* @throws FormProcessException
*/
@Override
+ @SuppressWarnings("unchecked")
public void init(final FormSectionEvent event) throws FormProcessException {
final PageState state = event.getPageState();
@@ -248,18 +250,26 @@ public abstract class AbstractComponentModelForm
if (selectedComponentIdStr != null
&& !selectedComponentIdStr.isEmpty()) {
- final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+
+ componentModel = loadSelectedComponent(
+ Long.parseLong(selectedComponentIdStr));
+
+ keyField.setValue(state, componentModel.getKey());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T loadSelectedComponent(final long componentId) {
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ComponentModelRepository componentModelRepo = cdiUtil
.findBean(ComponentModelRepository.class);
-
- final ComponentModel model = componentModelRepo
- .findById(Long.parseLong(selectedComponentIdStr))
+
+ return (T) componentModelRepo
+ .findById(componentId)
.orElseThrow(() -> new IllegalArgumentException(String
- .format("No ComponentModel with ID %s in the database.",
- selectedComponentIdStr)));
-
- keyField.setValue(state, model.getKey());
- }
+ .format("No ComponentModel with ID %d in the database.",
+ componentId)));
}
/**
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/layout/FlexLayoutComponentForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/layout/FlexLayoutComponentForm.java
new file mode 100644
index 000000000..9f5ed9b7c
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/pagemodels/layout/FlexLayoutComponentForm.java
@@ -0,0 +1,411 @@
+/*
+ * Copyright (C) 2018 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.ui.admin.pagemodels.layout;
+
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.FormProcessException;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.List;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.PropertySheet;
+import com.arsdigita.bebop.PropertySheetModel;
+import com.arsdigita.bebop.PropertySheetModelBuilder;
+import com.arsdigita.bebop.event.FormSectionEvent;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.SingleSelect;
+import com.arsdigita.bebop.list.ListCellRenderer;
+import com.arsdigita.bebop.list.ListModel;
+import com.arsdigita.bebop.list.ListModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.ui.admin.AdminUiConstants;
+import com.arsdigita.ui.admin.pagemodels.AbstractComponentModelForm;
+import com.arsdigita.ui.admin.pagemodels.PageModelsTab;
+import com.arsdigita.util.LockableImpl;
+import com.arsdigita.xml.Element;
+
+import org.libreccm.cdi.utils.CdiUtil;
+import org.libreccm.core.UnexpectedErrorException;
+import org.libreccm.pagemodel.ComponentModelRepository;
+import org.libreccm.pagemodel.layout.FlexBox;
+import org.libreccm.pagemodel.layout.FlexDirection;
+import org.libreccm.pagemodel.layout.FlexLayout;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Objects;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class FlexLayoutComponentForm
+ extends AbstractComponentModelForm {
+
+ private final ParameterSingleSelectionModel selectedComponentId;
+
+ private SingleSelect directionSelect;
+// private FlexBoxesPanel boxesPanel;
+
+ private List boxesList;
+
+ public FlexLayoutComponentForm(
+ final PageModelsTab pageModelsTab,
+ final ParameterSingleSelectionModel selectedModelId,
+ final ParameterSingleSelectionModel selectedComponentId) {
+
+ super("FlexLayoutComponentForm",
+ pageModelsTab,
+ selectedModelId,
+ selectedComponentId);
+
+ Objects.requireNonNull(pageModelsTab);
+ Objects.requireNonNull(selectedModelId);
+ Objects.requireNonNull(selectedComponentId);
+
+ this.selectedComponentId = selectedComponentId;
+ }
+
+ @Override
+ protected void addWidgets() {
+
+ directionSelect = new SingleSelect("directionSelect");
+ directionSelect.setLabel(new GlobalizedMessage(
+ AdminUiConstants.ADMIN_BUNDLE,
+ "ui.admin.pagelayout.flexlayout.direction.label"));
+ directionSelect
+ .addOption(new Option(
+ FlexDirection.HORIZONTAL.toString(),
+ new Label(new GlobalizedMessage(
+ AdminUiConstants.ADMIN_BUNDLE,
+ "ui.admin.pagelayout.flexlayout.direction"
+ + ".option.horizontal"))));
+ directionSelect
+ .addOption(new Option(
+ FlexDirection.VERTICAL.toString(),
+ new Label(new GlobalizedMessage(
+ AdminUiConstants.ADMIN_BUNDLE,
+ "ui.admin.pagelayout.flexlayout.direction"
+ + ".option.vertical"))));
+ add(directionSelect);
+
+// boxesPanel = new FlexBoxesPanel();
+// add(boxesPanel);
+ boxesList
+ = new BoxesList(new BoxesListModelBuilder(selectedComponentId));
+ boxesList.setCellRenderer(new BoxesListCellRenderer());
+ boxesList.setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.pagelayout.flexlayout.no_boxes",
+ AdminUiConstants.ADMIN_BUNDLE)));
+ add(boxesList);
+ }
+
+ @Override
+ protected FlexLayout createComponentModel() {
+ return new FlexLayout();
+ }
+
+ @Override
+ protected void updateComponentModel(final FlexLayout componentModel,
+ final PageState state,
+ final FormData data) {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+
+ @Override
+ public void init(final FormSectionEvent event) throws FormProcessException {
+
+ super.init(event);
+
+ final PageState state = event.getPageState();
+
+ final FlexLayout layout = getComponentModel();
+
+ if (layout == null) {
+ directionSelect.setValue(state, FlexDirection.VERTICAL.toString());
+ } else {
+ directionSelect.setValue(state, layout.getDirection().toString());
+ }
+ }
+
+// private class FlexBoxesPanel extends SimpleContainer {
+//
+// private FlexDirection direction;
+//
+// public FlexBoxesPanel() {
+// super("flexLayout", "bebop");
+//
+// direction = FlexDirection.VERTICAL;
+// }
+//
+// public FlexDirection getDirection() {
+// return direction;
+// }
+//
+// public void setFlexDirection(final FlexDirection direction) {
+// this.direction = direction;
+// }
+//
+// @Override
+// protected Element generateParent(final Element parent) {
+//
+// final Element element = super.generateParent(parent);
+// element.addAttribute("direction", direction
+// .toString()
+// .toLowerCase());
+// return element;
+// }
+//
+// }
+ private class FlexBoxPanel extends BoxPanel {
+
+ private final FlexBox box;
+
+ public FlexBoxPanel(final FlexBox box) {
+
+ super(BoxPanel.VERTICAL);
+
+ this.box = box;
+
+ final PropertySheet propertySheet = new PropertySheet(
+ new FlexBoxPropertySheetModelBuilder(box));
+ super.add(propertySheet);
+ }
+
+ }
+
+ private class FlexBoxPropertySheetModelBuilder
+ extends LockableImpl
+ implements PropertySheetModelBuilder {
+
+ private final FlexBox box;
+
+ public FlexBoxPropertySheetModelBuilder(final FlexBox box) {
+ this.box = box;
+ }
+
+ @Override
+ public PropertySheetModel makeModel(final PropertySheet sheet,
+ final PageState state) {
+
+ return new FlexBoxPropertySheetModel(box);
+ }
+
+ }
+
+ private class FlexBoxPropertySheetModel implements PropertySheetModel {
+
+ private final FlexBox box;
+ private final Iterator propertyIterator;
+ private FlexBoxProperty currentProperty;
+
+ public FlexBoxPropertySheetModel(final FlexBox box) {
+ this.box = box;
+ propertyIterator = Arrays
+ .asList(FlexBoxProperty.values())
+ .iterator();
+ }
+
+ @Override
+ public boolean nextRow() {
+
+ if (box == null) {
+ return false;
+ }
+
+ if (propertyIterator.hasNext()) {
+ currentProperty = propertyIterator.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public String getLabel() {
+ return currentProperty.toString();
+ }
+
+ @Override
+ public GlobalizedMessage getGlobalizedLabel() {
+
+ final String key = String
+ .format("ui.admin.pagemodels.flexlayout.box.properties.%s",
+ currentProperty.toString().toLowerCase());
+ return new GlobalizedMessage(key, AdminUiConstants.ADMIN_BUNDLE);
+ }
+
+ @Override
+ public String getValue() {
+
+ switch (currentProperty) {
+ case ORDER:
+ return Integer.toString(box.getOrder());
+ case SIZE:
+ return Integer.toString(box.getSize());
+ case COMPONENT:
+ if (box.getComponent() == null) {
+ return "";
+ } else {
+ return box.getComponent().getClass().getName();
+ }
+ default:
+ throw new UnexpectedErrorException(String
+ .format("Invalid \"%s\" for property of FlexBox.",
+ currentProperty.toString()));
+ }
+ }
+ }
+
+ private static enum FlexBoxProperty {
+ ORDER,
+ SIZE,
+ COMPONENT
+ }
+
+ private class BoxesList extends List {
+
+ private FlexLayout flexLayout;
+
+ public BoxesList(final ListModelBuilder listModelBuilder) {
+ super(listModelBuilder);
+ }
+
+ public FlexLayout getFlexLayout() {
+ return flexLayout;
+ }
+
+ public void setFlexLayout(final FlexLayout flexLayout) {
+ this.flexLayout = flexLayout;
+ }
+
+ @Override
+ protected String getTagName() {
+ return "flexLayoutBoxesList";
+ }
+
+ @Override
+ protected void exportLayoutAttribute(final Element list) {
+
+ if (flexLayout.getDirection() == FlexDirection.HORIZONTAL) {
+ list.addAttribute("layout", "horizontal");
+ } else {
+ list.addAttribute("layout", "vertical");
+ }
+ }
+
+ }
+
+ private class BoxesListModelBuilder
+ extends LockableImpl
+ implements ListModelBuilder {
+
+ private final ParameterSingleSelectionModel selectedComponentId;
+
+ public BoxesListModelBuilder(
+ final ParameterSingleSelectionModel selectedComponentId) {
+
+ super();
+
+ Objects.requireNonNull(selectedComponentId);
+
+ this.selectedComponentId = selectedComponentId;
+ }
+
+ @Override
+ public ListModel makeModel(final List list,
+ final PageState state) {
+
+ if (selectedComponentId.isSelected(state)) {
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+
+ final ComponentModelRepository componentModelRepo = cdiUtil
+ .findBean(ComponentModelRepository.class);
+
+ final String componentModelId = selectedComponentId
+ .getSelectedKey(state);
+
+ final FlexLayout flexLayout = (FlexLayout) componentModelRepo
+ .findById(Long.parseLong(componentModelId))
+ .orElseThrow(() -> new IllegalArgumentException(String
+ .format("No ComponentModel with ID %s in the database",
+ componentModelId)));
+
+ return new BoxesListModel(flexLayout.getBoxes());
+
+ } else {
+ return new BoxesListModel(Collections.emptyList());
+ }
+ }
+
+ }
+
+ private class BoxesListModel implements ListModel {
+
+ private final Iterator iterator;
+ private FlexBox currentBox;
+
+ public BoxesListModel(final java.util.List boxes) {
+ this.iterator = boxes.iterator();
+ }
+
+ @Override
+ public boolean next() {
+ if (iterator.hasNext()) {
+ currentBox = iterator.next();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public Object getElement() {
+ return currentBox;
+ }
+
+ @Override
+ public String getKey() {
+ return Long.toString(currentBox.getBoxId());
+ }
+
+ }
+
+ private class BoxesListCellRenderer implements ListCellRenderer {
+
+ @Override
+ public Component getComponent(final List list,
+ final PageState state,
+ final Object value,
+ final String key,
+ final int index,
+ final boolean isSelected) {
+
+ final FlexBox box = (FlexBox) value;
+
+ return new FlexBoxPanel(box);
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
index 148a86a97..e33c8b1ea 100644
--- a/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/core/AbstractEntityRepository.java
@@ -188,7 +188,7 @@ public abstract class AbstractEntityRepository implements Serializable {
/**
* Finds an entity by its ID and does fetch joins for the provided
* attributes. Be careful with this method. Do not a too many attributes to
- * the fetch joins, only does which you really need. Otherwise there can be
+ * the fetch joins, only those which you really need. Otherwise there can be
* a serious performance impact.
*
* @param entityId The ID of the entity to retrieve.
diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
index 927c0b816..03eeee24f 100644
--- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
+++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
@@ -18,7 +18,7 @@
*/
package org.libreccm.core;
-import com.arsdigita.pagemodel.layout.ui.FlexLayoutComponentForm;
+import com.arsdigita.ui.admin.pagemodels.layout.FlexLayoutComponentForm;
import com.arsdigita.ui.admin.AdminServlet;
import com.arsdigita.ui.admin.AdminUiConstants;
import com.arsdigita.ui.admin.applications.AdminApplicationCreator;
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelRepository.java b/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelRepository.java
index 9217cd330..b35032174 100644
--- a/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/ComponentModelRepository.java
@@ -23,10 +23,23 @@ import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+
import javax.enterprise.context.RequestScoped;
import javax.transaction.Transactional;
+
import java.util.UUID;
+import javax.persistence.EntityGraph;
+import javax.persistence.NoResultException;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+
/**
* Repository class for managing {@link ComponentModel} entities.
*
@@ -47,7 +60,7 @@ public class ComponentModelRepository
public String getIdAttributeName() {
return "componentModelId";
}
-
+
@Override
public Long getIdOfEntity(final ComponentModel entity) {
return entity.getComponentModelId();
@@ -83,4 +96,69 @@ public class ComponentModelRepository
}
}
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Optional findById(final long modelId,
+ final Class modelClass) {
+
+ return Optional.ofNullable(getEntityManager().find(modelClass,
+ modelId));
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Optional findById(
+ final long modelId,
+ final Class modelClass,
+ final String entityGraphName) {
+
+ return Optional.ofNullable(getEntityManager().find(modelClass,
+ modelId));
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Optional findById(
+ final long entityId,
+ final Class modelClass,
+ final EntityGraph entityGraph) {
+
+ Objects.requireNonNull(entityId);
+ Objects.requireNonNull(entityGraph);
+
+ final Map hints = new HashMap<>();
+ hints.put(FETCH_GRAPH_HINT_KEY, entityGraph);
+ return Optional.ofNullable(getEntityManager().find(modelClass,
+ entityId,
+ hints));
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public Optional findById(
+ final long entityId,
+ final Class modelClass,
+ final String... fetchJoins) {
+
+ Objects.requireNonNull(entityId);
+
+ final CriteriaBuilder builder = getEntityManager()
+ .getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = builder
+ .createQuery(modelClass);
+ final Root from = criteriaQuery.from(modelClass);
+ criteriaQuery.from(getEntityClass());
+ criteriaQuery.select(from);
+ for (final String fetchJoin : fetchJoins) {
+ from.fetch(fetchJoin);
+ }
+
+ criteriaQuery
+ .where(builder.equal(from.get(getIdAttributeName()), entityId));
+
+ final TypedQuery query = getEntityManager()
+ .createQuery(criteriaQuery);
+ try {
+ return Optional.of(query.getSingleResult());
+ } catch (NoResultException ex) {
+ return Optional.empty();
+ }
+ }
+
}
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java
index de0c17205..5f5e68a81 100644
--- a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexBox.java
@@ -56,6 +56,7 @@ public class FlexBox implements Serializable {
private long boxId;
@ManyToOne
+ @JoinColumn(name = "LAYOUT_ID")
private FlexLayout layout;
@Column(name = "BOX_ORDER")
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java
index 5eecb3e56..f65e1a9ef 100644
--- a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayout.java
@@ -46,7 +46,7 @@ import javax.persistence.Table;
* @author Jens Pelzetter
*/
@Entity
-@Table(name = "HORIZONTAL_LAYOUT_COMPONENTS", schema = CoreConstants.DB_SCHEMA)
+@Table(name = "FLEX_LAYOUT_COMPONENTS", schema = CoreConstants.DB_SCHEMA)
public class FlexLayout extends ComponentModel {
private static final long serialVersionUID = 1977244351125227610L;
@@ -65,7 +65,6 @@ public class FlexLayout extends ComponentModel {
*/
@OneToMany(mappedBy = "layout")
@OrderBy(value = "order")
- @JoinColumn(name = "LAYOUT_ID")
private List boxes;
public FlexLayout() {
diff --git a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutRenderer.java b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutRenderer.java
index 298e3520e..c7809640a 100644
--- a/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutRenderer.java
+++ b/ccm-core/src/main/java/org/libreccm/pagemodel/layout/FlexLayoutRenderer.java
@@ -59,7 +59,7 @@ public class FlexLayoutRenderer implements ComponentRenderer {
componentModel
.getBoxes()
.stream()
- .map(this::renderBox)
+ .map(box -> renderBox(box, parameters))
.collect(Collectors.toList()));
return result;
diff --git a/ccm-core/src/main/java/org/libreccm/theming/ThemeFiles.java b/ccm-core/src/main/java/org/libreccm/theming/ThemeFiles.java
index a840aa5ff..7db5a9f52 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/ThemeFiles.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/ThemeFiles.java
@@ -40,7 +40,7 @@ import javax.ws.rs.core.Response;
* @author Jens Pelzetter
*/
@RequestScoped
-@Path("/{theme}")
+@Path("/files/{theme}")
public class ThemeFiles {
@Inject
diff --git a/ccm-core/src/main/java/org/libreccm/theming/ThemeFilesDav.java b/ccm-core/src/main/java/org/libreccm/theming/ThemeFilesDav.java
new file mode 100644
index 000000000..8a3f5f07d
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/theming/ThemeFilesDav.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2018 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 org.libreccm.theming;
+
+import org.libreccm.webdav.methods.PROPFIND;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path("/dav/{theme}")
+public class ThemeFilesDav {
+
+ @Inject
+ private Themes themes;
+
+ @GET
+ @Path("/{path}")
+ public Response getFile(@PathParam("theme") final String theme,
+ @PathParam("path") final String path) {
+
+ final ThemeInfo info = themes
+ .getTheme(theme, ThemeVersion.LIVE)
+ .orElseThrow(() -> new NotFoundException(String
+ .format("Theme \"%s\" does not exist.", theme)));
+
+ final InputStream inputStream = themes
+ .getFileFromTheme(info, path)
+ .orElseThrow(() -> new NotFoundException(String
+ .format("The file \"%s\" does exist in the theme \"%s\".",
+ path,
+ theme)));
+
+ final MediaType mediaType = getMediaTypeFromPath(path);
+
+ final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(inputStream));
+ final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ try {
+ int value = reader.read();
+ while (value != -1) {
+ outputStream.write(value);
+ value = reader.read();
+ }
+ } catch (IOException ex) {
+ throw new WebApplicationException(ex);
+ }
+
+ final byte[] data = outputStream.toByteArray();
+ return Response.ok(data, mediaType).build();
+
+ }
+
+ @PROPFIND
+ @Path("/{path}")
+ public Response propfind(@PathParam("theme") final String theme,
+ @PathParam("path") final String path) {
+
+ throw new UnsupportedOperationException();
+
+ }
+
+ private MediaType getMediaTypeFromPath(final String path) {
+
+ if (path.endsWith(".css")) {
+ return new MediaType("text", "css");
+ } else {
+ return MediaType.WILDCARD_TYPE;
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/theming/ThemesService.java b/ccm-core/src/main/java/org/libreccm/theming/ThemesService.java
index 20a178880..22587f0d3 100644
--- a/ccm-core/src/main/java/org/libreccm/theming/ThemesService.java
+++ b/ccm-core/src/main/java/org/libreccm/theming/ThemesService.java
@@ -36,6 +36,7 @@ public class ThemesService extends Application {
final Set> classes = new HashSet<>();
classes.add(ThemeFiles.class);
+ classes.add(ThemeFilesDav.class);
return classes;
}
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/Headers.java b/ccm-core/src/main/java/org/libreccm/webdav/Headers.java
new file mode 100644
index 000000000..186401867
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/Headers.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2018 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 org.libreccm.webdav;
+
+/**
+ * WebDAV Headers.
+ *
+ * The class is based on a class/interface from java.net WebDAV Project:
+ *
+ * https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/Headers.java
+ *
+ *
+ * @author Markus KARG
+ * @author Jens Pelzetter
+ *
+ * @see
+ *
+ * Chapter 10 "HTTP Headers for Distributed Authoring" of RFC 4918 "HTTP
+ * Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ *
+ */
+public final class Headers {
+
+ /**
+ * WebDAV DAV Header
+ *
+ * @see
+ * Chapter
+ * 10.1 "DAV Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String DAV = "DAV";
+
+ /**
+ * WebDAV Depth Header
+ *
+ * @see
+ * Chapter
+ * 10.2 "Depth Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String DEPTH = "Depth";
+
+ /**
+ * WebDAV Depth Header Value "0"
+ *
+ * @see
+ * Chapter
+ * 10.2 "Depth Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String DEPTH_0 = "0";
+
+ /**
+ * WebDAV Depth Header Value "1"
+ *
+ * @see
+ * Chapter
+ * 10.2 "Depth Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String DEPTH_1 = "1";
+
+ /**
+ * WebDAV Depth Header Value "infinity"
+ *
+ * @see
+ * Chapter
+ * 10.2 "Depth Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String DEPTH_INFINITY = "infinity";
+
+ /**
+ * WebDAV Destination Header
+ *
+ * @see
+ * Chapter
+ * 10.3 "Destination Header" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ public static final String DESTINATION = "Destination";
+
+ /**
+ * WebDAV If Header
+ *
+ * @see Chapter
+ * 10.4 "If Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String IF = "If";
+
+ /**
+ * WebDAV Lock-Token Header
+ *
+ * @see
+ * Chapter
+ * 10.5 "Lock-Token Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String LOCK_TOKEN = "Lock-Token";
+
+ /**
+ * WebDAV Overwrite Header
+ *
+ * @see
+ * Chapter
+ * 10.6 "Overwrite Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String OVERWRITE = "Overwrite";
+
+ /**
+ * WebDAV Overwrite Header Value "T"
+ *
+ * @see
+ * Chapter
+ * 10.6 "Overwrite Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String OVERWRITE_TRUE = "T";
+
+ /**
+ * WebDAV Overwrite Header Value "F"
+ *
+ * @see
+ * Chapter
+ * 10.6 "Overwrite Header" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ public static final String OVERWRITE_FALSE = "F";
+
+ /**
+ * WebDAV Timeout Header
+ *
+ * @see
+ * Chapter
+ * 10.7 "Timeout Request Header" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ public static final String TIMEOUT = "Timeout";
+
+ /**
+ * WebDAV Timeout Header Value "Second-"
+ *
+ * @see
+ * Chapter
+ * 10.7 "Timeout Request Header" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ public static final String TIMEOUT_SECOND = "Second-";
+
+ /**
+ * WebDAV Timeout Header Value "Infinite"
+ *
+ * @see
+ * Chapter
+ * 10.7 "Timeout Request Header" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ public static final String TIMEOUT_INFINITE = "Infinite";
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/ResponseStatus.java b/ccm-core/src/main/java/org/libreccm/webdav/ResponseStatus.java
new file mode 100644
index 000000000..2d60a824f
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/ResponseStatus.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2018 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 org.libreccm.webdav;
+
+import javax.ws.rs.core.Response;
+
+import static javax.ws.rs.core.Response.Status.Family.*;
+
+/**
+ * Commonly used status codes defined by WebDAV.
+ *
+ * The enum is based on an enum from the java.net WebDAV project:
+ *
+ * https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/ResponseStatus.java
+ *
+ * @author Markus KARG
+ * @author Jens Pelzetter
+ *
+ * @see
+ * Chapter
+ * 11 "Status Code Extensions to HTTP/1.1" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+public enum ResponseStatus implements Response.StatusType {
+
+ /**
+ * 207 Multi-Status
+ *
+ * @see
+ * Chapter
+ * 11.1 "207 Multi-Status" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ MULTI_STATUS(207, "Multi-Status"),
+ /**
+ * 422 Unprocessable Entity
+ *
+ * @see
+ * Chapter
+ * 11.2 "422 Unprocessable Entity" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"),
+ /**
+ * 423 Locked
+ *
+ * @see
+ * Chapter
+ * 11.3 "423 Locked" of RFC 4918 "HTTP Extensions for Web Distributed
+ * Authoring and Versioning (WebDAV)"
+ */
+ LOCKED(423, "Locked"),
+ /**
+ * 424 Failed Dependency
+ *
+ * @see
+ * Chapter
+ * 11.4 "424 Failed Dependency" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ FAILED_DEPENDENCY(424, "Failed Dependency"),
+ /**
+ * 507 Insufficient Storage
+ *
+ * @see
+ * Chapter
+ * 11.5 "507 Insufficient Storage" of RFC 4918 "HTTP Extensions for Web
+ * Distributed Authoring and Versioning (WebDAV)"
+ */
+ INSUFFICIENT_STORAGE(507, "Insufficient Storage");
+
+ private final int statusCode;
+
+ private final String reasonPhrase;
+
+ private ResponseStatus(final int statusCode, final String reasonPhrase) {
+ this.statusCode = statusCode;
+ this.reasonPhrase = reasonPhrase;
+ }
+
+ @Override
+ public int getStatusCode() {
+ return statusCode;
+
+ }
+
+ @Override
+ public Response.Status.Family getFamily() {
+ switch (this.statusCode / 100) {
+ case 1:
+ return INFORMATIONAL;
+ case 2:
+ return SUCCESSFUL;
+ case 3:
+ return REDIRECTION;
+ case 4:
+ return CLIENT_ERROR;
+ case 5:
+ return SERVER_ERROR;
+ default:
+ return OTHER;
+ }
+ }
+
+ @Override
+ public String getReasonPhrase() {
+ return reasonPhrase;
+ }
+
+ @Override
+ public String toString() {
+ return reasonPhrase;
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/COPY.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/COPY.java
new file mode 100644
index 000000000..1b6085772
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/COPY.java
@@ -0,0 +1,49 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV COPY requests.
+ *
+ * Adopted from
+ * https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/COPY.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter
+ * 9.8 "COPY Method" of RFC 4918 "HTTP Extensions for Web Distributed Authoring
+ * and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("COPY")
+public @interface COPY {
+ // Has no members.
+}
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/LOCK.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/LOCK.java
new file mode 100644
index 000000000..eda697149
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/LOCK.java
@@ -0,0 +1,49 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV LOCK requests.
+ *
+ * Adopted from
+ * https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/LOCK.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter
+ * 9.10 "LOCK Method" of RFC 4918 "HTTP Extensions for Web Distributed Authoring
+ * and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("LOCK")
+public @interface LOCK {
+ // Has no members.
+}
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/MKCOL.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/MKCOL.java
new file mode 100644
index 000000000..c1f73e3ac
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/MKCOL.java
@@ -0,0 +1,47 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV MKCOL requests.
+ *
+ * Adopted from https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/MKCOL.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter 9.3 "MKCOL Method" of RFC 4918
+ * "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("MKCOL")
+public @interface MKCOL {
+ // Has no members.
+}
\ No newline at end of file
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/MOVE.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/MOVE.java
new file mode 100644
index 000000000..e3159f134
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/MOVE.java
@@ -0,0 +1,47 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV MOVE requests.
+ *
+ * Adopted from https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/MOVE.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter 9.9 "COPY Method" of RFC 4918
+ * "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("MOVE")
+public @interface MOVE {
+ // Has no members.
+}
\ No newline at end of file
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPFIND.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPFIND.java
new file mode 100644
index 000000000..f2a271b91
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPFIND.java
@@ -0,0 +1,47 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV PROPFIND requests.
+ *
+ * Adopted from https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/PROPFIND.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter 9.1 "PROPFIND Method" of RFC 4918
+ * "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("PROPFIND")
+public @interface PROPFIND {
+ // Has no members.
+}
\ No newline at end of file
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPPATCH.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPPATCH.java
new file mode 100644
index 000000000..5eefd7ff1
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/PROPPATCH.java
@@ -0,0 +1,47 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV PROPPATCH requests.
+ *
+ * Adopted from https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/PROPPATCH.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter 9.2 "PROPPATCH Method" of RFC 4918
+ * "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("PROPPATCH")
+public @interface PROPPATCH {
+ // Has no members.
+}
\ No newline at end of file
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/UNLOCK.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/UNLOCK.java
new file mode 100644
index 000000000..252583fd1
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/UNLOCK.java
@@ -0,0 +1,47 @@
+/*
+ * #%L
+ * WebDAV Support for JAX-RS
+ * %%
+ * Copyright (C) 2008 - 2018 The java.net WebDAV Project
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+package org.libreccm.webdav.methods;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Indicates that the annotated method responds to WebDAV UNLOCK requests.
+ *
+ * Adopted from https://gitlab.com/headcrashing/webdav-jaxrs/blob/master/src/main/java/net/java/dev/webdav/jaxrs/methods/UNLOCK.java
+ *
+ * @author Markus KARG (mkarg@java.net)
+ *
+ * @see Chapter 9.11 "UNLOCK Method" of RFC 4918
+ * "HTTP Extensions for Web Distributed Authoring and Versioning (WebDAV)"
+ */
+@Target(METHOD)
+@Retention(RUNTIME)
+@HttpMethod("UNLOCK")
+public @interface UNLOCK {
+ // Has no members.
+}
\ No newline at end of file
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/methods/package-info.java b/ccm-core/src/main/java/org/libreccm/webdav/methods/package-info.java
new file mode 100644
index 000000000..6db2e3567
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/methods/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2018 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
+ */
+/**
+ * Annotations for the WebDAV HTTP methods.
+ */
+package org.libreccm.webdav.methods;
diff --git a/ccm-core/src/main/java/org/libreccm/webdav/package-info.java b/ccm-core/src/main/java/org/libreccm/webdav/package-info.java
new file mode 100644
index 000000000..22d886d3c
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/webdav/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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
+ */
+/**
+ * Annotations and classes for exposing resources via WebDAV using JAX-RS.
+ * The classes in these packages are based on classes originally created for
+ * JAX-RS. This project was hosted on the now defunct dev.java.net site. The
+ * sources now be found at {@link https://gitlab.com/headcrashing/webdav-jaxrs}.
+ * Unfortunately the project is not maintained anymore and has not been updated
+ * for JAX-RS 2. Therefore we used the classes only as foundation for our
+ * implementation. The classes have been edited to match our coding standards
+ * and to be compatible with new versions of JAX-RS and other libraries.
+ */
+package org.libreccm.webdav;