CCM NG: Primarly bug fixing for the selection models
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@3897 8810af33-2d31-482b-a856-94f89814c4dfpull/2/head
parent
2d30f3d69f
commit
beb702efd9
|
|
@ -6,7 +6,7 @@
|
||||||
</Console>
|
</Console>
|
||||||
</Appenders>
|
</Appenders>
|
||||||
<Loggers>
|
<Loggers>
|
||||||
<Root level="info">
|
<Root level="warn">
|
||||||
<AppenderRef ref="Console"/>
|
<AppenderRef ref="Console"/>
|
||||||
</Root>
|
</Root>
|
||||||
<Logger name="com.arsdigita.ui.admin.AdminServlet"
|
<Logger name="com.arsdigita.ui.admin.AdminServlet"
|
||||||
|
|
@ -22,7 +22,10 @@
|
||||||
level="debug">
|
level="debug">
|
||||||
</Logger>
|
</Logger>
|
||||||
<Logger name="com.arsdigita.templating.PatternStylesheetResolver"
|
<Logger name="com.arsdigita.templating.PatternStylesheetResolver"
|
||||||
level="debug">
|
level="info">
|
||||||
|
</Logger>
|
||||||
|
<Logger name="com.arsdigita.templating.SimpleURIResolver"
|
||||||
|
level="warn">
|
||||||
</Logger>
|
</Logger>
|
||||||
<Logger name="com.arsdigita.web.CCMDispatcherServlet"
|
<Logger name="com.arsdigita.web.CCMDispatcherServlet"
|
||||||
level="debug">
|
level="debug">
|
||||||
|
|
|
||||||
|
|
@ -26,20 +26,28 @@ import com.arsdigita.bebop.event.EventListenerList;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
import com.arsdigita.util.Lockable;
|
import com.arsdigita.util.Lockable;
|
||||||
|
|
||||||
/**
|
import java.util.stream.Stream;
|
||||||
* A standard implementation of <code>SingleSelectionModel</code> and
|
|
||||||
* <code>Lockable</code>. Those wishing to define a SingleSelectionModel
|
|
||||||
* will ordinarily want to extend this class.
|
|
||||||
*
|
|
||||||
* @version $Id: AbstractSingleSelectionModel.java 287 2005-02-22 00:29:02Z sskracic $
|
|
||||||
*/
|
|
||||||
public abstract class AbstractSingleSelectionModel
|
|
||||||
implements SingleSelectionModel, Lockable {
|
|
||||||
|
|
||||||
private EventListenerList m_listeners;
|
/**
|
||||||
|
* A standard implementation of <code>SingleSelectionModel</code> and
|
||||||
|
* <code>Lockable</code>. Those wishing to define a SingleSelectionModel will
|
||||||
|
* ordinarily want to extend this class.
|
||||||
|
*
|
||||||
|
* jensp: Added generics and Java 8 streams instead of using an iterator.
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
*
|
||||||
|
* @author Unknown
|
||||||
|
* @author Jens Pelzetter (jensp)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractSingleSelectionModel<T>
|
||||||
|
implements SingleSelectionModel<T>, Lockable {
|
||||||
|
|
||||||
|
private final EventListenerList m_listeners;
|
||||||
private boolean m_locked;
|
private boolean m_locked;
|
||||||
|
|
||||||
/** Creates a new AbstractSingleSelectionModel.
|
/**
|
||||||
|
* Creates a new AbstractSingleSelectionModel.
|
||||||
*/
|
*/
|
||||||
public AbstractSingleSelectionModel() {
|
public AbstractSingleSelectionModel() {
|
||||||
m_listeners = new EventListenerList();
|
m_listeners = new EventListenerList();
|
||||||
|
|
@ -49,51 +57,57 @@ public abstract class AbstractSingleSelectionModel
|
||||||
* Returns <code>true</code> if there is a selected element.
|
* Returns <code>true</code> if there is a selected element.
|
||||||
*
|
*
|
||||||
* @param state the state of the current request
|
* @param state the state of the current request
|
||||||
|
*
|
||||||
* @return <code>true</code> if there is a selected component;
|
* @return <code>true</code> if there is a selected component;
|
||||||
* <code>false</code> otherwise.
|
* <code>false</code> otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean isSelected(PageState state) {
|
@Override
|
||||||
|
public boolean isSelected(final PageState state) {
|
||||||
return getSelectedKey(state) != null;
|
return getSelectedKey(state) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract Object getSelectedKey(PageState state);
|
@Override
|
||||||
|
public abstract T getSelectedKey(final PageState state);
|
||||||
|
|
||||||
public abstract void setSelectedKey(PageState state, Object key);
|
@Override
|
||||||
|
public abstract void setSelectedKey(final PageState state, final T key);
|
||||||
|
|
||||||
public void clearSelection(PageState state) {
|
@Override
|
||||||
|
public void clearSelection(final PageState state) {
|
||||||
setSelectedKey(state, null);
|
setSelectedKey(state, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection change events
|
// Selection change events
|
||||||
|
@Override
|
||||||
public void addChangeListener(ChangeListener l) {
|
public void addChangeListener(final ChangeListener changeListener) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_listeners.add(ChangeListener.class, l);
|
m_listeners.add(ChangeListener.class, changeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeChangeListener(ChangeListener l) {
|
@Override
|
||||||
|
public void removeChangeListener(final ChangeListener changeListener) {
|
||||||
Assert.isUnlocked(this);
|
Assert.isUnlocked(this);
|
||||||
m_listeners.remove(ChangeListener.class, l);
|
m_listeners.remove(ChangeListener.class, changeListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fireStateChanged(PageState state) {
|
protected void fireStateChanged(final PageState state) {
|
||||||
Iterator i = m_listeners.getListenerIterator(ChangeListener.class);
|
final ChangeEvent event = new ChangeEvent(this, state);
|
||||||
ChangeEvent e = null;
|
final Iterator<ChangeListener> iterator = m_listeners
|
||||||
|
.getListenerIterator(ChangeListener.class);
|
||||||
while (i.hasNext()) {
|
while(iterator.hasNext()) {
|
||||||
if ( e == null ) {
|
iterator.next().stateChanged(event);
|
||||||
e = new ChangeEvent(this, state);
|
|
||||||
}
|
|
||||||
((ChangeListener) i.next()).stateChanged(e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// implement Lockable
|
// implement Lockable
|
||||||
|
@Override
|
||||||
public void lock() {
|
public void lock() {
|
||||||
m_locked = true;
|
m_locked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final boolean isLocked() {
|
public final boolean isLocked() {
|
||||||
return m_locked;
|
return m_locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import com.arsdigita.xml.Element;
|
||||||
* of certain parts of the screen. Therefore the label has to use a
|
* of certain parts of the screen. Therefore the label has to use a
|
||||||
* GlobalizedMessage for the information presented.
|
* GlobalizedMessage for the information presented.
|
||||||
*
|
*
|
||||||
* A Label is meant to provide semantically relevant informatin and may not be
|
* A Label is meant to provide semantically relevant information and may not be
|
||||||
* used for fixed arbitrary Text. Use Embedded instead.
|
* used for fixed arbitrary Text. Use Embedded instead.
|
||||||
*
|
*
|
||||||
* (Previous usage: can be used to generate either some static, fixed
|
* (Previous usage: can be used to generate either some static, fixed
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,15 @@ import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
import com.arsdigita.util.Assert;
|
import com.arsdigita.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of {@link SingleSelectionModel} that uses
|
* An implementation of {@link SingleSelectionModel} that uses a state parameter
|
||||||
* a state parameter for managing the currently selected key.
|
* for managing the currently selected key.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
*
|
||||||
* A typical use case for this class is as follows.
|
* A typical use case for this class is as follows.
|
||||||
* <blockquote><pre><code>public TheConstructor() {
|
* <blockquote>
|
||||||
|
* <pre>
|
||||||
|
* <code>
|
||||||
|
* public TheConstructor() {
|
||||||
* m_parameter = new StringParameter("my_key");
|
* m_parameter = new StringParameter("my_key");
|
||||||
* m_sel = new ParameterSingleSelectionModel(m_parameter);
|
* m_sel = new ParameterSingleSelectionModel(m_parameter);
|
||||||
* }
|
* }
|
||||||
|
|
@ -35,22 +38,29 @@ import com.arsdigita.util.Assert;
|
||||||
* public void register(Page p) {
|
* public void register(Page p) {
|
||||||
* p.addComponent(this);
|
* p.addComponent(this);
|
||||||
* p.addComponentStateParam(this, m_param);
|
* p.addComponentStateParam(this, m_param);
|
||||||
* }</code></pre></blockquote>
|
* }
|
||||||
|
* </code>
|
||||||
|
* </pre>
|
||||||
|
* </blockquote>
|
||||||
|
*
|
||||||
|
* jensp 2016-02-26: Added generics
|
||||||
|
*
|
||||||
|
* @param <T> Generics parameter
|
||||||
*
|
*
|
||||||
* @author Stanislav Freidin
|
* @author Stanislav Freidin
|
||||||
* @version $Id: ParameterSingleSelectionModel.java 287 2005-02-22 00:29:02Z sskracic $
|
* @author Jens Pelzetter
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class ParameterSingleSelectionModel
|
public class ParameterSingleSelectionModel<T>
|
||||||
extends AbstractSingleSelectionModel {
|
extends AbstractSingleSelectionModel<T> {
|
||||||
|
|
||||||
|
private final ParameterModel m_parameter;
|
||||||
private ParameterModel m_parameter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new ParameterSingleSelectionModel.
|
* Constructs a new ParameterSingleSelectionModel.
|
||||||
*
|
*
|
||||||
* @param m the parameter model that will be used to
|
* @param m the parameter model that will be used to keep track of the
|
||||||
* keep track of the currently selected key
|
* currently selected key
|
||||||
*/
|
*/
|
||||||
public ParameterSingleSelectionModel(ParameterModel m) {
|
public ParameterSingleSelectionModel(ParameterModel m) {
|
||||||
super();
|
super();
|
||||||
|
|
@ -62,17 +72,21 @@ public class ParameterSingleSelectionModel
|
||||||
* Returns the key that identifies the selected element.
|
* Returns the key that identifies the selected element.
|
||||||
*
|
*
|
||||||
* @param state a <code>PageState</code> value
|
* @param state a <code>PageState</code> value
|
||||||
|
*
|
||||||
* @return a <code>String</code> value.
|
* @return a <code>String</code> value.
|
||||||
*/
|
*/
|
||||||
public Object getSelectedKey(PageState state) {
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T getSelectedKey(final PageState state) {
|
||||||
final FormModel model = state.getPage().getStateModel();
|
final FormModel model = state.getPage().getStateModel();
|
||||||
if (model.containsFormParam(m_parameter)) {
|
if (model.containsFormParam(m_parameter)) {
|
||||||
return state.getValue(m_parameter);
|
return (T) state.getValue(m_parameter);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public final ParameterModel getStateParameter() {
|
public final ParameterModel getStateParameter() {
|
||||||
return m_parameter;
|
return m_parameter;
|
||||||
}
|
}
|
||||||
|
|
@ -80,10 +94,11 @@ public class ParameterSingleSelectionModel
|
||||||
/**
|
/**
|
||||||
* Set the selected key.
|
* Set the selected key.
|
||||||
*
|
*
|
||||||
* @param state represents the state of the current request
|
* @param state represents the state of the current request
|
||||||
* @param newKey the new selected key
|
* @param newKey the new selected key
|
||||||
*/
|
*/
|
||||||
public void setSelectedKey(PageState state, Object newKey) {
|
@Override
|
||||||
|
public void setSelectedKey(final PageState state, final Object newKey) {
|
||||||
final Object oldKey = getSelectedKey(state);
|
final Object oldKey = getSelectedKey(state);
|
||||||
|
|
||||||
if (Assert.isEnabled()) {
|
if (Assert.isEnabled()) {
|
||||||
|
|
@ -103,4 +118,5 @@ public class ParameterSingleSelectionModel
|
||||||
|
|
||||||
fireStateChanged(state);
|
fireStateChanged(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,10 +38,14 @@ import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
* key's <code>toString</code> method produces a representation of the key
|
* key's <code>toString</code> method produces a representation of the key
|
||||||
* that can be used in URL strings and hidden form controls.
|
* that can be used in URL strings and hidden form controls.
|
||||||
*
|
*
|
||||||
|
* Edit for CCM NG: Added generics.
|
||||||
|
*
|
||||||
|
* @param <T> Type for the key
|
||||||
|
*
|
||||||
* @author David Lutterkort
|
* @author David Lutterkort
|
||||||
* @version $Id: SingleSelectionModel.java 287 2005-02-22 00:29:02Z sskracic $
|
* @author Jens Pelzetter
|
||||||
*/
|
*/
|
||||||
public interface SingleSelectionModel {
|
public interface SingleSelectionModel<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns <code>true</code> if there is a selected element.
|
* Returns <code>true</code> if there is a selected element.
|
||||||
|
|
@ -58,7 +62,7 @@ public interface SingleSelectionModel {
|
||||||
* @param state a <code>PageState</code> value
|
* @param state a <code>PageState</code> value
|
||||||
* @return a <code>String</code> value.
|
* @return a <code>String</code> value.
|
||||||
*/
|
*/
|
||||||
Object getSelectedKey(PageState state);
|
T getSelectedKey(PageState state);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the selected key. If <code>key</code> is not in the collection of
|
* Sets the selected key. If <code>key</code> is not in the collection of
|
||||||
|
|
@ -70,7 +74,7 @@ public interface SingleSelectionModel {
|
||||||
* @throws IllegalArgumentException if the supplied <code>key</code> can not
|
* @throws IllegalArgumentException if the supplied <code>key</code> can not
|
||||||
* be selected in the context of the current request.
|
* be selected in the context of the current request.
|
||||||
*/
|
*/
|
||||||
void setSelectedKey(PageState state, Object key);
|
void setSelectedKey(PageState state, T key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the selection.
|
* Clears the selection.
|
||||||
|
|
@ -84,16 +88,16 @@ public interface SingleSelectionModel {
|
||||||
* Adds a change listener to the model. The listener's
|
* Adds a change listener to the model. The listener's
|
||||||
* <code>stateChanged</code> method is called whenever the selected key changes.
|
* <code>stateChanged</code> method is called whenever the selected key changes.
|
||||||
*
|
*
|
||||||
* @param l a listener to notify when the selected key changes
|
* @param changeListener a listener to notify when the selected key changes
|
||||||
*/
|
*/
|
||||||
void addChangeListener(ChangeListener l);
|
void addChangeListener(ChangeListener changeListener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a change listener from the model.
|
* Removes a change listener from the model.
|
||||||
*
|
*
|
||||||
* @param l the listener to remove
|
* @param changeListener the listener to remove
|
||||||
*/
|
*/
|
||||||
void removeChangeListener(ChangeListener l);
|
void removeChangeListener(ChangeListener changeListener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the state parameter that will be used to keep track
|
* Returns the state parameter that will be used to keep track
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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.bebop;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.event.PrintEvent;
|
||||||
|
import com.arsdigita.bebop.event.PrintListener;
|
||||||
|
import com.arsdigita.util.UncheckedWrapperException;
|
||||||
|
import com.arsdigita.xml.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class Text extends SimpleComponent {
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
private boolean outputEscaped;
|
||||||
|
private PrintListener printListener;
|
||||||
|
|
||||||
|
public Text() {
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text(final String text) {
|
||||||
|
this.text = text;
|
||||||
|
outputEscaped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Text(final PrintListener printListener) {
|
||||||
|
this();
|
||||||
|
this.printListener = printListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(final String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOutputEscaped() {
|
||||||
|
return outputEscaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputEscaped(final boolean outputEscaped) {
|
||||||
|
this.outputEscaped = outputEscaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrintListener(final PrintListener printListener) {
|
||||||
|
if (printListener == null) {
|
||||||
|
throw new IllegalArgumentException("PrintListener can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.printListener = printListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateXML(final PageState state, final Element parent) {
|
||||||
|
|
||||||
|
if (!isVisible(state)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Text target = firePrintEvent(state);
|
||||||
|
|
||||||
|
final Element textElem = parent.newChildElement("bebop:text",
|
||||||
|
BEBOP_XML_NS);
|
||||||
|
|
||||||
|
target.exportAttributes(textElem);
|
||||||
|
|
||||||
|
if (outputEscaped) {
|
||||||
|
textElem.addAttribute("escape", "no");
|
||||||
|
} else {
|
||||||
|
textElem.addAttribute("escape", "yes");
|
||||||
|
}
|
||||||
|
|
||||||
|
textElem.setText(target.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Text firePrintEvent(final PageState state) {
|
||||||
|
final Text component;
|
||||||
|
if (printListener == null) {
|
||||||
|
component = this;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
component = (Text) this.clone();
|
||||||
|
printListener.prepare(new PrintEvent(this, state, component));
|
||||||
|
} catch (CloneNotSupportedException ex) {
|
||||||
|
throw new UncheckedWrapperException(
|
||||||
|
"Could not clone Text component for PrintListener. "
|
||||||
|
+ "This propaby indicates a serious programming error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -28,22 +28,25 @@ import java.util.NoSuchElementException;
|
||||||
*/
|
*/
|
||||||
public class EventListenerList extends javax.swing.event.EventListenerList {
|
public class EventListenerList extends javax.swing.event.EventListenerList {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -1930203818146602205L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append all the event listeners from <code>l</code>.
|
* Append all the event listeners from <code>l</code>.
|
||||||
*
|
*
|
||||||
* @param l The list of listeners to copy from
|
* @param list The list of listeners to copy from
|
||||||
*
|
*
|
||||||
* @pre l != null
|
* @pre l != null
|
||||||
*/
|
*/
|
||||||
public void addAll(EventListenerList l) {
|
public void addAll(final EventListenerList list) {
|
||||||
|
|
||||||
if ( l.listenerList.length == 0 )
|
if ( list.listenerList.length == 0 ) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Object[] tmp = new Object[listenerList.length + l.listenerList.length];
|
Object[] tmp = new Object[listenerList.length + list.listenerList.length];
|
||||||
System.arraycopy(listenerList, 0, tmp, 0, listenerList.length);
|
System.arraycopy(listenerList, 0, tmp, 0, listenerList.length);
|
||||||
System.arraycopy(l.listenerList, 0,
|
System.arraycopy(list.listenerList, 0,
|
||||||
tmp, listenerList.length, l.listenerList.length);
|
tmp, listenerList.length, list.listenerList.length);
|
||||||
listenerList = tmp;
|
listenerList = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,15 +56,17 @@ public class EventListenerList extends javax.swing.event.EventListenerList {
|
||||||
* {@link javax.swing.event.EventListenerList Swing's
|
* {@link javax.swing.event.EventListenerList Swing's
|
||||||
* <code>EventListenerList</code>}.
|
* <code>EventListenerList</code>}.
|
||||||
*
|
*
|
||||||
* @param t The class of the event listeners that should be returned
|
* @param <T>
|
||||||
|
* @param type The class of the event listeners that should be returned
|
||||||
|
* @return
|
||||||
*
|
*
|
||||||
* @pre t != null
|
* @pre t != null
|
||||||
* */
|
* */
|
||||||
public Iterator getListenerIterator(final Class t) {
|
public <T> Iterator<T> getListenerIterator(final Class<T> type) {
|
||||||
return new EventListenerIterator(t);
|
return new EventListenerIterator<>(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EventListenerIterator implements Iterator {
|
private class EventListenerIterator<T> implements Iterator<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The listener we will return with the next call to next().
|
* The listener we will return with the next call to next().
|
||||||
|
|
@ -69,31 +74,35 @@ public class EventListenerList extends javax.swing.event.EventListenerList {
|
||||||
* matching listeners have been returned, in which case _next
|
* matching listeners have been returned, in which case _next
|
||||||
* is -1
|
* is -1
|
||||||
* */
|
* */
|
||||||
private int _count;
|
private final int count;
|
||||||
private int _next;
|
private int next;
|
||||||
private Class _t;
|
private final Class<T> type;
|
||||||
|
|
||||||
EventListenerIterator(Class t) {
|
EventListenerIterator(Class<T> type) {
|
||||||
|
|
||||||
_count = getListenerList().length;
|
count = getListenerList().length;
|
||||||
_next = -2;
|
next = -2;
|
||||||
_t = t;
|
this.type = type;
|
||||||
findNext();
|
findNext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return (_next < _count);
|
return (next < count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object next() throws NoSuchElementException {
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T next() throws NoSuchElementException {
|
||||||
if ( ! hasNext() ) {
|
if ( ! hasNext() ) {
|
||||||
throw new NoSuchElementException("Iterator exhausted");
|
throw new NoSuchElementException("Iterator exhausted");
|
||||||
}
|
}
|
||||||
int result = _next;
|
int result = next;
|
||||||
findNext();
|
findNext();
|
||||||
return getListenerList()[result+1];
|
return (T) getListenerList()[result+1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void remove() throws UnsupportedOperationException {
|
public void remove() throws UnsupportedOperationException {
|
||||||
throw new UnsupportedOperationException("Removal not supported");
|
throw new UnsupportedOperationException("Removal not supported");
|
||||||
}
|
}
|
||||||
|
|
@ -108,14 +117,14 @@ public class EventListenerList extends javax.swing.event.EventListenerList {
|
||||||
* */
|
* */
|
||||||
private void findNext() {
|
private void findNext() {
|
||||||
|
|
||||||
for (int i = _next+2; i<_count; i+=2) {
|
for (int i = next+2; i<count; i+=2) {
|
||||||
|
|
||||||
if (getListenerList()[i] == _t) {
|
if (getListenerList()[i] == type) {
|
||||||
_next = i;
|
next = i;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_next = _count;
|
next = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ public class LongParameter extends NumberParameter {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object unmarshal(String encoded) {
|
public Object unmarshal(String encoded) {
|
||||||
try {
|
try {
|
||||||
return new Long(encoded);
|
return new Long(encoded);
|
||||||
|
|
@ -43,6 +44,7 @@ public class LongParameter extends NumberParameter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Class getValueClass() {
|
public Class getValueClass() {
|
||||||
return Long.class;
|
return Long.class;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the abstract model for a form parameter object. This
|
* Represents the abstract model for a form parameter object. This
|
||||||
* class must be subclassed for each specific data type.
|
* class must be subclassed for each specific data type.
|
||||||
|
|
@ -495,4 +497,24 @@ public abstract class ParameterModel implements Lockable {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object other) {
|
||||||
|
if (other == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(other instanceof ParameterModel)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_name.equals(((ParameterModel) other).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 7;
|
||||||
|
hash = 73 * hash + Objects.hashCode(this.m_name);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.templating;
|
package com.arsdigita.templating;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
|
|
@ -32,7 +34,7 @@ import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.URIResolver;
|
import javax.xml.transform.URIResolver;
|
||||||
import javax.xml.transform.stream.StreamSource;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An implementation of the URIResolver interface that keeps track of all the
|
* An implementation of the URIResolver interface that keeps track of all the
|
||||||
|
|
@ -44,7 +46,7 @@ import org.apache.log4j.Logger;
|
||||||
*/
|
*/
|
||||||
final class SimpleURIResolver implements URIResolver {
|
final class SimpleURIResolver implements URIResolver {
|
||||||
|
|
||||||
private static final Logger s_log = Logger.getLogger
|
private static final Logger s_log = LogManager.getLogger
|
||||||
(SimpleURIResolver.class);
|
(SimpleURIResolver.class);
|
||||||
|
|
||||||
private final Set m_uniqueStylesheetURIs;
|
private final Set m_uniqueStylesheetURIs;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 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;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.SingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.event.ChangeListener;
|
||||||
|
import com.arsdigita.bebop.parameters.LongParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.ParameterModel;
|
||||||
|
|
||||||
|
import org.libreccm.cdi.utils.CdiUtil;
|
||||||
|
import org.libreccm.core.CcmObject;
|
||||||
|
import org.libreccm.core.CcmObjectRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <T>
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
|
||||||
|
*/
|
||||||
|
public class CcmObjectSelectionModel<T extends CcmObject>
|
||||||
|
implements SingleSelectionModel<Long>{
|
||||||
|
|
||||||
|
private final Class<T> clazz;
|
||||||
|
private final SingleSelectionModel<Long> model;
|
||||||
|
|
||||||
|
public CcmObjectSelectionModel(final LongParameter parameter) {
|
||||||
|
this(null, parameter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CcmObjectSelectionModel(final String parameterName) {
|
||||||
|
this(null, new LongParameter(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// public CcmObjectSelectionModel(final SingleSelectionModel<T> model ) {
|
||||||
|
// this(null, model);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
public CcmObjectSelectionModel(final Class<T> clazz,
|
||||||
|
final String parameterName) {
|
||||||
|
this(clazz, new LongParameter(parameterName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CcmObjectSelectionModel(final Class<T> clazz,
|
||||||
|
final LongParameter parameter) {
|
||||||
|
this(clazz, new ParameterSingleSelectionModel<>(parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CcmObjectSelectionModel(final Class<T> clazz,
|
||||||
|
final SingleSelectionModel<Long> model) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.model = model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected(final PageState state) {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getSelectedKey(final PageState state) {
|
||||||
|
return model.getSelectedKey(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelectedKey(final PageState state, final Long key) {
|
||||||
|
model.setSelectedKey(state, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getSelectedObject(final PageState state) {
|
||||||
|
final Long key = getSelectedKey(state);
|
||||||
|
final CcmObjectRepository repository = CdiUtil.createCdiUtil().findBean(
|
||||||
|
CcmObjectRepository.class);
|
||||||
|
//final T object = repository.findById(key);
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearSelection(PageState state) {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addChangeListener(ChangeListener changeListener) {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeChangeListener(ChangeListener changeListener) {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParameterModel getStateParameter() {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,7 @@ package com.arsdigita.ui.admin;
|
||||||
|
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
import com.arsdigita.bebop.parameters.BigDecimalParameter;
|
||||||
|
import com.arsdigita.bebop.parameters.LongParameter;
|
||||||
import com.arsdigita.globalization.GlobalizedMessage;
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -100,11 +101,11 @@ interface AdminConstants {
|
||||||
/**
|
/**
|
||||||
* Global state parameters.
|
* Global state parameters.
|
||||||
*/
|
*/
|
||||||
BigDecimalParameter GROUP_ID_PARAM = new BigDecimalParameter("group_id");
|
LongParameter GROUP_ID_PARAM = new LongParameter("group_id");
|
||||||
|
|
||||||
BigDecimalParameter APPLICATIONS_ID_PARAM = new BigDecimalParameter("application_id");
|
LongParameter APPLICATIONS_ID_PARAM = new LongParameter("application_id");
|
||||||
|
|
||||||
BigDecimalParameter USER_ID_PARAM = new BigDecimalParameter("user_id");
|
LongParameter USER_ID_PARAM = new LongParameter("user_id");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User summary panel.
|
* User summary panel.
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,64 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.ui.admin.usersgroupsroles;
|
package com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.ActionLink;
|
||||||
import com.arsdigita.bebop.BoxPanel;
|
import com.arsdigita.bebop.BoxPanel;
|
||||||
|
import com.arsdigita.bebop.Form;
|
||||||
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||||
|
import com.arsdigita.bebop.Text;
|
||||||
|
import com.arsdigita.bebop.event.PrintEvent;
|
||||||
|
import com.arsdigita.bebop.form.Submit;
|
||||||
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
import com.arsdigita.bebop.parameters.LongParameter;
|
||||||
|
import com.arsdigita.globalization.GlobalizedMessage;
|
||||||
|
|
||||||
|
import static com.arsdigita.ui.admin.AdminUiConstants.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
*/
|
*/
|
||||||
public class UserAdmin extends BoxPanel {
|
public class UserAdmin extends BoxPanel {
|
||||||
|
|
||||||
|
private final ParameterSingleSelectionModel<String> selectedUserId;
|
||||||
|
private final TextField usersTableFilter;
|
||||||
|
|
||||||
public UserAdmin() {
|
public UserAdmin() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
//add(new Label("User Admin class"));
|
//add(new Label("User Admin class"));
|
||||||
add(new UsersTable());
|
final Form filterForm = new Form("usersTableFilterForm");
|
||||||
|
usersTableFilter = new TextField("usersTableFilter");
|
||||||
|
usersTableFilter.setLabel(new GlobalizedMessage(
|
||||||
|
"ui.admin.users.table.filter.term", ADMIN_BUNDLE));
|
||||||
|
filterForm.add(usersTableFilter);
|
||||||
|
filterForm.add(new Submit(new GlobalizedMessage(
|
||||||
|
"ui.admin.users.table.filter.submit", ADMIN_BUNDLE)));
|
||||||
|
final ActionLink clearLink = new ActionLink(new GlobalizedMessage(
|
||||||
|
"ui.admin.users.table.filter.clear", ADMIN_BUNDLE));
|
||||||
|
clearLink.addActionListener((e) -> {
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
usersTableFilter.setValue(state, null);
|
||||||
|
});
|
||||||
|
filterForm.add(clearLink);
|
||||||
|
add(filterForm);
|
||||||
|
|
||||||
|
selectedUserId = new ParameterSingleSelectionModel<>(USER_ID_PARAM);
|
||||||
|
|
||||||
|
final UsersTable usersTable = new UsersTable(usersTableFilter,
|
||||||
|
selectedUserId);
|
||||||
|
add(usersTable);
|
||||||
|
|
||||||
|
final Text text = new Text();
|
||||||
|
text.setPrintListener((final PrintEvent e) -> {
|
||||||
|
final Text target = (Text) e.getTarget();
|
||||||
|
final PageState state = e.getPageState();
|
||||||
|
if (selectedUserId.isSelected(state)) {
|
||||||
|
target.setText(selectedUserId.getSelectedKey(state));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
add(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,16 +94,6 @@ public class UsersGroupsRolesTab extends LayoutPanel {
|
||||||
setBody(body);
|
setBody(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SimpleContainer buildUserAdmin() {
|
|
||||||
final BoxPanel panel = new BoxPanel();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
panel.add(new Label("User Admin"));
|
|
||||||
|
|
||||||
return panel;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addSection(final Label label,
|
private void addSection(final Label label,
|
||||||
final Component component,
|
final Component component,
|
||||||
final BoxPanel panel) {
|
final BoxPanel panel) {
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,17 @@
|
||||||
*/
|
*/
|
||||||
package com.arsdigita.ui.admin.usersgroupsroles;
|
package com.arsdigita.ui.admin.usersgroupsroles;
|
||||||
|
|
||||||
|
import com.arsdigita.bebop.Component;
|
||||||
|
import com.arsdigita.bebop.ControlLink;
|
||||||
import com.arsdigita.bebop.Label;
|
import com.arsdigita.bebop.Label;
|
||||||
import com.arsdigita.bebop.PageState;
|
import com.arsdigita.bebop.PageState;
|
||||||
|
import com.arsdigita.bebop.ParameterSingleSelectionModel;
|
||||||
import com.arsdigita.bebop.Table;
|
import com.arsdigita.bebop.Table;
|
||||||
|
import com.arsdigita.bebop.event.TableActionAdapter;
|
||||||
|
import com.arsdigita.bebop.event.TableActionEvent;
|
||||||
|
import com.arsdigita.bebop.event.TableActionListener;
|
||||||
|
import com.arsdigita.bebop.form.TextField;
|
||||||
|
import com.arsdigita.bebop.table.TableCellRenderer;
|
||||||
import com.arsdigita.bebop.table.TableColumn;
|
import com.arsdigita.bebop.table.TableColumn;
|
||||||
import com.arsdigita.bebop.table.TableColumnModel;
|
import com.arsdigita.bebop.table.TableColumnModel;
|
||||||
import com.arsdigita.bebop.table.TableModel;
|
import com.arsdigita.bebop.table.TableModel;
|
||||||
|
|
@ -52,9 +60,16 @@ public class UsersTable extends Table {
|
||||||
private static final int COL_PRIMARY_EMAIL = 3;
|
private static final int COL_PRIMARY_EMAIL = 3;
|
||||||
private static final int COL_BANNED = 4;
|
private static final int COL_BANNED = 4;
|
||||||
|
|
||||||
public UsersTable() {
|
private final TextField usersTableFilter;
|
||||||
|
private final ParameterSingleSelectionModel<String> selectedUserId;
|
||||||
|
|
||||||
|
public UsersTable(final TextField usersTableFilter,
|
||||||
|
final ParameterSingleSelectionModel<String> selectedUserId) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.usersTableFilter = usersTableFilter;
|
||||||
|
this.selectedUserId = selectedUserId;
|
||||||
|
|
||||||
setEmptyView(new Label(new GlobalizedMessage(
|
setEmptyView(new Label(new GlobalizedMessage(
|
||||||
"ui.admin.users.table.no_users", ADMIN_BUNDLE)));
|
"ui.admin.users.table.no_users", ADMIN_BUNDLE)));
|
||||||
|
|
||||||
|
|
@ -79,7 +94,36 @@ public class UsersTable extends Table {
|
||||||
COL_BANNED,
|
COL_BANNED,
|
||||||
new Label(new GlobalizedMessage(
|
new Label(new GlobalizedMessage(
|
||||||
"ui.admin.users.table.banned", ADMIN_BUNDLE))));
|
"ui.admin.users.table.banned", ADMIN_BUNDLE))));
|
||||||
|
|
||||||
|
columnModel.get(COL_SCREEN_NAME).setCellRenderer(new TableCellRenderer() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Component getComponent(final Table table,
|
||||||
|
final PageState state,
|
||||||
|
final Object value,
|
||||||
|
final boolean isSelected,
|
||||||
|
final Object key,
|
||||||
|
final int row,
|
||||||
|
final int column) {
|
||||||
|
return new ControlLink((String) value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
addTableActionListener(new TableActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cellSelected(final TableActionEvent event) {
|
||||||
|
final String key = (String) event.getRowKey();
|
||||||
|
|
||||||
|
selectedUserId.setSelectedKey(event.getPageState(), key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void headSelected(final TableActionEvent event) {
|
||||||
|
//Nothing
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setModelBuilder(new UsersTableModelBuilder());
|
setModelBuilder(new UsersTableModelBuilder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,7 +134,7 @@ public class UsersTable extends Table {
|
||||||
public TableModel makeModel(final Table table, final PageState state) {
|
public TableModel makeModel(final Table table, final PageState state) {
|
||||||
table.getRowSelectionModel().clearSelection(state);
|
table.getRowSelectionModel().clearSelection(state);
|
||||||
|
|
||||||
return new UsersTableModel();
|
return new UsersTableModel(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -100,12 +144,24 @@ public class UsersTable extends Table {
|
||||||
private final List<User> users;
|
private final List<User> users;
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
|
||||||
public UsersTableModel() {
|
public UsersTableModel(final PageState state) {
|
||||||
LOGGER.debug("Creating UsersTableModel...");
|
LOGGER.debug("Creating UsersTableModel...");
|
||||||
|
final String filterTerm = (String) usersTableFilter
|
||||||
|
.getValue(state);
|
||||||
|
LOGGER.debug("Value of filter is: \"{}\"", filterTerm);
|
||||||
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
final UserRepository userRepository = CdiUtil.createCdiUtil()
|
||||||
.findBean(UserRepository.class);
|
.findBean(UserRepository.class);
|
||||||
users = userRepository.findAll();
|
if (filterTerm == null || filterTerm.isEmpty()) {
|
||||||
LOGGER.debug("Found {} users in database.", users.size());
|
users = userRepository.findAll();
|
||||||
|
LOGGER.debug("Found {} users in database.", users.size());
|
||||||
|
} else {
|
||||||
|
users = userRepository.filtered(filterTerm);
|
||||||
|
LOGGER.debug("Found {} users in database which match the "
|
||||||
|
+ "filter \"{}\".",
|
||||||
|
users.size(),
|
||||||
|
filterTerm);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -82,19 +82,19 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
protected void applyDefaultEntityGraph(final TypedQuery<E> query) {
|
protected void applyDefaultEntityGraph(final TypedQuery<E> query) {
|
||||||
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
|
if (getEntityClass().isAnnotationPresent(DefaultEntityGraph.class)) {
|
||||||
LOGGER.debug("The following EntityGraphs are available for the "
|
LOGGER.debug("The following EntityGraphs are available for the "
|
||||||
+ "entity class {}:",
|
+ "entity class {}:",
|
||||||
getEntityClass().getName());
|
getEntityClass().getName());
|
||||||
getEntityManager().getEntityGraphs(getEntityClass()).stream()
|
getEntityManager().getEntityGraphs(getEntityClass()).stream()
|
||||||
.forEach(g -> LOGGER.debug("\t{}", g.getName()));
|
.forEach(g -> LOGGER.debug("\t{}", g.getName()));
|
||||||
LOGGER.debug("Entity class {} has default entity graphs:",
|
LOGGER.debug("Entity class {} has default entity graphs:",
|
||||||
getEntityClass().getName());
|
getEntityClass().getName());
|
||||||
LOGGER.debug("Applying entity graph {}",
|
LOGGER.debug("Applying entity graph {}",
|
||||||
getEntityClass().getAnnotation(
|
getEntityClass().getAnnotation(
|
||||||
DefaultEntityGraph.class).value());
|
DefaultEntityGraph.class).value());
|
||||||
query.setHint(FETCH_GRAPH_HINT_KEY,
|
query.setHint(FETCH_GRAPH_HINT_KEY,
|
||||||
entityManager.getEntityGraph(
|
entityManager.getEntityGraph(
|
||||||
getEntityClass().getAnnotation(
|
getEntityClass().getAnnotation(
|
||||||
DefaultEntityGraph.class).value()));
|
DefaultEntityGraph.class).value()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,14 +202,59 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
public List<E> findAll() {
|
public List<E> findAll() {
|
||||||
// We are using the Critiera API here because otherwise we can't
|
// We are using the Critiera API here because otherwise we can't
|
||||||
// pass the type of the entity dynmacially.
|
// pass the type of the entity dynmacially.
|
||||||
|
return executeCriteriaQuery(createCriteriaQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> findAll(final String entityGraphName) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final EntityGraph<E> entityGraph = (EntityGraph<E>) entityManager
|
||||||
|
.getEntityGraph(
|
||||||
|
entityGraphName);
|
||||||
|
|
||||||
|
return findAll(entityGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> findAll(final EntityGraph<E> entityGraph) {
|
||||||
|
// We are using the Critiera API here because otherwise we can't
|
||||||
|
// pass the type of the entity dynmacially.
|
||||||
|
return executeCriteriaQuery(createCriteriaQuery(), entityGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CriteriaQuery<E> createCriteriaQuery() {
|
||||||
final CriteriaBuilder criteriaBuilder = entityManager
|
final CriteriaBuilder criteriaBuilder = entityManager
|
||||||
.getCriteriaBuilder();
|
.getCriteriaBuilder();
|
||||||
final CriteriaQuery<E> criteriaQuery = criteriaBuilder.createQuery(
|
final CriteriaQuery<E> criteriaQuery = criteriaBuilder.createQuery(
|
||||||
getEntityClass());
|
getEntityClass());
|
||||||
final Root<E> root = criteriaQuery.from(getEntityClass());
|
final Root<E> root = criteriaQuery.from(getEntityClass());
|
||||||
criteriaQuery.select(root);
|
return criteriaQuery.select(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CriteriaBuilder getCriteriaBuilder() {
|
||||||
|
return entityManager.getCriteriaBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery) {
|
||||||
|
if (hasDefaultEntityGraph()) {
|
||||||
|
return executeCriteriaQuery(criteriaQuery, getDefaultEntityGraph());
|
||||||
|
} else {
|
||||||
|
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery,
|
||||||
|
final String graphName) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
final EntityGraph<E> entityGraph = (EntityGraph< E>) entityManager
|
||||||
|
.getEntityGraph(
|
||||||
|
graphName);
|
||||||
|
return executeCriteriaQuery(criteriaQuery, entityGraph);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<E> executeCriteriaQuery(final CriteriaQuery<E> criteriaQuery,
|
||||||
|
final EntityGraph<E> entityGraph) {
|
||||||
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
|
final TypedQuery<E> query = entityManager.createQuery(criteriaQuery);
|
||||||
|
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
|
||||||
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
@ -251,4 +296,19 @@ public abstract class AbstractEntityRepository<K, E> {
|
||||||
entityManager.remove(entity);
|
entityManager.remove(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean hasDefaultEntityGraph() {
|
||||||
|
return getEntityClass().isAnnotationPresent(DefaultEntityGraph.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getDefaultEntityGraph() {
|
||||||
|
if (hasDefaultEntityGraph()) {
|
||||||
|
return getEntityClass().getAnnotation(DefaultEntityGraph.class)
|
||||||
|
.value();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(String.format(
|
||||||
|
"Entity class \"%s\" has no DefaultEntityGraph!",
|
||||||
|
getEntityClass().getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,14 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||||
query = "SELECT u FROM User u WHERE u.name = :name"),
|
query = "SELECT u FROM User u WHERE u.name = :name"),
|
||||||
@NamedQuery(name = "User.findByEmailAddress",
|
@NamedQuery(name = "User.findByEmailAddress",
|
||||||
query = "SELECT u FROM User u WHERE "
|
query = "SELECT u FROM User u WHERE "
|
||||||
+ "u.primaryEmailAddress.address = :emailAddress")
|
+ "u.primaryEmailAddress.address = :emailAddress"),
|
||||||
|
@NamedQuery(
|
||||||
|
name = "User.filterByNameAndEmail",
|
||||||
|
query = "SELECT u FROM User u WHERE "
|
||||||
|
+ "LOWER(u.name) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
|
+ "OR LOWER(u.givenName) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
|
+ "OR LOWER(u.familyName) LIKE CONCAT(LOWER(:term), '%') "
|
||||||
|
+ "OR LOWER(u.primaryEmailAddress.address) LIKE CONCAT('%', LOWER(:term), '%')")
|
||||||
})
|
})
|
||||||
@NamedEntityGraphs({
|
@NamedEntityGraphs({
|
||||||
@NamedEntityGraph(
|
@NamedEntityGraph(
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,7 @@ package org.libreccm.security;
|
||||||
import org.libreccm.core.AbstractEntityRepository;
|
import org.libreccm.core.AbstractEntityRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
import javax.enterprise.context.ApplicationScoped;
|
|
||||||
import javax.enterprise.context.RequestScoped;
|
import javax.enterprise.context.RequestScoped;
|
||||||
import javax.persistence.EntityGraph;
|
import javax.persistence.EntityGraph;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
|
@ -126,13 +124,6 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
|
||||||
applyDefaultEntityGraph(query);
|
applyDefaultEntityGraph(query);
|
||||||
|
|
||||||
return getSingleResultOrNull(query);
|
return getSingleResultOrNull(query);
|
||||||
|
|
||||||
// final List<User> result = query.getResultList();
|
|
||||||
// if (result.isEmpty()) {
|
|
||||||
// return null;
|
|
||||||
// } else {
|
|
||||||
// return result.get(0);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public User findByEmailAddress(final String emailAddress,
|
public User findByEmailAddress(final String emailAddress,
|
||||||
|
|
@ -150,8 +141,16 @@ public class UserRepository extends AbstractEntityRepository<Long, User> {
|
||||||
"User.findByEmailAddress", User.class);
|
"User.findByEmailAddress", User.class);
|
||||||
query.setParameter("emailAddress", emailAddress);
|
query.setParameter("emailAddress", emailAddress);
|
||||||
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
|
query.setHint(FETCH_GRAPH_HINT_KEY, entityGraph);
|
||||||
|
|
||||||
return getSingleResultOrNull(query);
|
return getSingleResultOrNull(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<User> filtered(final String term) {
|
||||||
|
final TypedQuery<User> query = getEntityManager().createNamedQuery(
|
||||||
|
"User.filterByNameAndEmail", User.class);
|
||||||
|
query.setParameter("term", term);
|
||||||
|
|
||||||
|
return query.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -165,3 +165,7 @@ ui.admin.users.table.givenname=Given name
|
||||||
ui.admin.users.table.familyname=Family name
|
ui.admin.users.table.familyname=Family name
|
||||||
ui.admin.users.table.primary_email=E-Mail
|
ui.admin.users.table.primary_email=E-Mail
|
||||||
ui.admin.users.table.banned=Banned
|
ui.admin.users.table.banned=Banned
|
||||||
|
ui.admin.users.table.filter.term=Filter users
|
||||||
|
ui.admin.users.table.filter.submit=Apply
|
||||||
|
ui.admin.users.table.no_users=No users matching users found.
|
||||||
|
ui.admin.users.table.filter.clear=Clear filter
|
||||||
|
|
|
||||||
|
|
@ -165,3 +165,7 @@ ui.admin.users.table.givenname=Vorname
|
||||||
ui.admin.users.table.familyname=Familienname
|
ui.admin.users.table.familyname=Familienname
|
||||||
ui.admin.users.table.primary_email=E-Mail
|
ui.admin.users.table.primary_email=E-Mail
|
||||||
ui.admin.users.table.banned=Gesperrt
|
ui.admin.users.table.banned=Gesperrt
|
||||||
|
ui.admin.users.table.filter.term=Benutzer filtern
|
||||||
|
ui.admin.users.table.filter.submit=Anwenden
|
||||||
|
ui.admin.users.table.no_users=Keine auf den aktuellen Filter passenden Benutzer gefunden.
|
||||||
|
ui.admin.users.table.filter.clear=Filter zur\u00fccksetzen
|
||||||
|
|
|
||||||
|
|
@ -138,3 +138,7 @@ ui.admin.users.table.givenname=Given name
|
||||||
ui.admin.users.table.familyname=Family name
|
ui.admin.users.table.familyname=Family name
|
||||||
ui.admin.users.table.primary_email=E-Mail
|
ui.admin.users.table.primary_email=E-Mail
|
||||||
ui.admin.users.table.banned=Banned
|
ui.admin.users.table.banned=Banned
|
||||||
|
ui.admin.users.table.filter.term=Filter users
|
||||||
|
ui.admin.users.table.filter.submit=Apply
|
||||||
|
ui.admin.users.table.no_users=No users matching users found.
|
||||||
|
ui.admin.users.table.filter.clear=Clear filter
|
||||||
|
|
|
||||||
|
|
@ -129,3 +129,7 @@ ui.admin.users.table.givenname=Given name
|
||||||
ui.admin.users.table.familyname=Family name
|
ui.admin.users.table.familyname=Family name
|
||||||
ui.admin.users.table.primary_email=E-Mail
|
ui.admin.users.table.primary_email=E-Mail
|
||||||
ui.admin.users.table.banned=Banned
|
ui.admin.users.table.banned=Banned
|
||||||
|
ui.admin.users.table.filter.term=Filter users
|
||||||
|
ui.admin.users.table.filter.submit=Apply
|
||||||
|
ui.admin.users.table.no_users=No users matching users found.
|
||||||
|
ui.admin.users.table.filter.clear=Clear filter
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue