Commit 3e8b8e22 authored by Nico Mack's avatar Nico Mack

Introduction of Conditional interface and subsequent refactoring of

SelectableCorona
parent 7870e77f
......@@ -26,6 +26,8 @@ CENTRED_NODE=centred
CIRCLE_SIZE_NODE=circleSize
COLOUR_NODE=colour
COLOURSC_NODE=colourscheme
CONDITION_NODE=condition
CONDITION_BUILDER_NAMESPACE=lu.list.itis.dkd.tui.event.conditional.builder
CONNECTIONS_NODE=connections
CONTENT_NODE=content
CONTENT_BUILDER_NAMESPACE=lu.list.itis.dkd.tui.content.builder
......@@ -55,6 +57,7 @@ END_NODE=end
ENDING_NODE=ending
ENERGY_THRESHOLD_NODE=energyThreshold
EXCLUSIVE_NODE=exclusive
EXPRESSION_NODE=expression
FACE_COLOUR_ELEMENT=faceColour
FADE_IN_TIME_NODE=fadeInTime
FADE_OUT_TIME_NODE=fadeOutTime
......
......@@ -131,18 +131,17 @@
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.10.0</version>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.10.0</version>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.10.0</version>
<scope>runtime</scope>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
......
......@@ -168,24 +168,6 @@ public class BootstrappingUtils {
// ---------------------------------------------------------------------------
private static void logAndThrowBuildException(BuildException exception, Element element, String childName) throws BuildException {
Element causedBy = ((childName != null) && (childName.length() > 0)) ? element.getChild(childName) : element;
if (causedBy == null) {
causedBy = element;
}
if (causedBy instanceof LocatedElement) {
int lineNumber = ((LocatedElement) causedBy).getLine();
LOGGER.error("An error occured in line {}!", lineNumber, exception); //$NON-NLS-1$
} else {
LOGGER.error("Scenario contains errors!", exception); //$NON-NLS-1$
}
throw (exception);
}
// ---------------------------------------------------------------------------
private static String getContent(Element rootElement, String childName, BootstrapContext context) {
String content;
if ((childName != null) && (childName.length() > 0))
......@@ -433,6 +415,31 @@ public class BootstrappingUtils {
// ***************************************************************************
// * Class Body
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param exception
* @param element
* @param childName
* @throws BuildException
*/
// ---------------------------------------------------------------------------
public static void logAndThrowBuildException(BuildException exception, Element element, String childName) throws BuildException {
Element causedBy = ((childName != null) && (childName.length() > 0)) ? element.getChild(childName) : element;
if (causedBy == null) {
causedBy = element;
}
if (causedBy instanceof LocatedElement) {
int lineNumber = ((LocatedElement) causedBy).getLine();
LOGGER.error("An error occured in line {}!", lineNumber, exception); //$NON-NLS-1$
} else {
LOGGER.error("Scenario contains errors!", exception); //$NON-NLS-1$
}
throw (exception);
}
// ---------------------------------------------------------------------------
/**
* returns the content of a child node as a string
......
package lu.list.itis.dkd.tui.bootstrapping;
import lu.list.itis.dkd.tui.event.conditional.Condition;
import lu.list.itis.dkd.tui.event.conditional.builder.BaseConditionBuilder;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Externalization;
import org.jdom2.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @author nico.mack@list.lu
* @since 2.5
* @version 2.5.0
*/
public class ConditionBootstrapper {
private static final Logger LOGGER = LoggerFactory.getLogger(ConditionBootstrapper.class.getSimpleName());
/**
* Method used to determine the appropriate builder for a given object and then issue a build call.
*
* @param objectNode
* The node from a larger document that contains, as children, all the necessary information
* to resolve the correct builder and build the final widget.
* @return The final widget as defined by the children of the element node.
* @throws ClassNotFoundException
* Thrown when the class of the builder for the widget or those of the nested corona
* builder(s) could not be found.
* @throws SecurityException
* Thrown when the constructor cannot be retrieved due to some security constraints.
* @throws NoSuchMethodException
* Thrown when no constructor with the given parameter type is available.
* @throws InvocationTargetException
* Thrown if the invocation of any constructor through reflection throws an exception.
* @throws IllegalArgumentException
* Thrown when the provided argument is not eligible for the builder's constructor.
* @throws IllegalAccessException
* Thrown if this Constructor object is enforcing Java language access control and the
* underlying constructor is inaccessible.
* @throws InstantiationException
* Thrown if the class that declares the underlying constructor represents an abstract
* class.
*/
@SuppressWarnings("unchecked")
private static Condition<?> buildConditionFromElement(Element conditionNode, BootstrapContext context, BootstrapCallback callback) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
Condition<?> instance = null;
Element type = conditionNode.getChild(Externalization.TYPE_NODE);
Class<?> builder = Class.forName(Externalization.CONDITION_BUILDER_NAMESPACE + Externalization.NAMESPACE_SEPARATOR + type.getValue() + Externalization.BUILDER_CLASS_POSTFIX);
if ((context == null) || (context.size() == 0)) {
Constructor<BaseConditionBuilder<?>> constructor = (Constructor<BaseConditionBuilder<?>>) builder.getConstructor(new Class[] {Element.class});
instance = constructor.newInstance(new Object[] {conditionNode}).build();
} else {
Constructor<BaseConditionBuilder<?>> constructor = (Constructor<BaseConditionBuilder<?>>) builder.getConstructor(new Class[] {Element.class, BootstrapContext.class, BootstrapCallback.class});
instance = constructor.newInstance(new Object[] {conditionNode, context, callback}).build();
}
return instance;
}
/**
* builds a widget from the specified template node. A second parameter allows specifying the
* bootstrapping context, a map holding the names and the values of variables for interpolation of
* variable properties in template definition.
*
* @param conditionNode
* specifies the template node to build the widget from
* @param bootstrapContext
* specifies the names of variables and their respective values for interpolation of
* properties in template definition
* @param callback
* @return an instance of the widget as specified in the provided template node.
* @throws BuildException
* if build of widget failed
*/
public static Condition<?> buildConditionFromTemplate(Element conditionNode, BootstrapContext bootstrapContext, BootstrapCallback callback) throws BuildException {
Condition<?> instance;
try {
instance = buildConditionFromElement(conditionNode, bootstrapContext, callback);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
LOGGER.error("A condition could not be build from specified template!", e); //$NON-NLS-1$
throw new BuildException("A condition could not be build from specified template!" + e.getMessage(), e); //$NON-NLS-1$
}
return instance;
}
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional;
import lu.list.itis.dkd.tui.event.conditional.builder.BaseConditionBuilder;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 1.0.0
* @param <T>
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public abstract class Condition<T> implements Conditional<T> {
// ---------------------------------------------------------------------------
// ***************************************************************************
// *Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
*
*/
// ---------------------------------------------------------------------------
public Condition() {}
// ---------------------------------------------------------------------------
/**
* @param builder
*/
// ---------------------------------------------------------------------------
public Condition(BaseConditionBuilder<?> builder) {
// Nothing to do here.
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
@Override
public void setCondition(Condition<T> condition) {
// Dummy implementation.
}
// ---------------------------------------------------------------------------
@Override
public Condition<T> getCondition() {
return this;
}
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 1.0.0
* @param <T>
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ConditionEvent<T> {
private Conditional<T> source;
private T match;
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param source
* @param match
*/
// ---------------------------------------------------------------------------
public ConditionEvent(Conditional<T> source, T match) {
this.source = source;
this.match = match;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* Simple getter method for source.
*
* @return The value of source.
*/
// ---------------------------------------------------------------------------
public Conditional<T> getSource() {
return source;
}
// ---------------------------------------------------------------------------
/**
* Simple getter method for match.
*
* @return The value of match.
*/
// ---------------------------------------------------------------------------
public T getMatch() {
return match;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional;
import java.util.ArrayList;
import java.util.List;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 1.0.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class ConditionEventSource {
private List<ConditionListener> listeners;
// ***************************************************************************
// * Constants *
// ***************************************************************************
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
*
*/
// ---------------------------------------------------------------------------
public ConditionEventSource() {
listeners = new ArrayList<>();
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitives *
// ***************************************************************************
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param listener
*/
// ---------------------------------------------------------------------------
public void addConditionListener(ConditionListener listener) {
listeners.add(listener);
}
// ---------------------------------------------------------------------------
/**
* @param listener
*/
// ---------------------------------------------------------------------------
public void removeConditionListener(ConditionListener listener) {
listeners.remove(listener);
}
// ---------------------------------------------------------------------------
/**
* @param <T>
* @param event
*/
// ---------------------------------------------------------------------------
public <T> void notifyConditionListener(ConditionEvent<T> event) {
for (ConditionListener listener : listeners) {
listener.conditionSatisfied(event);
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
\ No newline at end of file
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 1.0.0
*/
public interface ConditionListener {
/**
* @param event
*/
public void conditionSatisfied(ConditionEvent event);
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional;
/**
* @author Nico Mack [nico.mack@list.lu]
* @since 2.5
* @version 1.0.0
* @param <T>
*/
public interface Conditional<T> {
/**
* @param candidate
* @return
*/
public boolean satisfiedBy(T candidate);
/**
* @param condition
*/
public void setCondition(Condition<T> condition);
/**
* @return
*/
public Condition<T> getCondition();
}
/**
* Copyright Luxembourg Institute of Science and Technology, 2018. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP 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, version 3 of the
* License.
*
* TULIP 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 TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.event.conditional.builder;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapCallback;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapContext;
import lu.list.itis.dkd.tui.event.conditional.Condition;
import lu.list.itis.dkd.tui.exception.BuildException;
import org.jdom2.Element;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
* @param <B>
*/
public abstract class BaseConditionBuilder<B extends BaseConditionBuilder<B>> {
public BaseConditionBuilder(Element rootElement) throws BuildException {};
public BaseConditionBuilder(Element rootElement, BootstrapContext context, BootstrapCallback callback) throws BuildException {};
/**
* @return
*/
public abstract Condition build();
}
......@@ -61,6 +61,8 @@ public class Externalization extends NLS {
public static String CIRCLE_SIZE_NODE;
public static String COLOUR_NODE;
public static String COLOURSC_NODE;
public static String CONDITION_NODE;
public static String CONDITION_BUILDER_NAMESPACE;
public static String CONNECTIONS_NODE;
public static String CONTENT_NODE;
public static String CONTENT_BUILDER_NAMESPACE;
......@@ -90,6 +92,7 @@ public class Externalization extends NLS {
public static String ENDING_NODE;
public static String ENERGY_THRESHOLD_NODE;
public static String EXCLUSIVE_NODE;
public static String EXPRESSION_NODE;
public static String FACE_COLOUR_ELEMENT;
public static String FADE_IN_TIME_NODE;
public static String FADE_OUT_TIME_NODE;
......
......@@ -90,7 +90,6 @@ public class Sector extends SelectableCorona {
centered = builder.centered;
radialLayout = builder.radialLayout;
this.buildSectorFromProperties();
touchManager = new TouchManager(isLatching);
......@@ -143,6 +142,7 @@ public class Sector extends SelectableCorona {
// ---------------------------------------------------------------------------
private void buildSectorFromProperties() {
size = 2 * outerRadius;
double angle = this.getAngle();
arcSpan -= gap;
......@@ -320,6 +320,7 @@ public class Sector extends SelectableCorona {
return new Sector(this);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
......
......@@ -20,6 +20,8 @@ import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.event.Selectable;
import lu.list.itis.dkd.tui.event.SelectionEvent;
import lu.list.itis.dkd.tui.event.SelectionListener;
import lu.list.itis.dkd.tui.event.conditional.Condition;
import lu.list.itis.dkd.tui.event.conditional.Conditional;
import lu.list.itis.dkd.tui.widget.corona.builder.BaseSelectableCoronaBuilder;
import java.util.ArrayList;
......@@ -34,10 +36,11 @@ import java.util.List;
// * Class Definition and Members *
// ***************************************************************************
public abstract class SelectableCorona extends FadingCorona implements Selectable {
public abstract class SelectableCorona extends FadingCorona implements Selectable, Conditional<Integer> {
protected boolean isSelected;
protected int index;
protected String group;
protected Condition<Integer> condition;
protected List<SelectionListener> listeners;
// ---------------------------------------------------------------------------
......@@ -55,6 +58,8 @@ public abstract class SelectableCorona extends FadingCorona implements Selectabl
index = builder.index;
isSelected = builder.selected;
group = builder.group;
condition = builder.condition;
listeners = new ArrayList<>();
}
......@@ -72,6 +77,8 @@ public abstract class SelectableCorona extends FadingCorona implements Selectabl
index = original.index;
isSelected = original.isSelected;
group = original.group;
condition = original.condition;
listeners = new ArrayList<>();
}
......@@ -178,6 +185,34 @@ public abstract class SelectableCorona extends FadingCorona implements Selectabl
return this.group;
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public boolean satisfiedBy(Integer candidate) {
boolean satisfied = (this.condition != null) ? this.condition.satisfiedBy(candidate) : false;
this.setSelected(satisfied);
return satisfied;
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public void setCondition(Condition<Integer> condition) {
this.condition = condition;
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public Condition<Integer> getCondition() {
return this.condition;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class
......
......@@ -20,6 +20,8 @@ import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapCallback;
import lu.list.itis.dkd.tui.bootstrapping.BootstrapContext;
import lu.list.itis.dkd.tui.bootstrapping.BootstrappingUtils;
import lu.list.itis.dkd.tui.bootstrapping.ConditionBootstrapper;
import lu.list.itis.dkd.tui.event.conditional.Condition;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Externalization;
import lu.list.itis.dkd.tui.utility.Point;
......@@ -40,6 +42,9 @@ public abstract class BaseSelectableCoronaBuilder<B extends BaseSelectableCorona
public int index;
public boolean selected;
public String group;
public Condition<Integer> condition;
private static final String MULTIPLE_CONDITIONS_TEMPLATE = "Multiple conditions detected in SelectableCorona!"; //$NON-NLS-1$