SEBSERV-44 SEBSERV-45 finished config tool and some bug fixes
This commit is contained in:
		
							parent
							
								
									74306412e1
								
							
						
					
					
						commit
						84ac76efd7
					
				
					 45 changed files with 1253 additions and 522 deletions
				
			
		| 
						 | 
					@ -48,7 +48,7 @@ public enum AttributeType {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    INLINE_TABLE(COMPOSITE_LIST),
 | 
					    INLINE_TABLE(COMPOSITE_LIST),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ;
 | 
					    COMPOSITE_TABLE(COMPOSITE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public final AttributeValueType attributeValueType;
 | 
					    public final AttributeValueType attributeValueType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,8 +20,8 @@ public enum AttributeValueType {
 | 
				
			||||||
    BASE64_BINARY,
 | 
					    BASE64_BINARY,
 | 
				
			||||||
    /** A list of single values of the same type */
 | 
					    /** A list of single values of the same type */
 | 
				
			||||||
    LIST,
 | 
					    LIST,
 | 
				
			||||||
    /** A composite of different typed values like a Map or Dictionary */
 | 
					    /** A composite of different typed values like a map or dictionary */
 | 
				
			||||||
    COMPOSITE,
 | 
					    COMPOSITE,
 | 
				
			||||||
    /** A list of composites of the same type like a Table */
 | 
					    /** A list of composites (list of dictionary) of the same type like a Table */
 | 
				
			||||||
    COMPOSITE_LIST
 | 
					    COMPOSITE_LIST
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,13 +8,23 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package ch.ethz.seb.sebserver.gbl.model.sebconfig;
 | 
					package ch.ethz.seb.sebserver.gbl.model.sebconfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Arrays;
 | 
				
			||||||
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import javax.validation.constraints.NotNull;
 | 
					import javax.validation.constraints.NotNull;
 | 
				
			||||||
import javax.validation.constraints.Size;
 | 
					import javax.validation.constraints.Size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonCreator;
 | 
					import com.fasterxml.jackson.annotation.JsonCreator;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 | 
					import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 | 
				
			||||||
import com.fasterxml.jackson.annotation.JsonProperty;
 | 
					import com.fasterxml.jackson.annotation.JsonProperty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.Constants;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
 | 
					import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
				
			||||||
| 
						 | 
					@ -24,8 +34,25 @@ import ch.ethz.seb.sebserver.gbl.model.Entity;
 | 
				
			||||||
@JsonIgnoreProperties(ignoreUnknown = true)
 | 
					@JsonIgnoreProperties(ignoreUnknown = true)
 | 
				
			||||||
public final class ConfigurationAttribute implements Entity {
 | 
					public final class ConfigurationAttribute implements Entity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final Logger log = LoggerFactory.getLogger(ConfigurationAttribute.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** This configuration attribute dependency key can be used to set a specific localized text key prefix for
 | 
				
			||||||
 | 
					     * resources. This is usually convenient if two different attributes use the same resources and to avoid
 | 
				
			||||||
 | 
					     * to multiply the resources for each attribute with the attribute name prefix, we can set a specific
 | 
				
			||||||
 | 
					     * resourceLocTextKey prefix to use. */
 | 
				
			||||||
    public static final String DEPENDENCY_RESOURCE_LOC_TEXT_KEY = "resourceLocTextKey";
 | 
					    public static final String DEPENDENCY_RESOURCE_LOC_TEXT_KEY = "resourceLocTextKey";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** This configuration attribute dependency key indicates the group identifier for grouped COMOSITE_TYPE types */
 | 
				
			||||||
 | 
					    public static final String DEPENDENCY_GROUP_ID = "groupId";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** This configuration attribute dependency key indicates if a default value should be created even if the
 | 
				
			||||||
 | 
					     * attribute is a child attribute and normally no default value is generated on creation. */
 | 
				
			||||||
 | 
					    public static final String DEPENDENCY_CREATE_DEFAULT_VALUE = "createDefaultValue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** his configuration attribute dependency key indicates if the input field should be shown in the directly
 | 
				
			||||||
 | 
					     * in the View even if the attribute is a child attribute and is usually shown in a table or composite. */
 | 
				
			||||||
 | 
					    public static final String DEPENDENCY_SHOW_IN_VIEW = "showInView";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String FILTER_ATTR_PARENT_ID = "parentId";
 | 
					    public static final String FILTER_ATTR_PARENT_ID = "parentId";
 | 
				
			||||||
    public static final String FILTER_ATTR_TYPE = "type";
 | 
					    public static final String FILTER_ATTR_TYPE = "type";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -156,4 +183,55 @@ public final class ConfigurationAttribute implements Entity {
 | 
				
			||||||
        return builder.toString();
 | 
					        return builder.toString();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static boolean hasDependency(
 | 
				
			||||||
 | 
					            final String dependencyName,
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (StringUtils.isBlank(attribute.dependencies)) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return attribute.dependencies.contains(dependencyName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String getDependencyValue(
 | 
				
			||||||
 | 
					            final String dependencyName,
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getDependencyValue(dependencyName, attribute.dependencies);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static String getDependencyValue(
 | 
				
			||||||
 | 
					            final String dependencyName,
 | 
				
			||||||
 | 
					            final String dependnciesString) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (StringUtils.isBlank(dependnciesString)) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getAttributeDependencyMap(dependnciesString).get(dependencyName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Map<String, String> getAttributeDependencyMap(final ConfigurationAttribute attribute) {
 | 
				
			||||||
 | 
					        if (StringUtils.isBlank(attribute.dependencies)) {
 | 
				
			||||||
 | 
					            return Collections.emptyMap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getAttributeDependencyMap(attribute.dependencies);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Map<String, String> getAttributeDependencyMap(final String dependnciesString) {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            return Arrays.asList(StringUtils.split(dependnciesString, Constants.LIST_SEPARATOR))
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .map(s -> StringUtils.split(s, Constants.FORM_URL_ENCODED_NAME_VALUE_SEPARATOR))
 | 
				
			||||||
 | 
					                    .collect(Collectors.toMap(pair -> pair[0], pair -> pair[1]));
 | 
				
			||||||
 | 
					        } catch (final Exception e) {
 | 
				
			||||||
 | 
					            log.error("Unexpected error while trying to parse dependency map of: {}",
 | 
				
			||||||
 | 
					                    dependnciesString,
 | 
				
			||||||
 | 
					                    e);
 | 
				
			||||||
 | 
					            return Collections.emptyMap();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,7 @@ public final class ConfigurationNode implements GrantEntity {
 | 
				
			||||||
    @JsonProperty(CONFIGURATION_NODE.ATTR_NAME)
 | 
					    @JsonProperty(CONFIGURATION_NODE.ATTR_NAME)
 | 
				
			||||||
    public final String name;
 | 
					    public final String name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Size(max = 4000, message = "configurationNode:description:size:{min}:{max}:${validatedValue}")
 | 
				
			||||||
    @JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION)
 | 
					    @JsonProperty(CONFIGURATION_NODE.ATTR_DESCRIPTION)
 | 
				
			||||||
    public final String description;
 | 
					    public final String description;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,6 @@ import com.fasterxml.jackson.core.JsonProcessingException;
 | 
				
			||||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
					import com.fasterxml.jackson.databind.ObjectMapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
					import ch.ethz.seb.sebserver.gbl.Constants;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public final class Utils {
 | 
					public final class Utils {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -294,22 +293,4 @@ public final class Utils {
 | 
				
			||||||
        return toCharArray(CharBuffer.wrap(chars));
 | 
					        return toCharArray(CharBuffer.wrap(chars));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static Map<String, String> getAttributeDependencyMap(final ConfigurationAttribute attribute) {
 | 
					 | 
				
			||||||
        if (StringUtils.isBlank(attribute.dependencies)) {
 | 
					 | 
				
			||||||
            return Collections.emptyMap();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            return Arrays.asList(StringUtils.split(attribute.dependencies, Constants.LIST_SEPARATOR))
 | 
					 | 
				
			||||||
                    .stream()
 | 
					 | 
				
			||||||
                    .map(s -> StringUtils.split(s, Constants.EMBEDDED_LIST_SEPARATOR))
 | 
					 | 
				
			||||||
                    .collect(Collectors.toMap(pair -> pair[0], pair -> pair[1]));
 | 
					 | 
				
			||||||
        } catch (final Exception e) {
 | 
					 | 
				
			||||||
            log.error("Unexpected error while trying to parse dependency map of ConfigurationAttribute: {}",
 | 
					 | 
				
			||||||
                    attribute,
 | 
					 | 
				
			||||||
                    e);
 | 
					 | 
				
			||||||
            return Collections.emptyMap();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,11 +65,14 @@ public final class SelectionFieldBuilder extends FieldBuilder<String> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void buildInput(final FormBuilder builder, final Label lab) {
 | 
					    private void buildInput(final FormBuilder builder, final Label lab) {
 | 
				
			||||||
 | 
					        final String actionKey = (this.label != null) ? this.label.name + ".action" : null;
 | 
				
			||||||
        final Selection selection = builder.widgetFactory.selectionLocalized(
 | 
					        final Selection selection = builder.widgetFactory.selectionLocalized(
 | 
				
			||||||
                this.type,
 | 
					                this.type,
 | 
				
			||||||
                builder.formParent,
 | 
					                builder.formParent,
 | 
				
			||||||
                this.itemsSupplier);
 | 
					                this.itemsSupplier,
 | 
				
			||||||
 | 
					                null,
 | 
				
			||||||
 | 
					                null,
 | 
				
			||||||
 | 
					                actionKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
 | 
					        final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
 | 
				
			||||||
        ((Control) selection).setLayoutData(gridData);
 | 
					        ((Control) selection).setLayoutData(gridData);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,9 @@ public final class TextFieldBuilder extends FieldBuilder<String> {
 | 
				
			||||||
                            : builder.widgetFactory.textInput(builder.formParent, this.isPassword);
 | 
					                            : builder.widgetFactory.textInput(builder.formParent, this.isPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
 | 
					            final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, this.spanInput, 1);
 | 
				
			||||||
 | 
					            if (this.isArea) {
 | 
				
			||||||
 | 
					                gridData.heightHint = 50;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            textInput.setLayoutData(gridData);
 | 
					            textInput.setLayoutData(gridData);
 | 
				
			||||||
            if (this.value != null) {
 | 
					            if (this.value != null) {
 | 
				
			||||||
                textInput.setText(this.value);
 | 
					                textInput.setText(this.value);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package ch.ethz.seb.sebserver.gui.service.examconfig;
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.BooleanUtils;
 | 
				
			||||||
import org.eclipse.rap.rwt.RWT;
 | 
					import org.eclipse.rap.rwt.RWT;
 | 
				
			||||||
import org.eclipse.swt.SWT;
 | 
					import org.eclipse.swt.SWT;
 | 
				
			||||||
import org.eclipse.swt.layout.GridData;
 | 
					import org.eclipse.swt.layout.GridData;
 | 
				
			||||||
| 
						 | 
					@ -71,12 +72,18 @@ public interface InputFieldBuilder {
 | 
				
			||||||
        final GridData gridData = new GridData(
 | 
					        final GridData gridData = new GridData(
 | 
				
			||||||
                SWT.FILL, SWT.FILL,
 | 
					                SWT.FILL, SWT.FILL,
 | 
				
			||||||
                true, false,
 | 
					                true, false,
 | 
				
			||||||
                (orientation != null && attribute.parentId == null) ? orientation.width() : 1,
 | 
					                (orientation != null && isOnView(attribute)) ? orientation.width() : 1,
 | 
				
			||||||
                (orientation != null && attribute.parentId == null) ? orientation.height() : 1);
 | 
					                (orientation != null && isOnView(attribute)) ? orientation.height() : 1);
 | 
				
			||||||
        comp.setLayoutData(gridData);
 | 
					        comp.setLayoutData(gridData);
 | 
				
			||||||
        return comp;
 | 
					        return comp;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static boolean isOnView(final ConfigurationAttribute attribute) {
 | 
				
			||||||
 | 
					        return attribute.parentId == null || BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                ConfigurationAttribute.DEPENDENCY_SHOW_IN_VIEW,
 | 
				
			||||||
 | 
					                attribute));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static Label createErrorLabel(final Composite innerGrid) {
 | 
					    static Label createErrorLabel(final Composite innerGrid) {
 | 
				
			||||||
        final Label errorLabel = new Label(innerGrid, SWT.NONE);
 | 
					        final Label errorLabel = new Label(innerGrid, SWT.NONE);
 | 
				
			||||||
        errorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 | 
					        errorLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@ public interface ValueChangeRule {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void applyRule(
 | 
					    void applyRule(
 | 
				
			||||||
            ViewContext context,
 | 
					            ViewContext context,
 | 
				
			||||||
            ConfigurationAttribute attribut,
 | 
					            ConfigurationAttribute attribute,
 | 
				
			||||||
            ConfigurationValue value);
 | 
					            ConfigurationValue value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,335 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.BooleanUtils;
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
 | 
					import org.eclipse.swt.SWT;
 | 
				
			||||||
 | 
					import org.eclipse.swt.layout.GridData;
 | 
				
			||||||
 | 
					import org.eclipse.swt.layout.GridLayout;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Label;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Table;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.TableColumn;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.TableItem;
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.Constants;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public abstract class AbstractTableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final Logger log = LoggerFactory.getLogger(AbstractTableFieldBuilder.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected final RestService restService;
 | 
				
			||||||
 | 
					    protected final WidgetFactory widgetFactory;
 | 
				
			||||||
 | 
					    protected InputFieldBuilderSupplier inputFieldBuilderSupplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected AbstractTableFieldBuilder(
 | 
				
			||||||
 | 
					            final RestService restService,
 | 
				
			||||||
 | 
					            final WidgetFactory widgetFactory) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.restService = restService;
 | 
				
			||||||
 | 
					        this.widgetFactory = widgetFactory;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void init(final InputFieldBuilderSupplier inputFieldBuilderSupplier) {
 | 
				
			||||||
 | 
					        this.inputFieldBuilderSupplier = inputFieldBuilderSupplier;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected Table createTable(final Composite parent, final TableContext tableContext) {
 | 
				
			||||||
 | 
					        final Table table = new Table(parent, SWT.NONE | SWT.V_SCROLL);
 | 
				
			||||||
 | 
					        table.setLayout(new GridLayout());
 | 
				
			||||||
 | 
					        final GridData gridData = new GridData(
 | 
				
			||||||
 | 
					                SWT.FILL, SWT.FILL,
 | 
				
			||||||
 | 
					                true, false,
 | 
				
			||||||
 | 
					                (tableContext.orientation != null) ? tableContext.orientation.width() : 1,
 | 
				
			||||||
 | 
					                (tableContext.orientation != null) ? tableContext.orientation.height() : 1);
 | 
				
			||||||
 | 
					        gridData.heightHint = tableContext.orientation.height * 20 + 40;
 | 
				
			||||||
 | 
					        table.setLayoutData(gridData);
 | 
				
			||||||
 | 
					        table.setHeaderVisible(true);
 | 
				
			||||||
 | 
					        table.addListener(SWT.Resize, event -> adaptColumnWidth(table, tableContext));
 | 
				
			||||||
 | 
					        return table;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected TableContext createTableContext(final ConfigurationAttribute attribute, final ViewContext viewContext) {
 | 
				
			||||||
 | 
					        final TableContext tableContext = new TableContext(
 | 
				
			||||||
 | 
					                this.inputFieldBuilderSupplier,
 | 
				
			||||||
 | 
					                this.widgetFactory,
 | 
				
			||||||
 | 
					                this.restService,
 | 
				
			||||||
 | 
					                attribute,
 | 
				
			||||||
 | 
					                viewContext);
 | 
				
			||||||
 | 
					        return tableContext;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected void setSelectionListener(final Table table, final AbstractTableInputField tableField) {
 | 
				
			||||||
 | 
					        table.addListener(SWT.MouseDoubleClick, event -> {
 | 
				
			||||||
 | 
					            final int selectionIndex = table.getSelectionIndex();
 | 
				
			||||||
 | 
					            if (selectionIndex >= 0) {
 | 
				
			||||||
 | 
					                tableField.openForm(selectionIndex);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected void adaptColumnWidth(
 | 
				
			||||||
 | 
					            final Table table,
 | 
				
			||||||
 | 
					            final TableContext tableContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            final int currentTableWidth = table.getClientArea().width - 50;
 | 
				
			||||||
 | 
					            final TableColumn[] columns = table.getColumns();
 | 
				
			||||||
 | 
					            final List<Orientation> orientations = tableContext
 | 
				
			||||||
 | 
					                    .getColumnAttributes()
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .map(attr -> tableContext.getOrientation(attr.id))
 | 
				
			||||||
 | 
					                    .collect(Collectors.toList());
 | 
				
			||||||
 | 
					            final Integer div = orientations
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .map(o -> o.width)
 | 
				
			||||||
 | 
					                    .reduce(0, (acc, val) -> acc + val);
 | 
				
			||||||
 | 
					            final int widthUnit = currentTableWidth / div;
 | 
				
			||||||
 | 
					            for (int i = 0; i < columns.length - 2; i++) {
 | 
				
			||||||
 | 
					                columns[i].setWidth(widthUnit * orientations.get(i).width);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (final Exception e) {
 | 
				
			||||||
 | 
					            log.warn("Failed to adaptColumnWidth: ", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected static void setValueToCell(
 | 
				
			||||||
 | 
					            final TableContext tableContext,
 | 
				
			||||||
 | 
					            final TableItem item,
 | 
				
			||||||
 | 
					            final int cellIndex,
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					            final TableValue tableValue) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (attribute.type) {
 | 
				
			||||||
 | 
					            case CHECKBOX: {
 | 
				
			||||||
 | 
					                item.setImage(
 | 
				
			||||||
 | 
					                        cellIndex,
 | 
				
			||||||
 | 
					                        (BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null))
 | 
				
			||||||
 | 
					                                ? ImageIcon.YES.getImage(item.getDisplay())
 | 
				
			||||||
 | 
					                                : ImageIcon.NO.getImage(item.getDisplay()));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case SINGLE_SELECTION: {
 | 
				
			||||||
 | 
					                final String key = ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX +
 | 
				
			||||||
 | 
					                        attribute.getName() + "." +
 | 
				
			||||||
 | 
					                        tableValue.value;
 | 
				
			||||||
 | 
					                item.setText(
 | 
				
			||||||
 | 
					                        cellIndex,
 | 
				
			||||||
 | 
					                        tableContext.i18nSupport().getText(key, getValue(attribute, tableValue)));
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            default: {
 | 
				
			||||||
 | 
					                item.setText(cellIndex, getValue(attribute, tableValue));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static String getValue(
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					            final TableValue tableValue) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (tableValue == null) {
 | 
				
			||||||
 | 
					            if (StringUtils.isBlank(attribute.defaultValue)) {
 | 
				
			||||||
 | 
					                return Constants.EMPTY_NOTE;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return attribute.defaultValue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            if (StringUtils.isBlank(tableValue.value)) {
 | 
				
			||||||
 | 
					                return Constants.EMPTY_NOTE;
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                return tableValue.value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static abstract class AbstractTableInputField extends AbstractInputField<Table> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected final TableContext tableContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected AbstractTableInputField(
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					                final Orientation orientation,
 | 
				
			||||||
 | 
					                final Table control,
 | 
				
			||||||
 | 
					                final Label errorLabel,
 | 
				
			||||||
 | 
					                final TableContext tableContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            super(attribute, orientation, control, errorLabel);
 | 
				
			||||||
 | 
					            this.tableContext = tableContext;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public ConfigurationValue initValue(final Collection<ConfigurationValue> values) {
 | 
				
			||||||
 | 
					            clearTable();
 | 
				
			||||||
 | 
					            // get all child values as TableValues
 | 
				
			||||||
 | 
					            final List<TableValue> tableValues = getChildValues(
 | 
				
			||||||
 | 
					                    this.tableContext,
 | 
				
			||||||
 | 
					                    this.attribute,
 | 
				
			||||||
 | 
					                    values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            initValue(tableValues);
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abstract void initValue(final List<TableValue> tableValues);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abstract void openForm(final int selectionIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        abstract void applyTableRowValues(final int index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected List<TableValue> getChildValues(
 | 
				
			||||||
 | 
					                final TableContext tableContext,
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					                final Collection<ConfigurationValue> values) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return values.stream()
 | 
				
			||||||
 | 
					                    .filter(v -> isChildValue(tableContext, attribute, v))
 | 
				
			||||||
 | 
					                    .map(TableValue::of)
 | 
				
			||||||
 | 
					                    .collect(Collectors.toList());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected boolean isChildValue(
 | 
				
			||||||
 | 
					                final TableContext tableContext,
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					                final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!tableContext.getViewContext().attributeMapping.attributeIdMapping
 | 
				
			||||||
 | 
					                    .containsKey(value.attributeId)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ConfigurationAttribute attr = tableContext.getAttribute(value.attributeId);
 | 
				
			||||||
 | 
					            while (attr.parentId != null) {
 | 
				
			||||||
 | 
					                if (attribute.id.equals(attr.parentId)) {
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                attr = tableContext.getAttribute(attr.parentId);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected Map<Integer, Map<Long, TableValue>> createRowIndexMap(final List<TableValue> tableValues) {
 | 
				
			||||||
 | 
					            final Map<Integer, Map<Long, TableValue>> indexMapping = new HashMap<>();
 | 
				
			||||||
 | 
					            for (final TableValue tableValue : tableValues) {
 | 
				
			||||||
 | 
					                final Map<Long, TableValue> rowValues = indexMapping.computeIfAbsent(
 | 
				
			||||||
 | 
					                        tableValue.listIndex,
 | 
				
			||||||
 | 
					                        key -> new HashMap<>());
 | 
				
			||||||
 | 
					                rowValues.put(tableValue.attributeId, tableValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return indexMapping;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected void valuesFromIndexMap(
 | 
				
			||||||
 | 
					                final List<Map<Long, TableValue>> values,
 | 
				
			||||||
 | 
					                final Map<Integer, Map<Long, TableValue>> indexMapping) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            values.clear();
 | 
				
			||||||
 | 
					            final List<Integer> rows = new ArrayList<>(indexMapping.keySet());
 | 
				
			||||||
 | 
					            rows.sort((i1, i2) -> i1.compareTo(i2));
 | 
				
			||||||
 | 
					            rows
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .forEach(i -> {
 | 
				
			||||||
 | 
					                        final Map<Long, TableValue> rowValues = indexMapping.get(i);
 | 
				
			||||||
 | 
					                        values.add(rowValues);
 | 
				
			||||||
 | 
					                        // addTableRow(rowValues);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					//            for (int i = 0; i < rows.size(); i++) {
 | 
				
			||||||
 | 
					//                final Map<Long, TableValue> rowValues = indexMapping.get(i);
 | 
				
			||||||
 | 
					//                values.add(rowValues);
 | 
				
			||||||
 | 
					//                addTableRow(rowValues);
 | 
				
			||||||
 | 
					//            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected void applyFormValues(
 | 
				
			||||||
 | 
					                final List<Map<Long, TableValue>> values,
 | 
				
			||||||
 | 
					                final Map<Long, TableValue> rowValues,
 | 
				
			||||||
 | 
					                final int index) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (values != null && !values.isEmpty()) {
 | 
				
			||||||
 | 
					                values.remove(index);
 | 
				
			||||||
 | 
					                values.add(index, rowValues);
 | 
				
			||||||
 | 
					                applyTableRowValues(index);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // send values to web-service
 | 
				
			||||||
 | 
					            this.tableContext.getValueChangeListener()
 | 
				
			||||||
 | 
					                    .tableChanged(extractTableValue(values));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected ConfigurationTableValues extractTableValue(final List<Map<Long, TableValue>> values) {
 | 
				
			||||||
 | 
					            final List<TableValue> collect = values
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .flatMap(map -> map.values().stream())
 | 
				
			||||||
 | 
					                    .collect(Collectors.toList());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return new ConfigurationTableValues(
 | 
				
			||||||
 | 
					                    this.tableContext.getInstitutionId(),
 | 
				
			||||||
 | 
					                    this.tableContext.getConfigurationId(),
 | 
				
			||||||
 | 
					                    this.attribute.id,
 | 
				
			||||||
 | 
					                    collect);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void setDefaultValue() {
 | 
				
			||||||
 | 
					            // NOTE this just empty the list for now
 | 
				
			||||||
 | 
					            // TODO do we need default values for lists?
 | 
				
			||||||
 | 
					            clearTable();
 | 
				
			||||||
 | 
					            final List<TableValue> values = new ArrayList<>();
 | 
				
			||||||
 | 
					            this.tableContext.getValueChangeListener().tableChanged(
 | 
				
			||||||
 | 
					                    new ConfigurationTableValues(
 | 
				
			||||||
 | 
					                            this.tableContext.getInstitutionId(),
 | 
				
			||||||
 | 
					                            this.tableContext.getConfigurationId(),
 | 
				
			||||||
 | 
					                            this.attribute.id,
 | 
				
			||||||
 | 
					                            values));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        void clearTable() {
 | 
				
			||||||
 | 
					            this.control.setSelection(-1);
 | 
				
			||||||
 | 
					            if (this.control.getItemCount() > 0) {
 | 
				
			||||||
 | 
					                for (final TableItem item : this.control.getItems()) {
 | 
				
			||||||
 | 
					                    item.dispose();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected void setValueToControl(final String value) {
 | 
				
			||||||
 | 
					            throw new UnsupportedOperationException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public String getValue() {
 | 
				
			||||||
 | 
					            throw new UnsupportedOperationException();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,259 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Arrays;
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
 | 
					import org.eclipse.swt.SWT;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Table;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.TableColumn;
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.TableItem;
 | 
				
			||||||
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.Constants;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Lazy
 | 
				
			||||||
 | 
					@Component
 | 
				
			||||||
 | 
					@GuiProfile
 | 
				
			||||||
 | 
					public class CompositeTableFieldBuilder extends AbstractTableFieldBuilder {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final Logger log = LoggerFactory.getLogger(CompositeTableFieldBuilder.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final String TABLE_ENTRY_NAME = "TABLE_ENTRY";
 | 
				
			||||||
 | 
					    private static final String TABLE_COLUMN_NAME_KEY = "TABLE_COLUMN_NAME";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected CompositeTableFieldBuilder(
 | 
				
			||||||
 | 
					            final RestService restService,
 | 
				
			||||||
 | 
					            final WidgetFactory widgetFactory) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        super(restService, widgetFactory);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean builderFor(
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					            final Orientation orientation) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (attribute == null) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return AttributeType.COMPOSITE_TABLE == attribute.type;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public InputField createInputField(
 | 
				
			||||||
 | 
					            final Composite parent,
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					            final ViewContext viewContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final I18nSupport i18nSupport = viewContext.getI18nSupport();
 | 
				
			||||||
 | 
					        final TableContext tableContext = createTableContext(attribute, viewContext);
 | 
				
			||||||
 | 
					        final Table table = createTable(parent, tableContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final String resources = attribute.getResources();
 | 
				
			||||||
 | 
					        final String[] columnsAndRows = StringUtils.split(
 | 
				
			||||||
 | 
					                resources,
 | 
				
			||||||
 | 
					                Constants.EMBEDDED_LIST_SEPARATOR);
 | 
				
			||||||
 | 
					        final String[] columns = (columnsAndRows.length == 2)
 | 
				
			||||||
 | 
					                ? StringUtils.split(columnsAndRows[0], Constants.LIST_SEPARATOR)
 | 
				
			||||||
 | 
					                : new String[] { TABLE_ENTRY_NAME };
 | 
				
			||||||
 | 
					        final String[] rows = (columnsAndRows.length == 2)
 | 
				
			||||||
 | 
					                ? StringUtils.split(columnsAndRows[1], Constants.LIST_SEPARATOR)
 | 
				
			||||||
 | 
					                : StringUtils.split(columnsAndRows[0], Constants.LIST_SEPARATOR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final String attributeNameKey = ExamConfigurationService.attributeNameKey(attribute);
 | 
				
			||||||
 | 
					        for (int i = 0; i < columns.length; i++) {
 | 
				
			||||||
 | 
					            final TableColumn column = this.widgetFactory.tableColumnLocalized(
 | 
				
			||||||
 | 
					                    table,
 | 
				
			||||||
 | 
					                    new LocTextKey(attributeNameKey + "." + columns[i]),
 | 
				
			||||||
 | 
					                    new LocTextKey(attributeNameKey + "." + columns[i] + ".tootlip"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            column.setData(TABLE_COLUMN_NAME_KEY, columns[i]);
 | 
				
			||||||
 | 
					            column.setWidth(100);
 | 
				
			||||||
 | 
					            column.setResizable(false);
 | 
				
			||||||
 | 
					            column.setMoveable(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (int i = 0; i < rows.length; i++) {
 | 
				
			||||||
 | 
					            final TableItem item = new TableItem(table, SWT.NONE);
 | 
				
			||||||
 | 
					            for (int j = 0; j < columns.length; j++) {
 | 
				
			||||||
 | 
					                if (TABLE_ENTRY_NAME.equals(columns[j])) {
 | 
				
			||||||
 | 
					                    item.setText(j, i18nSupport.getText(
 | 
				
			||||||
 | 
					                            ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + rows[i],
 | 
				
			||||||
 | 
					                            rows[i]));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final CompositeTableInputField tableField = new CompositeTableInputField(
 | 
				
			||||||
 | 
					                tableContext,
 | 
				
			||||||
 | 
					                table,
 | 
				
			||||||
 | 
					                Arrays.asList(columns),
 | 
				
			||||||
 | 
					                Arrays.asList(rows));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setSelectionListener(table, tableField);
 | 
				
			||||||
 | 
					        return tableField;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void adaptColumnWidth(
 | 
				
			||||||
 | 
					            final Table table,
 | 
				
			||||||
 | 
					            final TableContext tableContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            final int currentTableWidth = table.getClientArea().width - 50;
 | 
				
			||||||
 | 
					            final TableColumn[] columns = table.getColumns();
 | 
				
			||||||
 | 
					            final int widthUnit = currentTableWidth / (columns.length + 2);
 | 
				
			||||||
 | 
					            for (int i = 0; i < columns.length; i++) {
 | 
				
			||||||
 | 
					                final int factor = (TABLE_ENTRY_NAME.equals(columns[i].getData(TABLE_COLUMN_NAME_KEY))) ? 4 : 1;
 | 
				
			||||||
 | 
					                columns[i].setWidth(widthUnit * factor);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (final Exception e) {
 | 
				
			||||||
 | 
					            log.warn("Failed to adaptColumnWidth: ", e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static final class CompositeTableInputField extends AbstractTableInputField {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final List<String> columns;
 | 
				
			||||||
 | 
					        final List<String> rows;
 | 
				
			||||||
 | 
					        final List<Map<Long, TableValue>> values;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CompositeTableInputField(
 | 
				
			||||||
 | 
					                final TableContext tableContext,
 | 
				
			||||||
 | 
					                final Table control,
 | 
				
			||||||
 | 
					                final List<String> columns,
 | 
				
			||||||
 | 
					                final List<String> rows) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            super(tableContext.attribute, tableContext.orientation, control, null, tableContext);
 | 
				
			||||||
 | 
					            this.values = new ArrayList<>();
 | 
				
			||||||
 | 
					            this.columns = columns;
 | 
				
			||||||
 | 
					            this.rows = rows;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        void initValue(final List<TableValue> tableValues) {
 | 
				
			||||||
 | 
					            valuesFromIndexMap(this.values, createRowIndexMap(tableValues));
 | 
				
			||||||
 | 
					            for (int i = 0; i < this.values.size(); i++) {
 | 
				
			||||||
 | 
					                setRowValues(i, this.values.get(i));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected void applyTableRowValues(final int index) {
 | 
				
			||||||
 | 
					            setRowValues(index, this.values.get(index));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void setRowValues(final int index, final Map<Long, TableValue> map) {
 | 
				
			||||||
 | 
					            final TableItem rowItem = this.control.getItem(index);
 | 
				
			||||||
 | 
					            for (final TableValue val : map.values()) {
 | 
				
			||||||
 | 
					                final Orientation orientation = this.tableContext.getOrientation(val.attributeId);
 | 
				
			||||||
 | 
					                final String groupId = orientation.getGroupId();
 | 
				
			||||||
 | 
					                if (StringUtils.isNoneBlank(groupId)) {
 | 
				
			||||||
 | 
					                    final int cellIndex = this.columns.indexOf(groupId);
 | 
				
			||||||
 | 
					                    if (cellIndex >= 0) {
 | 
				
			||||||
 | 
					                        setValueToCell(
 | 
				
			||||||
 | 
					                                this.tableContext,
 | 
				
			||||||
 | 
					                                rowItem,
 | 
				
			||||||
 | 
					                                cellIndex,
 | 
				
			||||||
 | 
					                                this.tableContext.getAttribute(val.attributeId),
 | 
				
			||||||
 | 
					                                val);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected void openForm(final int selectionIndex) {
 | 
				
			||||||
 | 
					            final String row = this.rows.get(selectionIndex);
 | 
				
			||||||
 | 
					            final Map<Long, TableValue> rowValues = this.values.get(selectionIndex);
 | 
				
			||||||
 | 
					            final TableRowFormBuilder builder = new TableRowFormBuilder(
 | 
				
			||||||
 | 
					                    this.tableContext,
 | 
				
			||||||
 | 
					                    rowValues,
 | 
				
			||||||
 | 
					                    row);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            new ModalInputDialog<Map<Long, TableValue>>(
 | 
				
			||||||
 | 
					                    this.control.getShell(),
 | 
				
			||||||
 | 
					                    this.tableContext.getWidgetFactory())
 | 
				
			||||||
 | 
					                            .setDialogWidth(500)
 | 
				
			||||||
 | 
					                            .open(
 | 
				
			||||||
 | 
					                                    new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + row),
 | 
				
			||||||
 | 
					                                    rowVals -> applyFormValues(this.values, rowVals, selectionIndex),
 | 
				
			||||||
 | 
					                                    () -> this.tableContext.getValueChangeListener()
 | 
				
			||||||
 | 
					                                            .tableChanged(extractTableValue(this.values)),
 | 
				
			||||||
 | 
					                                    builder);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected Map<Integer, Map<Long, TableValue>> createRowIndexMap(final List<TableValue> tableValues) {
 | 
				
			||||||
 | 
					            final Map<Integer, Map<Long, TableValue>> indexMapping = new HashMap<>();
 | 
				
			||||||
 | 
					            for (final TableValue tableValue : tableValues) {
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attribute = this.tableContext
 | 
				
			||||||
 | 
					                        .getViewContext()
 | 
				
			||||||
 | 
					                        .getAttribute(tableValue.attributeId);
 | 
				
			||||||
 | 
					                final String groupId = ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                        ConfigurationAttribute.DEPENDENCY_GROUP_ID,
 | 
				
			||||||
 | 
					                        attribute);
 | 
				
			||||||
 | 
					                final int index = this.rows.indexOf(groupId);
 | 
				
			||||||
 | 
					                final Map<Long, TableValue> rowValues = indexMapping.computeIfAbsent(
 | 
				
			||||||
 | 
					                        index,
 | 
				
			||||||
 | 
					                        key -> new HashMap<>());
 | 
				
			||||||
 | 
					                rowValues.put(tableValue.attributeId, tableValue);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return indexMapping;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        void clearTable() {
 | 
				
			||||||
 | 
					            // nothing to clear for this table type
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected boolean isChildValue(
 | 
				
			||||||
 | 
					                final TableContext tableContext,
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					                final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            final boolean childValue = super.isChildValue(tableContext, attribute, value);
 | 
				
			||||||
 | 
					            if (childValue) {
 | 
				
			||||||
 | 
					                final ConfigurationAttribute attr = tableContext.getAttribute(value.attributeId);
 | 
				
			||||||
 | 
					                return ConfigurationAttribute.hasDependency(
 | 
				
			||||||
 | 
					                        ConfigurationAttribute.DEPENDENCY_GROUP_ID,
 | 
				
			||||||
 | 
					                        attr);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return childValue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -166,7 +166,6 @@ public class ExamConfigurationServiceImpl implements ExamConfigurationService {
 | 
				
			||||||
        gridLayout.verticalSpacing = 0;
 | 
					        gridLayout.verticalSpacing = 0;
 | 
				
			||||||
        composite.setLayout(gridLayout);
 | 
					        composite.setLayout(gridLayout);
 | 
				
			||||||
        final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
 | 
					        final GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
 | 
				
			||||||
        gridData.heightHint = 200;
 | 
					 | 
				
			||||||
        composite.setLayoutData(gridData);
 | 
					        composite.setLayoutData(gridData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final ViewGridBuilder viewGridBuilder = new ViewGridBuilder(
 | 
					        final ViewGridBuilder viewGridBuilder = new ViewGridBuilder(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,9 +8,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Objects;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import org.eclipse.swt.SWT;
 | 
					 | 
				
			||||||
import org.eclipse.swt.widgets.Composite;
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
import org.eclipse.swt.widgets.Label;
 | 
					import org.eclipse.swt.widgets.Label;
 | 
				
			||||||
import org.springframework.context.annotation.Lazy;
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
| 
						 | 
					@ -20,14 +17,22 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Lazy
 | 
					@Lazy
 | 
				
			||||||
@Component
 | 
					@Component
 | 
				
			||||||
@GuiProfile
 | 
					@GuiProfile
 | 
				
			||||||
public class LabelBuilder implements InputFieldBuilder {
 | 
					public class LabelBuilder implements InputFieldBuilder {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final WidgetFactory widgetFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    protected LabelBuilder(final WidgetFactory widgetFactory) {
 | 
				
			||||||
 | 
					        this.widgetFactory = widgetFactory;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public boolean builderFor(
 | 
					    public boolean builderFor(
 | 
				
			||||||
            final ConfigurationAttribute attribute,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
| 
						 | 
					@ -46,12 +51,9 @@ public class LabelBuilder implements InputFieldBuilder {
 | 
				
			||||||
            final ConfigurationAttribute attribute,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ViewContext viewContext) {
 | 
					            final ViewContext viewContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Objects.requireNonNull(parent);
 | 
					        final Label label = this.widgetFactory.labelLocalized(
 | 
				
			||||||
        Objects.requireNonNull(attribute);
 | 
					                parent,
 | 
				
			||||||
        Objects.requireNonNull(viewContext);
 | 
					                ExamConfigurationService.attributeNameLocKey(attribute));
 | 
				
			||||||
 | 
					 | 
				
			||||||
        final Label label = new Label(parent, SWT.NONE);
 | 
					 | 
				
			||||||
        label.setText(attribute.name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new LabelField(
 | 
					        return new LabelField(
 | 
				
			||||||
                attribute,
 | 
					                attribute,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,6 @@ package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
				
			||||||
import java.util.Arrays;
 | 
					import java.util.Arrays;
 | 
				
			||||||
import java.util.Collections;
 | 
					import java.util.Collections;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
| 
						 | 
					@ -19,7 +18,6 @@ import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
					import ch.ethz.seb.sebserver.gbl.Constants;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class SelectionFieldBuilder {
 | 
					public abstract class SelectionFieldBuilder {
 | 
				
			||||||
| 
						 | 
					@ -47,10 +45,13 @@ public abstract class SelectionFieldBuilder {
 | 
				
			||||||
            return Collections.emptyList();
 | 
					            return Collections.emptyList();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Map<String, String> attributeDependencyMap = Utils.getAttributeDependencyMap(attribute);
 | 
					 | 
				
			||||||
        final String prefix =
 | 
					        final String prefix =
 | 
				
			||||||
                (attributeDependencyMap.containsKey(ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY))
 | 
					                (ConfigurationAttribute.hasDependency(
 | 
				
			||||||
                        ? attributeDependencyMap.get(ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY) + "."
 | 
					                        ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY,
 | 
				
			||||||
 | 
					                        attribute))
 | 
				
			||||||
 | 
					                                ? ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                                        ConfigurationAttribute.DEPENDENCY_RESOURCE_LOC_TEXT_KEY,
 | 
				
			||||||
 | 
					                                        attribute) + "."
 | 
				
			||||||
                                : ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.name + ".";
 | 
					                                : ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX + attribute.name + ".";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return Arrays.asList(StringUtils.split(
 | 
					        return Arrays.asList(StringUtils.split(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,21 +16,18 @@ import java.util.Objects;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.lang3.BooleanUtils;
 | 
					 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					import org.slf4j.Logger;
 | 
				
			||||||
import org.slf4j.LoggerFactory;
 | 
					import org.slf4j.LoggerFactory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.Constants;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeListener;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeListener;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigTableRowValues;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.seb.examconfig.GetExamConfigTableRowValues;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
				
			||||||
| 
						 | 
					@ -78,6 +75,10 @@ public class TableContext {
 | 
				
			||||||
                .collect(Collectors.toList());
 | 
					                .collect(Collectors.toList());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public I18nSupport i18nSupport() {
 | 
				
			||||||
 | 
					        return this.viewContext.i18nSupport;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public InputFieldBuilderSupplier getInputFieldBuilderSupplier() {
 | 
					    public InputFieldBuilderSupplier getInputFieldBuilderSupplier() {
 | 
				
			||||||
        return this.inputFieldBuilderSupplier;
 | 
					        return this.inputFieldBuilderSupplier;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -102,6 +103,20 @@ public class TableContext {
 | 
				
			||||||
        return this.rowAttributes;
 | 
					        return this.rowAttributes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<ConfigurationAttribute> getRowAttributes(final String rowGroupId) {
 | 
				
			||||||
 | 
					        if (StringUtils.isBlank(rowGroupId)) {
 | 
				
			||||||
 | 
					            return getRowAttributes();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return this.rowAttributes
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .filter(attr -> rowGroupId.equals(ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                            ConfigurationAttribute.DEPENDENCY_GROUP_ID,
 | 
				
			||||||
 | 
					                            attr)))
 | 
				
			||||||
 | 
					                    .sorted(rowAttributeComparator(this.viewContext))
 | 
				
			||||||
 | 
					                    .collect(Collectors.toList());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<ConfigurationAttribute> getColumnAttributes() {
 | 
					    public List<ConfigurationAttribute> getColumnAttributes() {
 | 
				
			||||||
        return this.columnAttributes;
 | 
					        return this.columnAttributes;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -188,31 +203,4 @@ public class TableContext {
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public String getRowValue(final TableValue tableValue) {
 | 
					 | 
				
			||||||
        if (tableValue == null || StringUtils.isBlank(tableValue.value)) {
 | 
					 | 
				
			||||||
            return Constants.EMPTY_NOTE;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        final ConfigurationAttribute attribute = this.viewContext.getAttribute(tableValue.attributeId);
 | 
					 | 
				
			||||||
        if (attribute != null) {
 | 
					 | 
				
			||||||
            switch (attribute.type) {
 | 
					 | 
				
			||||||
                case CHECKBOX: {
 | 
					 | 
				
			||||||
                    return BooleanUtils.toBoolean(tableValue.value)
 | 
					 | 
				
			||||||
                            ? this.viewContext.i18nSupport.getText(ResourceService.ACTIVE_TEXT_KEY)
 | 
					 | 
				
			||||||
                            : this.viewContext.i18nSupport.getText(ResourceService.INACTIVE_TEXT_KEY);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                case SINGLE_SELECTION: {
 | 
					 | 
				
			||||||
                    final String key = ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX +
 | 
					 | 
				
			||||||
                            attribute.getName() + "." +
 | 
					 | 
				
			||||||
                            tableValue.value;
 | 
					 | 
				
			||||||
                    return this.viewContext.i18nSupport.getText(key, tableValue.value);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                default:
 | 
					 | 
				
			||||||
                    return tableValue.value;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return tableValue.value;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,37 +9,27 @@
 | 
				
			||||||
package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig.impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.function.Function;
 | 
					import java.util.function.Function;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.lang3.BooleanUtils;
 | 
					 | 
				
			||||||
import org.eclipse.swt.SWT;
 | 
					import org.eclipse.swt.SWT;
 | 
				
			||||||
import org.eclipse.swt.layout.GridData;
 | 
					 | 
				
			||||||
import org.eclipse.swt.layout.GridLayout;
 | 
					 | 
				
			||||||
import org.eclipse.swt.widgets.Composite;
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
import org.eclipse.swt.widgets.Table;
 | 
					import org.eclipse.swt.widgets.Table;
 | 
				
			||||||
import org.eclipse.swt.widgets.TableColumn;
 | 
					import org.eclipse.swt.widgets.TableColumn;
 | 
				
			||||||
import org.eclipse.swt.widgets.TableItem;
 | 
					import org.eclipse.swt.widgets.TableItem;
 | 
				
			||||||
import org.slf4j.Logger;
 | 
					 | 
				
			||||||
import org.slf4j.LoggerFactory;
 | 
					 | 
				
			||||||
import org.springframework.context.annotation.Lazy;
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
import org.springframework.stereotype.Component;
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
 | 
					import ch.ethz.seb.sebserver.gui.service.page.impl.ModalInputDialog;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
					import ch.ethz.seb.sebserver.gui.widget.WidgetFactory;
 | 
				
			||||||
| 
						 | 
					@ -48,27 +38,13 @@ import ch.ethz.seb.sebserver.gui.widget.WidgetFactory.ImageIcon;
 | 
				
			||||||
@Lazy
 | 
					@Lazy
 | 
				
			||||||
@Component
 | 
					@Component
 | 
				
			||||||
@GuiProfile
 | 
					@GuiProfile
 | 
				
			||||||
public class TableFieldBuilder implements InputFieldBuilder {
 | 
					public class TableFieldBuilder extends AbstractTableFieldBuilder {
 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final Logger log = LoggerFactory.getLogger(TableFieldBuilder.class);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static final String ROW_VALUE_KEY = "RowValues";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private final RestService restService;
 | 
					 | 
				
			||||||
    private final WidgetFactory widgetFactory;
 | 
					 | 
				
			||||||
    private InputFieldBuilderSupplier inputFieldBuilderSupplier;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected TableFieldBuilder(
 | 
					    protected TableFieldBuilder(
 | 
				
			||||||
            final RestService restService,
 | 
					            final RestService restService,
 | 
				
			||||||
            final WidgetFactory widgetFactory) {
 | 
					            final WidgetFactory widgetFactory) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.restService = restService;
 | 
					        super(restService, widgetFactory);
 | 
				
			||||||
        this.widgetFactory = widgetFactory;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void init(final InputFieldBuilderSupplier inputFieldBuilderSupplier) {
 | 
					 | 
				
			||||||
        this.inputFieldBuilderSupplier = inputFieldBuilderSupplier;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					@ -89,35 +65,20 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
            final ConfigurationAttribute attribute,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ViewContext viewContext) {
 | 
					            final ViewContext viewContext) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final I18nSupport i18nSupport = viewContext.getI18nSupport();
 | 
					        final TableContext tableContext = createTableContext(attribute, viewContext);
 | 
				
			||||||
        final TableContext tableContext = new TableContext(
 | 
					        final Table table = createTable(parent, tableContext);
 | 
				
			||||||
                this.inputFieldBuilderSupplier,
 | 
					 | 
				
			||||||
                this.widgetFactory,
 | 
					 | 
				
			||||||
                this.restService,
 | 
					 | 
				
			||||||
                attribute,
 | 
					 | 
				
			||||||
                viewContext);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        final Table table = new Table(parent, SWT.NONE | SWT.H_SCROLL);
 | 
					 | 
				
			||||||
        table.setLayout(new GridLayout());
 | 
					 | 
				
			||||||
        final GridData gridData = new GridData(
 | 
					 | 
				
			||||||
                SWT.FILL, SWT.FILL,
 | 
					 | 
				
			||||||
                true, false,
 | 
					 | 
				
			||||||
                (tableContext.orientation != null) ? tableContext.orientation.width() : 1,
 | 
					 | 
				
			||||||
                (tableContext.orientation != null) ? tableContext.orientation.height() : 1);
 | 
					 | 
				
			||||||
        gridData.heightHint = tableContext.orientation.height * 20 + 40;
 | 
					 | 
				
			||||||
        table.setLayoutData(gridData);
 | 
					 | 
				
			||||||
        table.setHeaderVisible(true);
 | 
					 | 
				
			||||||
        table.addListener(SWT.Resize, event -> adaptColumnWidth(table, tableContext));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (final ConfigurationAttribute columnAttribute : tableContext.getColumnAttributes()) {
 | 
					        for (final ConfigurationAttribute columnAttribute : tableContext.getColumnAttributes()) {
 | 
				
			||||||
            final TableColumn column = new TableColumn(table, SWT.NONE);
 | 
					            final TableColumn column = this.widgetFactory.tableColumnLocalized(
 | 
				
			||||||
            final String text = i18nSupport.getText(
 | 
					                    table,
 | 
				
			||||||
                    ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX +
 | 
					                    new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX +
 | 
				
			||||||
                            columnAttribute.name,
 | 
					                            columnAttribute.name),
 | 
				
			||||||
                    columnAttribute.name);
 | 
					                    new LocTextKey(ExamConfigurationService.ATTRIBUTE_LABEL_LOC_TEXT_PREFIX +
 | 
				
			||||||
            column.setText(text);
 | 
					                            columnAttribute.name +
 | 
				
			||||||
 | 
					                            ".tootltip"));
 | 
				
			||||||
            column.setWidth(100);
 | 
					            column.setWidth(100);
 | 
				
			||||||
            column.setResizable(false);
 | 
					            column.setResizable(false);
 | 
				
			||||||
 | 
					            column.setMoveable(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final TableInputField tableField = new TableInputField(
 | 
					        final TableInputField tableField = new TableInputField(
 | 
				
			||||||
| 
						 | 
					@ -149,107 +110,28 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        table.addListener(SWT.MouseDoubleClick, event -> {
 | 
					        setSelectionListener(table, tableField);
 | 
				
			||||||
            final int selectionIndex = table.getSelectionIndex();
 | 
					 | 
				
			||||||
            if (selectionIndex >= 0) {
 | 
					 | 
				
			||||||
                tableField.openForm(selectionIndex);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return tableField;
 | 
					        return tableField;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void adaptColumnWidth(
 | 
					    static final class TableInputField extends AbstractTableInputField {
 | 
				
			||||||
            final Table table,
 | 
					 | 
				
			||||||
            final TableContext tableContext) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        private final List<Map<Long, TableValue>> values;
 | 
				
			||||||
            final int currentTableWidth = table.getClientArea().width - 50;
 | 
					 | 
				
			||||||
            final TableColumn[] columns = table.getColumns();
 | 
					 | 
				
			||||||
            final List<Orientation> orientations = tableContext
 | 
					 | 
				
			||||||
                    .getColumnAttributes()
 | 
					 | 
				
			||||||
                    .stream()
 | 
					 | 
				
			||||||
                    .map(attr -> tableContext.getOrientation(attr.id))
 | 
					 | 
				
			||||||
                    .collect(Collectors.toList());
 | 
					 | 
				
			||||||
            final Integer div = orientations
 | 
					 | 
				
			||||||
                    .stream()
 | 
					 | 
				
			||||||
                    .map(o -> o.width)
 | 
					 | 
				
			||||||
                    .reduce(0, (acc, val) -> acc + val);
 | 
					 | 
				
			||||||
            final int widthUnit = currentTableWidth / div;
 | 
					 | 
				
			||||||
            for (int i = 0; i < columns.length - 2; i++) {
 | 
					 | 
				
			||||||
                columns[i].setWidth(widthUnit * orientations.get(i).width);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } catch (final Exception e) {
 | 
					 | 
				
			||||||
            log.warn("Failed to adaptColumnWidth: ", e);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static final class TableInputField extends AbstractInputField<Table> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private final TableContext tableContext;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private List<Map<Long, TableValue>> values;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TableInputField(
 | 
					        TableInputField(
 | 
				
			||||||
                final TableContext tableContext,
 | 
					                final TableContext tableContext,
 | 
				
			||||||
                final Table control) {
 | 
					                final Table control) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            super(tableContext.attribute, tableContext.orientation, control, null);
 | 
					            super(tableContext.attribute, tableContext.orientation, control, null, tableContext);
 | 
				
			||||||
            this.tableContext = tableContext;
 | 
					            this.values = new ArrayList<>();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public ConfigurationValue initValue(final Collection<ConfigurationValue> values) {
 | 
					 | 
				
			||||||
            clearTable();
 | 
					 | 
				
			||||||
            // get all child values as TableValues
 | 
					 | 
				
			||||||
            final List<TableValue> tableValues = values.stream()
 | 
					 | 
				
			||||||
                    .filter(this::isChildValue)
 | 
					 | 
				
			||||||
                    .map(TableValue::of)
 | 
					 | 
				
			||||||
                    .collect(Collectors.toList());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            initValue(tableValues);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        void initValue(final List<TableValue> tableValues) {
 | 
					        void initValue(final List<TableValue> tableValues) {
 | 
				
			||||||
            final Map<Integer, Map<Long, TableValue>> _initValue = new HashMap<>();
 | 
					            valuesFromIndexMap(this.values, createRowIndexMap(tableValues));
 | 
				
			||||||
            for (final TableValue tableValue : tableValues) {
 | 
					            for (int i = 0; i < this.values.size(); i++) {
 | 
				
			||||||
                final Map<Long, TableValue> rowValues = _initValue.computeIfAbsent(
 | 
					                addTableRow(i, this.values.get(i));
 | 
				
			||||||
                        tableValue.listIndex,
 | 
					 | 
				
			||||||
                        key -> new HashMap<>());
 | 
					 | 
				
			||||||
                rowValues.put(tableValue.attributeId, tableValue);
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            final List<Integer> rows = new ArrayList<>(_initValue.keySet());
 | 
					 | 
				
			||||||
            rows.sort((i1, i2) -> i1.compareTo(i2));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.values = new ArrayList<>();
 | 
					 | 
				
			||||||
            rows
 | 
					 | 
				
			||||||
                    .stream()
 | 
					 | 
				
			||||||
                    .forEach(i -> {
 | 
					 | 
				
			||||||
                        final Map<Long, TableValue> rowValues = _initValue.get(i);
 | 
					 | 
				
			||||||
                        this.values.add(rowValues);
 | 
					 | 
				
			||||||
                        addTableRow(rowValues);
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private boolean isChildValue(final ConfigurationValue value) {
 | 
					 | 
				
			||||||
            if (!this.tableContext.getViewContext().attributeMapping.attributeIdMapping
 | 
					 | 
				
			||||||
                    .containsKey(value.attributeId)) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                return false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            ConfigurationAttribute attr = this.tableContext.getAttribute(value.attributeId);
 | 
					 | 
				
			||||||
            while (attr.parentId != null) {
 | 
					 | 
				
			||||||
                if (this.attribute.id.equals(attr.parentId)) {
 | 
					 | 
				
			||||||
                    return true;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                attr = this.tableContext.getAttribute(attr.parentId);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return false;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void deleteRow(final int selectionIndex) {
 | 
					        private void deleteRow(final int selectionIndex) {
 | 
				
			||||||
| 
						 | 
					@ -257,7 +139,7 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
            this.values.remove(selectionIndex);
 | 
					            this.values.remove(selectionIndex);
 | 
				
			||||||
            // send new values to web-service
 | 
					            // send new values to web-service
 | 
				
			||||||
            this.tableContext.getValueChangeListener()
 | 
					            this.tableContext.getValueChangeListener()
 | 
				
			||||||
                    .tableChanged(extractTableValue());
 | 
					                    .tableChanged(extractTableValue(this.values));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void addRow() {
 | 
					        private void addRow() {
 | 
				
			||||||
| 
						 | 
					@ -271,21 +153,22 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
                            Function.identity()));
 | 
					                            Function.identity()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.values.add(rowValues);
 | 
					            this.values.add(rowValues);
 | 
				
			||||||
            addTableRow(rowValues);
 | 
					            addTableRow(this.values.size() - 1, rowValues);
 | 
				
			||||||
            this.control.layout();
 | 
					            this.control.layout();
 | 
				
			||||||
            // send new values to web-service
 | 
					            // send new values to web-service
 | 
				
			||||||
            this.tableContext.getValueChangeListener()
 | 
					            this.tableContext.getValueChangeListener()
 | 
				
			||||||
                    .tableChanged(extractTableValue());
 | 
					                    .tableChanged(extractTableValue(this.values));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void addTableRow(final Map<Long, TableValue> rowValues) {
 | 
					        protected void addTableRow(final int index, final Map<Long, TableValue> rowValues) {
 | 
				
			||||||
            new TableItem(this.control, SWT.NONE);
 | 
					            new TableItem(this.control, SWT.NONE);
 | 
				
			||||||
            applyTableRowValues(this.values.size() - 1);
 | 
					            applyTableRowValues(index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // TODO try to add delete button within table row?
 | 
					            // TODO try to add delete button within table row?
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void applyTableRowValues(final int index) {
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected void applyTableRowValues(final int index) {
 | 
				
			||||||
            final TableItem item = this.control.getItem(index);
 | 
					            final TableItem item = this.control.getItem(index);
 | 
				
			||||||
            final Map<Long, TableValue> rowValues = this.values.get(index);
 | 
					            final Map<Long, TableValue> rowValues = this.values.get(index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -293,26 +176,14 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
            for (final ConfigurationAttribute attr : this.tableContext.getColumnAttributes()) {
 | 
					            for (final ConfigurationAttribute attr : this.tableContext.getColumnAttributes()) {
 | 
				
			||||||
                if (rowValues.containsKey(attr.id)) {
 | 
					                if (rowValues.containsKey(attr.id)) {
 | 
				
			||||||
                    final TableValue tableValue = rowValues.get(attr.id);
 | 
					                    final TableValue tableValue = rowValues.get(attr.id);
 | 
				
			||||||
                    if (attr.type == AttributeType.CHECKBOX) {
 | 
					                    setValueToCell(this.tableContext, item, cellIndex, attr, tableValue);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        item.setImage(
 | 
					 | 
				
			||||||
                                cellIndex,
 | 
					 | 
				
			||||||
                                (BooleanUtils.toBoolean((tableValue != null) ? tableValue.value : null))
 | 
					 | 
				
			||||||
                                        ? ImageIcon.YES.getImage(this.control.getDisplay())
 | 
					 | 
				
			||||||
                                        : ImageIcon.NO.getImage(this.control.getDisplay()));
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        item.setText(
 | 
					 | 
				
			||||||
                                cellIndex,
 | 
					 | 
				
			||||||
                                this.tableContext.getRowValue(tableValue));
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                cellIndex++;
 | 
					                cellIndex++;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            item.setData(ROW_VALUE_KEY, item);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void openForm(final int selectionIndex) {
 | 
					        @Override
 | 
				
			||||||
 | 
					        protected void openForm(final int selectionIndex) {
 | 
				
			||||||
            final Map<Long, TableValue> rowValues = this.values.get(selectionIndex);
 | 
					            final Map<Long, TableValue> rowValues = this.values.get(selectionIndex);
 | 
				
			||||||
            final TableRowFormBuilder builder = new TableRowFormBuilder(
 | 
					            final TableRowFormBuilder builder = new TableRowFormBuilder(
 | 
				
			||||||
                    this.tableContext,
 | 
					                    this.tableContext,
 | 
				
			||||||
| 
						 | 
					@ -327,69 +198,12 @@ public class TableFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
                                    ExamConfigurationService.getTablePopupTitleKey(
 | 
					                                    ExamConfigurationService.getTablePopupTitleKey(
 | 
				
			||||||
                                            this.attribute,
 | 
					                                            this.attribute,
 | 
				
			||||||
                                            this.tableContext.getViewContext().i18nSupport),
 | 
					                                            this.tableContext.getViewContext().i18nSupport),
 | 
				
			||||||
                                    values -> applyFormValues(values, selectionIndex),
 | 
					                                    rowVals -> applyFormValues(this.values, rowVals, selectionIndex),
 | 
				
			||||||
                                    () -> this.tableContext.getValueChangeListener()
 | 
					                                    () -> this.tableContext.getValueChangeListener()
 | 
				
			||||||
                                            .tableChanged(extractTableValue()),
 | 
					                                            .tableChanged(extractTableValue(this.values)),
 | 
				
			||||||
                                    builder);
 | 
					                                    builder);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private void applyFormValues(final Map<Long, TableValue> values, final int index) {
 | 
					 | 
				
			||||||
            if (values != null && !values.isEmpty()) {
 | 
					 | 
				
			||||||
                this.values.remove(index);
 | 
					 | 
				
			||||||
                this.values.add(index, values);
 | 
					 | 
				
			||||||
                applyTableRowValues(index);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // send values to web-service
 | 
					 | 
				
			||||||
            this.tableContext.getValueChangeListener()
 | 
					 | 
				
			||||||
                    .tableChanged(extractTableValue());
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private ConfigurationTableValues extractTableValue() {
 | 
					 | 
				
			||||||
            final List<TableValue> collect = this.values
 | 
					 | 
				
			||||||
                    .stream()
 | 
					 | 
				
			||||||
                    .flatMap(map -> map.values().stream())
 | 
					 | 
				
			||||||
                    .collect(Collectors.toList());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return new ConfigurationTableValues(
 | 
					 | 
				
			||||||
                    this.tableContext.getInstitutionId(),
 | 
					 | 
				
			||||||
                    this.tableContext.getConfigurationId(),
 | 
					 | 
				
			||||||
                    this.attribute.id,
 | 
					 | 
				
			||||||
                    collect);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public void setDefaultValue() {
 | 
					 | 
				
			||||||
            // NOTE this just empty the list for now
 | 
					 | 
				
			||||||
            // TODO do we need default values for lists?
 | 
					 | 
				
			||||||
            clearTable();
 | 
					 | 
				
			||||||
            final List<TableValue> values = new ArrayList<>();
 | 
					 | 
				
			||||||
            this.tableContext.getValueChangeListener().tableChanged(
 | 
					 | 
				
			||||||
                    new ConfigurationTableValues(
 | 
					 | 
				
			||||||
                            this.tableContext.getInstitutionId(),
 | 
					 | 
				
			||||||
                            this.tableContext.getConfigurationId(),
 | 
					 | 
				
			||||||
                            this.attribute.id,
 | 
					 | 
				
			||||||
                            values));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void clearTable() {
 | 
					 | 
				
			||||||
            this.control.setSelection(-1);
 | 
					 | 
				
			||||||
            if (this.control.getItemCount() > 0) {
 | 
					 | 
				
			||||||
                for (final TableItem item : this.control.getItems()) {
 | 
					 | 
				
			||||||
                    item.dispose();
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        protected void setValueToControl(final String value) {
 | 
					 | 
				
			||||||
            throw new UnsupportedOperationException();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public String getValue() {
 | 
					 | 
				
			||||||
            throw new UnsupportedOperationException();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,11 +25,11 @@ import org.eclipse.swt.widgets.Label;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.Orientation;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ExamConfigurationService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputField;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.InputFieldBuilder;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.examconfig.impl.TableFieldBuilder.TableInputField;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
 | 
					import ch.ethz.seb.sebserver.gui.service.page.ModalInputDialogComposer;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.page.PageService;
 | 
					import ch.ethz.seb.sebserver.gui.service.page.PageService;
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,7 @@ public class TableRowFormBuilder implements ModalInputDialogComposer<Map<Long, T
 | 
				
			||||||
    private final TableContext tableContext;
 | 
					    private final TableContext tableContext;
 | 
				
			||||||
    private final Map<Long, TableValue> rowValues;
 | 
					    private final Map<Long, TableValue> rowValues;
 | 
				
			||||||
    private final int listIndex;
 | 
					    private final int listIndex;
 | 
				
			||||||
 | 
					    private final String rowGroupId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public TableRowFormBuilder(
 | 
					    public TableRowFormBuilder(
 | 
				
			||||||
            final TableContext tableContext,
 | 
					            final TableContext tableContext,
 | 
				
			||||||
| 
						 | 
					@ -49,6 +50,18 @@ public class TableRowFormBuilder implements ModalInputDialogComposer<Map<Long, T
 | 
				
			||||||
        this.tableContext = tableContext;
 | 
					        this.tableContext = tableContext;
 | 
				
			||||||
        this.rowValues = rowValues;
 | 
					        this.rowValues = rowValues;
 | 
				
			||||||
        this.listIndex = listIndex;
 | 
					        this.listIndex = listIndex;
 | 
				
			||||||
 | 
					        this.rowGroupId = null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TableRowFormBuilder(
 | 
				
			||||||
 | 
					            final TableContext tableContext,
 | 
				
			||||||
 | 
					            final Map<Long, TableValue> rowValues,
 | 
				
			||||||
 | 
					            final String rowGroupId) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.tableContext = tableContext;
 | 
				
			||||||
 | 
					        this.rowValues = rowValues;
 | 
				
			||||||
 | 
					        this.listIndex = 0;
 | 
				
			||||||
 | 
					        this.rowGroupId = rowGroupId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					@ -67,11 +80,25 @@ public class TableRowFormBuilder implements ModalInputDialogComposer<Map<Long, T
 | 
				
			||||||
                false);
 | 
					                false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final List<InputField> inputFields = new ArrayList<>();
 | 
					        final List<InputField> inputFields = new ArrayList<>();
 | 
				
			||||||
        for (final ConfigurationAttribute attribute : this.tableContext.getRowAttributes()) {
 | 
					        for (final ConfigurationAttribute attribute : this.tableContext.getRowAttributes(this.rowGroupId)) {
 | 
				
			||||||
            createLabel(grid, attribute);
 | 
					            createLabel(grid, attribute);
 | 
				
			||||||
            inputFields.add(createInputField(grid, attribute));
 | 
					            inputFields.add(createInputField(grid, attribute));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (final InputField inputField : inputFields) {
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute = inputField.getAttribute();
 | 
				
			||||||
 | 
					            this.tableContext.getValueChangeListener().notifyGUI(
 | 
				
			||||||
 | 
					                    this.tableContext.getViewContext(),
 | 
				
			||||||
 | 
					                    attribute,
 | 
				
			||||||
 | 
					                    new ConfigurationValue(
 | 
				
			||||||
 | 
					                            null,
 | 
				
			||||||
 | 
					                            null,
 | 
				
			||||||
 | 
					                            null,
 | 
				
			||||||
 | 
					                            attribute.id,
 | 
				
			||||||
 | 
					                            this.listIndex,
 | 
				
			||||||
 | 
					                            inputField.getValue()));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // when the pop-up gets closed we have to remove the input fields from the view context
 | 
					        // when the pop-up gets closed we have to remove the input fields from the view context
 | 
				
			||||||
        grid.addDisposeListener(event -> {
 | 
					        grid.addDisposeListener(event -> {
 | 
				
			||||||
            this.tableContext.flushInputFields(this.rowValues.keySet());
 | 
					            this.tableContext.flushInputFields(this.rowValues.keySet());
 | 
				
			||||||
| 
						 | 
					@ -103,14 +130,8 @@ public class TableRowFormBuilder implements ModalInputDialogComposer<Map<Long, T
 | 
				
			||||||
                attribute,
 | 
					                attribute,
 | 
				
			||||||
                this.tableContext.getViewContext());
 | 
					                this.tableContext.getViewContext());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (attribute.type == AttributeType.TABLE) {
 | 
					        final TableValue initValue = this.rowValues.get(attribute.id);
 | 
				
			||||||
            ((TableInputField) inputField).initValue(new ArrayList<>(this.rowValues.values()));
 | 
					        inputField.initValue((initValue != null) ? initValue.value : null, this.listIndex);
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            inputField.initValue(
 | 
					 | 
				
			||||||
                    this.rowValues.get(attribute.id).value,
 | 
					 | 
				
			||||||
                    this.listIndex);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // we have to register the input field within the ViewContext to receive error messages
 | 
					        // we have to register the input field within the ViewContext to receive error messages
 | 
				
			||||||
        this.tableContext.registerInputField(inputField);
 | 
					        this.tableContext.registerInputField(inputField);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,14 +64,23 @@ public class TextFieldBuilder implements InputFieldBuilder {
 | 
				
			||||||
                .createInnerGrid(parent, attribute, orientation);
 | 
					                .createInnerGrid(parent, attribute, orientation);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Text text;
 | 
					        final Text text;
 | 
				
			||||||
        if (attribute.type == AttributeType.INTEGER ||
 | 
					        final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
 | 
				
			||||||
                attribute.type == AttributeType.DECIMAL) {
 | 
					        switch (attribute.type) {
 | 
				
			||||||
 | 
					            case INTEGER:
 | 
				
			||||||
 | 
					            case DECIMAL: {
 | 
				
			||||||
                text = new Text(innerGrid, SWT.RIGHT | SWT.BORDER);
 | 
					                text = new Text(innerGrid, SWT.RIGHT | SWT.BORDER);
 | 
				
			||||||
        } else {
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            case TEXT_AREA: {
 | 
				
			||||||
 | 
					                text = new Text(innerGrid, SWT.LEFT | SWT.BORDER | SWT.MULTI);
 | 
				
			||||||
 | 
					                gridData.heightHint = 50;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            default: {
 | 
				
			||||||
                text = new Text(innerGrid, SWT.LEFT | SWT.BORDER);
 | 
					                text = new Text(innerGrid, SWT.LEFT | SWT.BORDER);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 | 
					        }
 | 
				
			||||||
 | 
					        text.setLayoutData(gridData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final LocTextKey toolTipKey = ExamConfigurationService.getToolTipKey(
 | 
					        final LocTextKey toolTipKey = ExamConfigurationService.getToolTipKey(
 | 
				
			||||||
                attribute,
 | 
					                attribute,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,10 +96,6 @@ public final class ViewContext {
 | 
				
			||||||
    public View getView() {
 | 
					    public View getView() {
 | 
				
			||||||
        return this.view;
 | 
					        return this.view;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
//
 | 
					 | 
				
			||||||
//    public AttributeMapping getAttributeMapping() {
 | 
					 | 
				
			||||||
//        return this.attributeMapping;
 | 
					 | 
				
			||||||
//    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Collection<ConfigurationAttribute> getChildAttributes(final Long id) {
 | 
					    public Collection<ConfigurationAttribute> getChildAttributes(final Long id) {
 | 
				
			||||||
        return this.attributeMapping.childAttributeMapping.get(id);
 | 
					        return this.attributeMapping.childAttributeMapping.get(id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,7 @@ import java.util.Arrays;
 | 
				
			||||||
import java.util.HashSet;
 | 
					import java.util.HashSet;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.BooleanUtils;
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
import org.eclipse.swt.SWT;
 | 
					import org.eclipse.swt.SWT;
 | 
				
			||||||
import org.eclipse.swt.layout.GridData;
 | 
					import org.eclipse.swt.layout.GridData;
 | 
				
			||||||
| 
						 | 
					@ -71,8 +72,12 @@ public class ViewGridBuilder {
 | 
				
			||||||
            log.debug("Add SEB Configuration Attribute: " + attribute);
 | 
					            log.debug("Add SEB Configuration Attribute: " + attribute);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // ignore nested attributes here
 | 
					        // ignore nested attributes here (if not propagated to show up in view)
 | 
				
			||||||
        if (attribute.parentId != null) {
 | 
					        if (attribute.parentId != null &&
 | 
				
			||||||
 | 
					                !BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                        ConfigurationAttribute.DEPENDENCY_SHOW_IN_VIEW,
 | 
				
			||||||
 | 
					                        attribute))) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return this;
 | 
					            return this;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ public class AllowFlashFullscreenRule implements ValueChangeRule {
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void applyRule(
 | 
					    public void applyRule(
 | 
				
			||||||
            final ViewContext context,
 | 
					            final ViewContext context,
 | 
				
			||||||
            final ConfigurationAttribute attribut,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ConfigurationValue value) {
 | 
					            final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (BooleanUtils.toBoolean(value.value)) {
 | 
					        if (BooleanUtils.toBoolean(value.value)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ public class BrowserViewModeRule implements ValueChangeRule {
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void applyRule(
 | 
					    public void applyRule(
 | 
				
			||||||
            final ViewContext context,
 | 
					            final ViewContext context,
 | 
				
			||||||
            final ConfigurationAttribute attribut,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ConfigurationValue value) {
 | 
					            final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (StringUtils.isBlank(value.value)) {
 | 
					        if (StringUtils.isBlank(value.value)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ public class ExitKeySequenceChangeRule implements ValueChangeRule {
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void applyRule(
 | 
					    public void applyRule(
 | 
				
			||||||
            final ViewContext context,
 | 
					            final ViewContext context,
 | 
				
			||||||
            final ConfigurationAttribute attribut,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ConfigurationValue value) {
 | 
					            final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (BooleanUtils.toBoolean(value.value)) {
 | 
					        if (BooleanUtils.toBoolean(value.value)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,7 +34,7 @@ public class HideToolbarDefaultRule implements ValueChangeRule {
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public void applyRule(
 | 
					    public void applyRule(
 | 
				
			||||||
            final ViewContext context,
 | 
					            final ViewContext context,
 | 
				
			||||||
            final ConfigurationAttribute attribut,
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
            final ConfigurationValue value) {
 | 
					            final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (BooleanUtils.toBoolean(value.value)) {
 | 
					        if (BooleanUtils.toBoolean(value.value)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,62 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This Source Code Form is subject to the terms of the Mozilla Public
 | 
				
			||||||
 | 
					 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
				
			||||||
 | 
					 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ch.ethz.seb.sebserver.gui.service.examconfig.impl.rules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.apache.commons.lang3.BooleanUtils;
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.util.Tuple;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.ValueChangeRule;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.examconfig.impl.ViewContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Lazy
 | 
				
			||||||
 | 
					@Service
 | 
				
			||||||
 | 
					@GuiProfile
 | 
				
			||||||
 | 
					public class ProxyPasswordRule implements ValueChangeRule {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static final String KEY_HTTP_PWD_REQUIRED = "HTTPRequiresPassword";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final Map<String, Tuple<String>> observed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public ProxyPasswordRule() {
 | 
				
			||||||
 | 
					        this.observed = new HashMap<>();
 | 
				
			||||||
 | 
					        this.observed.put(KEY_HTTP_PWD_REQUIRED, new Tuple<>("HTTPUsername", "HTTPPassword"));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean observesAttribute(final ConfigurationAttribute attribute) {
 | 
				
			||||||
 | 
					        return this.observed.containsKey(attribute.name);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void applyRule(
 | 
				
			||||||
 | 
					            final ViewContext context,
 | 
				
			||||||
 | 
					            final ConfigurationAttribute attribute,
 | 
				
			||||||
 | 
					            final ConfigurationValue value) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final Tuple<String> tuple = this.observed.get(attribute.name);
 | 
				
			||||||
 | 
					        if (tuple != null) {
 | 
				
			||||||
 | 
					            if (BooleanUtils.toBoolean(value.value)) {
 | 
				
			||||||
 | 
					                context.enable(tuple._1);
 | 
				
			||||||
 | 
					                context.enable(tuple._2);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                context.disable(tuple._1);
 | 
				
			||||||
 | 
					                context.disable(tuple._2);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -94,4 +94,6 @@ public interface I18nSupport {
 | 
				
			||||||
     * @return the text in current language parsed from localized text */
 | 
					     * @return the text in current language parsed from localized text */
 | 
				
			||||||
    String getText(String key, Locale locale, String def, Object... args);
 | 
					    String getText(String key, Locale locale, String def, Object... args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    boolean hasText(LocTextKey locTooltipKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ import ch.ethz.seb.sebserver.gbl.model.user.UserInfo;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.I18nSupport;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.i18n.LocTextKey;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.auth.CurrentUser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Lazy
 | 
					@Lazy
 | 
				
			||||||
| 
						 | 
					@ -168,4 +169,13 @@ public class I18nSupportImpl implements I18nSupport {
 | 
				
			||||||
        return this.messageSource.getMessage(key, args, def, locale);
 | 
					        return this.messageSource.getMessage(key, args, def, locale);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public boolean hasText(final LocTextKey key) {
 | 
				
			||||||
 | 
					        if (key == null) {
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return getText(key.name, (String) null) != null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,7 +155,7 @@ public final class PolyglotPageServiceImpl implements PolyglotPageService {
 | 
				
			||||||
        tableColumn.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey);
 | 
					        tableColumn.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey);
 | 
				
			||||||
        tableColumn.setText(this.i18nSupport.getText(locTextKey));
 | 
					        tableColumn.setText(this.i18nSupport.getText(locTextKey));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (locTooltipKey != null) {
 | 
					        if (this.i18nSupport.hasText(locTooltipKey)) {
 | 
				
			||||||
            tableColumn.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey);
 | 
					            tableColumn.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey);
 | 
				
			||||||
            tableColumn.setToolTipText(this.i18nSupport.getText(locTooltipKey));
 | 
					            tableColumn.setToolTipText(this.i18nSupport.getText(locTooltipKey));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -178,7 +178,7 @@ public final class PolyglotPageServiceImpl implements PolyglotPageService {
 | 
				
			||||||
        tabItem.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey);
 | 
					        tabItem.setData(POLYGLOT_ITEM_TEXT_DATA_KEY, locTextKey);
 | 
				
			||||||
        tabItem.setText(this.i18nSupport.getText(locTextKey));
 | 
					        tabItem.setText(this.i18nSupport.getText(locTextKey));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (locTooltipKey != null) {
 | 
					        if (this.i18nSupport.hasText(locTooltipKey)) {
 | 
				
			||||||
            tabItem.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey);
 | 
					            tabItem.setData(POLYGLOT_ITEM_TOOLTIP_DATA_KEY, locTooltipKey);
 | 
				
			||||||
            tabItem.setToolTipText(this.i18nSupport.getText(locTooltipKey));
 | 
					            tabItem.setToolTipText(this.i18nSupport.getText(locTooltipKey));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -189,7 +189,7 @@ public class PageServiceImpl implements PageService {
 | 
				
			||||||
                            .getUISession()
 | 
					                            .getUISession()
 | 
				
			||||||
                            .getHttpSession();
 | 
					                            .getHttpSession();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    log.debug("SET session PageState: {} : {}", pageAction.definition.targetState, httpSession.getId());
 | 
					                    log.debug("Set session PageState: {} : {}", pageAction.definition.targetState, httpSession.getId());
 | 
				
			||||||
                    httpSession.setAttribute(ATTR_PAGE_STATE, pageAction.definition.targetState);
 | 
					                    httpSession.setAttribute(ATTR_PAGE_STATE, pageAction.definition.targetState);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                } catch (final Exception e) {
 | 
					                } catch (final Exception e) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,7 +308,8 @@ public class EntityTable<ROW extends Entity> {
 | 
				
			||||||
                    // TODO error handling
 | 
					                    // TODO error handling
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.composite.layout(true, true);
 | 
					        this.composite.getParent().layout(true, true);
 | 
				
			||||||
 | 
					        PageService.updateScrolledComposite(this.composite);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Page<ROW> createTableRowsFromPage(final Page<ROW> page) {
 | 
					    private Page<ROW> createTableRowsFromPage(final Page<ROW> page) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,8 @@ public final class ColorSelection extends Composite implements Selection {
 | 
				
			||||||
    private static final long serialVersionUID = 4775375044147842526L;
 | 
					    private static final long serialVersionUID = 4775375044147842526L;
 | 
				
			||||||
    private static final Logger log = LoggerFactory.getLogger(ColorSelection.class);
 | 
					    private static final Logger log = LoggerFactory.getLogger(ColorSelection.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final LocTextKey DEFAULT_SELECT_TOOLTIP_KEY = new LocTextKey("sebserver.overall.action.select");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
					    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
				
			||||||
    private final ColorDialog colorDialog;
 | 
					    private final ColorDialog colorDialog;
 | 
				
			||||||
    private final Composite colorField;
 | 
					    private final Composite colorField;
 | 
				
			||||||
| 
						 | 
					@ -40,7 +42,11 @@ public final class ColorSelection extends Composite implements Selection {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Listener listener = null;
 | 
					    private Listener listener = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ColorSelection(final Composite parent, final WidgetFactory widgetFactory) {
 | 
					    ColorSelection(
 | 
				
			||||||
 | 
					            final Composite parent,
 | 
				
			||||||
 | 
					            final WidgetFactory widgetFactory,
 | 
				
			||||||
 | 
					            final String tooltipKeyPrefix) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        super(parent, SWT.NONE);
 | 
					        super(parent, SWT.NONE);
 | 
				
			||||||
        final GridLayout gridLayout = new GridLayout(2, false);
 | 
					        final GridLayout gridLayout = new GridLayout(2, false);
 | 
				
			||||||
        gridLayout.verticalSpacing = 1;
 | 
					        gridLayout.verticalSpacing = 1;
 | 
				
			||||||
| 
						 | 
					@ -60,7 +66,9 @@ public final class ColorSelection extends Composite implements Selection {
 | 
				
			||||||
        final Label imageButton = widgetFactory.imageButton(
 | 
					        final Label imageButton = widgetFactory.imageButton(
 | 
				
			||||||
                ImageIcon.COLOR,
 | 
					                ImageIcon.COLOR,
 | 
				
			||||||
                this,
 | 
					                this,
 | 
				
			||||||
                new LocTextKey("Set Color"),
 | 
					                (StringUtils.isNoneBlank(tooltipKeyPrefix)
 | 
				
			||||||
 | 
					                        ? new LocTextKey(tooltipKeyPrefix)
 | 
				
			||||||
 | 
					                        : DEFAULT_SELECT_TOOLTIP_KEY),
 | 
				
			||||||
                this::addColorSelection);
 | 
					                this::addColorSelection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final GridData actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false);
 | 
					        final GridData actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,9 @@ public final class MultiSelectionCombo extends Composite implements Selection {
 | 
				
			||||||
    private static final long serialVersionUID = -7787134114963647332L;
 | 
					    private static final long serialVersionUID = -7787134114963647332L;
 | 
				
			||||||
    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
					    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static final LocTextKey DEFAULT_ADD_TOOLTIP_KEY = new LocTextKey("sebserver.overall.add");
 | 
				
			||||||
 | 
					    private static final LocTextKey DEFAULT_REMOVE_TOOLTIP_KEY = new LocTextKey("sebserver.overall.remove");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final WidgetFactory widgetFactory;
 | 
					    private final WidgetFactory widgetFactory;
 | 
				
			||||||
    private final Combo combo;
 | 
					    private final Combo combo;
 | 
				
			||||||
    private final LocTextKey addTextKey;
 | 
					    private final LocTextKey addTextKey;
 | 
				
			||||||
| 
						 | 
					@ -64,10 +67,10 @@ public final class MultiSelectionCombo extends Composite implements Selection {
 | 
				
			||||||
        this.widgetFactory = widgetFactory;
 | 
					        this.widgetFactory = widgetFactory;
 | 
				
			||||||
        this.addTextKey = (locTextPrefix != null)
 | 
					        this.addTextKey = (locTextPrefix != null)
 | 
				
			||||||
                ? new LocTextKey(locTextPrefix + ".add")
 | 
					                ? new LocTextKey(locTextPrefix + ".add")
 | 
				
			||||||
                : new LocTextKey("sebserver.overall.add");
 | 
					                : DEFAULT_ADD_TOOLTIP_KEY;
 | 
				
			||||||
        this.removeTextKey = (locTextPrefix != null)
 | 
					        this.removeTextKey = (locTextPrefix != null)
 | 
				
			||||||
                ? new LocTextKey(locTextPrefix + ".remove")
 | 
					                ? new LocTextKey(locTextPrefix + ".remove")
 | 
				
			||||||
                : new LocTextKey("sebserver.overall.remove");
 | 
					                : DEFAULT_REMOVE_TOOLTIP_KEY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final GridLayout gridLayout = new GridLayout(2, false);
 | 
					        final GridLayout gridLayout = new GridLayout(2, false);
 | 
				
			||||||
        gridLayout.verticalSpacing = 1;
 | 
					        gridLayout.verticalSpacing = 1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,10 +36,11 @@ public final class ThresholdList extends Composite {
 | 
				
			||||||
    private static final long serialVersionUID = -2305091471607040280L;
 | 
					    private static final long serialVersionUID = -2305091471607040280L;
 | 
				
			||||||
    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
					    private static final int ACTION_COLUMN_WIDTH = 20;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final LocTextKey valueTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.value");
 | 
					    private static final String COLOR_SELECTION_TEXT_KEY = "sebserver.exam.indicator.thresholds.select.color";
 | 
				
			||||||
    private static final LocTextKey colorTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.color");
 | 
					    private static final LocTextKey VALUE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.value");
 | 
				
			||||||
    private static final LocTextKey addTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.add");
 | 
					    private static final LocTextKey COLOR_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.color");
 | 
				
			||||||
    private static final LocTextKey removeTextKey = new LocTextKey("sebserver.exam.indicator.thresholds.list.remove");
 | 
					    private static final LocTextKey ADD_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.add");
 | 
				
			||||||
 | 
					    private static final LocTextKey REMOVE_TEXT_KEY = new LocTextKey("sebserver.exam.indicator.thresholds.list.remove");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final WidgetFactory widgetFactory;
 | 
					    private final WidgetFactory widgetFactory;
 | 
				
			||||||
    private final List<Entry> thresholds = new ArrayList<>();
 | 
					    private final List<Entry> thresholds = new ArrayList<>();
 | 
				
			||||||
| 
						 | 
					@ -62,18 +63,24 @@ public final class ThresholdList extends Composite {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.addListener(SWT.Resize, this::adaptColumnWidth);
 | 
					        this.addListener(SWT.Resize, this::adaptColumnWidth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Label valueTitle = widgetFactory.labelLocalized(this, CustomVariant.TITLE_LABEL, valueTextKey);
 | 
					        final Label valueTitle = widgetFactory.labelLocalized(
 | 
				
			||||||
 | 
					                this,
 | 
				
			||||||
 | 
					                CustomVariant.TITLE_LABEL,
 | 
				
			||||||
 | 
					                VALUE_TEXT_KEY);
 | 
				
			||||||
        this.valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
					        this.valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
				
			||||||
        valueTitle.setLayoutData(this.valueCell);
 | 
					        valueTitle.setLayoutData(this.valueCell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Label colorTitle = widgetFactory.labelLocalized(this, CustomVariant.TITLE_LABEL, colorTextKey);
 | 
					        final Label colorTitle = widgetFactory.labelLocalized(
 | 
				
			||||||
 | 
					                this,
 | 
				
			||||||
 | 
					                CustomVariant.TITLE_LABEL,
 | 
				
			||||||
 | 
					                COLOR_TEXT_KEY);
 | 
				
			||||||
        this.colorCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
					        this.colorCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
				
			||||||
        colorTitle.setLayoutData(this.colorCell);
 | 
					        colorTitle.setLayoutData(this.colorCell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Label imageButton = widgetFactory.imageButton(
 | 
					        final Label imageButton = widgetFactory.imageButton(
 | 
				
			||||||
                ImageIcon.ADD_BOX,
 | 
					                ImageIcon.ADD_BOX,
 | 
				
			||||||
                this,
 | 
					                this,
 | 
				
			||||||
                addTextKey,
 | 
					                ADD_TEXT_KEY,
 | 
				
			||||||
                this::addThreshold);
 | 
					                this::addThreshold);
 | 
				
			||||||
        this.actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false);
 | 
					        this.actionCell = new GridData(SWT.LEFT, SWT.CENTER, true, false);
 | 
				
			||||||
        imageButton.setLayoutData(this.actionCell);
 | 
					        imageButton.setLayoutData(this.actionCell);
 | 
				
			||||||
| 
						 | 
					@ -120,7 +127,9 @@ public final class ThresholdList extends Composite {
 | 
				
			||||||
        final GridData valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
					        final GridData valueCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
				
			||||||
        valueInput.setLayoutData(valueCell);
 | 
					        valueInput.setLayoutData(valueCell);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final Selection selector = this.widgetFactory.selectionLocalized(Type.COLOR, this, null);
 | 
					        final Selection selector = this.widgetFactory.selectionLocalized(
 | 
				
			||||||
 | 
					                Type.COLOR, this, null, null, null,
 | 
				
			||||||
 | 
					                COLOR_SELECTION_TEXT_KEY);
 | 
				
			||||||
        final GridData selectorCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
					        final GridData selectorCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
				
			||||||
        selectorCell.horizontalIndent = 2;
 | 
					        selectorCell.horizontalIndent = 2;
 | 
				
			||||||
        selector.adaptToControl().setLayoutData(selectorCell);
 | 
					        selector.adaptToControl().setLayoutData(selectorCell);
 | 
				
			||||||
| 
						 | 
					@ -128,7 +137,7 @@ public final class ThresholdList extends Composite {
 | 
				
			||||||
        final Label imageButton = this.widgetFactory.imageButton(
 | 
					        final Label imageButton = this.widgetFactory.imageButton(
 | 
				
			||||||
                ImageIcon.REMOVE_BOX,
 | 
					                ImageIcon.REMOVE_BOX,
 | 
				
			||||||
                this,
 | 
					                this,
 | 
				
			||||||
                removeTextKey,
 | 
					                REMOVE_TEXT_KEY,
 | 
				
			||||||
                null);
 | 
					                null);
 | 
				
			||||||
        final GridData actionCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
					        final GridData actionCell = new GridData(SWT.FILL, SWT.CENTER, true, false);
 | 
				
			||||||
        imageButton.setLayoutData(actionCell);
 | 
					        imageButton.setLayoutData(actionCell);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -281,7 +281,8 @@ public class WidgetFactory {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Text textAreaInput(final Composite content) {
 | 
					    public Text textAreaInput(final Composite content) {
 | 
				
			||||||
        return new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI);
 | 
					        final Text textArea = new Text(content, SWT.LEFT | SWT.BORDER | SWT.MULTI);
 | 
				
			||||||
 | 
					        return textArea;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public Text textInput(final Composite content, final boolean password) {
 | 
					    public Text textInput(final Composite content, final boolean password) {
 | 
				
			||||||
| 
						 | 
					@ -477,7 +478,7 @@ public class WidgetFactory {
 | 
				
			||||||
                selection = new MultiSelectionCheckbox(parent);
 | 
					                selection = new MultiSelectionCheckbox(parent);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            case COLOR:
 | 
					            case COLOR:
 | 
				
			||||||
                selection = new ColorSelection(parent, this);
 | 
					                selection = new ColorSelection(parent, this, actionLocTextPrefix);
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            default:
 | 
					            default:
 | 
				
			||||||
                throw new IllegalArgumentException("Unsupported Selection.Type: " + type);
 | 
					                throw new IllegalArgumentException("Unsupported Selection.Type: " + type);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,12 +230,6 @@ public class PaginationServiceImpl implements PaginationService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Exam Table
 | 
					        // Exam Table
 | 
				
			||||||
        final Map<String, String> examTableMap = new HashMap<>();
 | 
					        final Map<String, String> examTableMap = new HashMap<>();
 | 
				
			||||||
        examTableMap.put(
 | 
					 | 
				
			||||||
                Domain.EXAM.ATTR_INSTITUTION_ID,
 | 
					 | 
				
			||||||
                ExamRecordDynamicSqlSupport.institutionId.name());
 | 
					 | 
				
			||||||
        examTableMap.put(
 | 
					 | 
				
			||||||
                Domain.EXAM.ATTR_LMS_SETUP_ID,
 | 
					 | 
				
			||||||
                ExamRecordDynamicSqlSupport.lmsSetupId.name());
 | 
					 | 
				
			||||||
        examTableMap.put(
 | 
					        examTableMap.put(
 | 
				
			||||||
                Domain.EXAM.ATTR_TYPE,
 | 
					                Domain.EXAM.ATTR_TYPE,
 | 
				
			||||||
                ExamRecordDynamicSqlSupport.type.name());
 | 
					                ExamRecordDynamicSqlSupport.type.name());
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,6 +210,7 @@ public class ConfigurationDAOImpl implements ConfigurationDAO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // with the current attribute values
 | 
					            // with the current attribute values
 | 
				
			||||||
            // TODO batch here for better performance
 | 
					            // TODO batch here for better performance
 | 
				
			||||||
 | 
					            // http://pretius.com/how-to-use-mybatis-effectively-perform-batch-db-operations/
 | 
				
			||||||
            allValues.stream()
 | 
					            allValues.stream()
 | 
				
			||||||
                    .map(oldValRec -> new ConfigurationValueRecord(
 | 
					                    .map(oldValRec -> new ConfigurationValueRecord(
 | 
				
			||||||
                            null,
 | 
					                            null,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
 | 
					import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
					import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationStatus;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationNode.ConfigurationType;
 | 
				
			||||||
| 
						 | 
					@ -44,6 +45,7 @@ import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationReco
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordMapper;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationRecordMapper;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordDynamicSqlSupport;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ConfigurationValueRecordMapper;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationAttributeRecord;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationNodeRecord;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationRecord;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationValueRecord;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.model.ConfigurationValueRecord;
 | 
				
			||||||
| 
						 | 
					@ -361,6 +363,8 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
 | 
				
			||||||
                    .build()
 | 
					                    .build()
 | 
				
			||||||
                    .execute()
 | 
					                    .execute()
 | 
				
			||||||
                    .stream()
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    // filter child attributes of tables. No default value for tables. Use templates for that
 | 
				
			||||||
 | 
					                    .filter(ConfigurationNodeDAOImpl::filterChildAttribute)
 | 
				
			||||||
                    .forEach(attrRec -> {
 | 
					                    .forEach(attrRec -> {
 | 
				
			||||||
                        final String value = templateValues.getOrDefault(
 | 
					                        final String value = templateValues.getOrDefault(
 | 
				
			||||||
                                attrRec.getId(),
 | 
					                                attrRec.getId(),
 | 
				
			||||||
| 
						 | 
					@ -379,6 +383,17 @@ public class ConfigurationNodeDAOImpl implements ConfigurationNodeDAO {
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static boolean filterChildAttribute(final ConfigurationAttributeRecord rec) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (rec.getParentId() == null) {
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return BooleanUtils.toBoolean(ConfigurationAttribute.getDependencyValue(
 | 
				
			||||||
 | 
					                ConfigurationAttribute.DEPENDENCY_CREATE_DEFAULT_VALUE,
 | 
				
			||||||
 | 
					                rec.getDependencies()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
     * Get values from template with configuration attribute id mapped to the value
 | 
					     * Get values from template with configuration attribute id mapped to the value
 | 
				
			||||||
     * returns empty list if no template available
 | 
					     * returns empty list if no template available
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,6 +28,7 @@ import org.springframework.stereotype.Component;
 | 
				
			||||||
import org.springframework.transaction.annotation.Transactional;
 | 
					import org.springframework.transaction.annotation.Transactional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationTableValues.TableValue;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
 | 
				
			||||||
| 
						 | 
					@ -293,7 +294,23 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
 | 
				
			||||||
                .flatMap(val -> attributeRecordById(val.attributeId))
 | 
					                .flatMap(val -> attributeRecordById(val.attributeId))
 | 
				
			||||||
                .map(attributeRecord -> {
 | 
					                .map(attributeRecord -> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    final Map<Long, ConfigurationAttributeRecord> attributeMap = this.configurationAttributeRecordMapper
 | 
					                    final String type = attributeRecord.getType();
 | 
				
			||||||
 | 
					                    if (AttributeType.TABLE.name().equals(type)) {
 | 
				
			||||||
 | 
					                        saveAsTable(value, attributeRecord);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        saveAsComposite(value);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return value;
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private void saveAsTable(
 | 
				
			||||||
 | 
					            final ConfigurationTableValues value,
 | 
				
			||||||
 | 
					            final ConfigurationAttributeRecord attributeRecord) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final Map<Long, ConfigurationAttributeRecord> attributeMap =
 | 
				
			||||||
 | 
					                this.configurationAttributeRecordMapper
 | 
				
			||||||
                        .selectByExample()
 | 
					                        .selectByExample()
 | 
				
			||||||
                        .where(
 | 
					                        .where(
 | 
				
			||||||
                                ConfigurationAttributeRecordDynamicSqlSupport.parentId,
 | 
					                                ConfigurationAttributeRecordDynamicSqlSupport.parentId,
 | 
				
			||||||
| 
						 | 
					@ -320,6 +337,7 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
 | 
				
			||||||
                .execute();
 | 
					                .execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // then add the new values
 | 
					        // then add the new values
 | 
				
			||||||
 | 
					        // TODO optimize with batching
 | 
				
			||||||
        for (final TableValue tableValue : value.values) {
 | 
					        for (final TableValue tableValue : value.values) {
 | 
				
			||||||
            final ConfigurationAttributeRecord columnAttr = attributeMap.get(tableValue.attributeId);
 | 
					            final ConfigurationAttributeRecord columnAttr = attributeMap.get(tableValue.attributeId);
 | 
				
			||||||
            final ConfigurationValueRecord valueRecord = new ConfigurationValueRecord(
 | 
					            final ConfigurationValueRecord valueRecord = new ConfigurationValueRecord(
 | 
				
			||||||
| 
						 | 
					@ -332,9 +350,51 @@ public class ConfigurationValueDAOImpl implements ConfigurationValueDAO {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.configurationValueRecordMapper.insert(valueRecord);
 | 
					            this.configurationValueRecordMapper.insert(valueRecord);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return value;
 | 
					    private void saveAsComposite(final ConfigurationTableValues value) {
 | 
				
			||||||
                });
 | 
					        // TODO optimize with batching
 | 
				
			||||||
 | 
					        for (final TableValue tableValue : value.values) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            final List<Long> valuePK = this.configurationValueRecordMapper.selectIdsByExample()
 | 
				
			||||||
 | 
					                    .where(
 | 
				
			||||||
 | 
					                            ConfigurationValueRecordDynamicSqlSupport.configurationId,
 | 
				
			||||||
 | 
					                            isEqualTo(value.configurationId))
 | 
				
			||||||
 | 
					                    .and(
 | 
				
			||||||
 | 
					                            ConfigurationValueRecordDynamicSqlSupport.configurationAttributeId,
 | 
				
			||||||
 | 
					                            isEqualTo(tableValue.attributeId))
 | 
				
			||||||
 | 
					                    .and(
 | 
				
			||||||
 | 
					                            ConfigurationValueRecordDynamicSqlSupport.listIndex,
 | 
				
			||||||
 | 
					                            isEqualTo(tableValue.listIndex))
 | 
				
			||||||
 | 
					                    .build()
 | 
				
			||||||
 | 
					                    .execute();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (valuePK != null && valuePK.size() > 1) {
 | 
				
			||||||
 | 
					                throw new IllegalStateException("Expected no more then one element");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (valuePK == null || valuePK.isEmpty()) {
 | 
				
			||||||
 | 
					                // insert
 | 
				
			||||||
 | 
					                this.configurationValueRecordMapper.insert(
 | 
				
			||||||
 | 
					                        new ConfigurationValueRecord(
 | 
				
			||||||
 | 
					                                null,
 | 
				
			||||||
 | 
					                                value.institutionId,
 | 
				
			||||||
 | 
					                                value.configurationId,
 | 
				
			||||||
 | 
					                                tableValue.attributeId,
 | 
				
			||||||
 | 
					                                tableValue.listIndex,
 | 
				
			||||||
 | 
					                                tableValue.value));
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                // update
 | 
				
			||||||
 | 
					                this.configurationValueRecordMapper.updateByPrimaryKey(
 | 
				
			||||||
 | 
					                        new ConfigurationValueRecord(
 | 
				
			||||||
 | 
					                                valuePK.iterator().next(),
 | 
				
			||||||
 | 
					                                value.institutionId,
 | 
				
			||||||
 | 
					                                value.configurationId,
 | 
				
			||||||
 | 
					                                tableValue.attributeId,
 | 
				
			||||||
 | 
					                                tableValue.listIndex,
 | 
				
			||||||
 | 
					                                tableValue.value));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private Result<ConfigurationAttributeRecord> attributeRecord(final ConfigurationValue value) {
 | 
					    private Result<ConfigurationAttributeRecord> attributeRecord(final ConfigurationValue value) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,39 +16,28 @@ import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
				
			||||||
public interface SebClientConfigService {
 | 
					public interface SebClientConfigService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static String SEB_CLIENT_CONFIG_EXAMPLE_XML =
 | 
					    static String SEB_CLIENT_CONFIG_EXAMPLE_XML =
 | 
				
			||||||
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n" +
 | 
					            "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\r\n"
 | 
				
			||||||
                    "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
 | 
					 | 
				
			||||||
                    +
 | 
					                    +
 | 
				
			||||||
                    "<plist version=\"1.0\">" +
 | 
					                    "<plist version=\"1.0\">\r\n" +
 | 
				
			||||||
                    "<dict>" +
 | 
					                    "  <dict>\r\n" +
 | 
				
			||||||
                    "<key>sebMode</key>" +
 | 
					                    "    <key>sebMode</key>\r\n" +
 | 
				
			||||||
                    "<integer>1</integer>" +
 | 
					                    "    <integer>1</integer>\r\n" +
 | 
				
			||||||
                    "<key>sebServerFallback</key>" +
 | 
					                    "    <key>sebServerFallback</key>\r\n" +
 | 
				
			||||||
                    "<true />" +
 | 
					                    "    <true />\r\n" +
 | 
				
			||||||
                    "<key>sebServerURL</key>" +
 | 
					                    "    <key>sebServerURL</key>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					                    "    <string>%s</string>\r\n" +
 | 
				
			||||||
                    "<key>sebServerConfiguration</key>" +
 | 
					                    "    <key>sebServerConfiguration</key>\r\n" +
 | 
				
			||||||
                    "<array>" +
 | 
					                    "    <dict>\r\n" +
 | 
				
			||||||
                    "<dict>" +
 | 
					                    "        <key>institution</key>\r\n" +
 | 
				
			||||||
                    "<key>institution</key>" +
 | 
					                    "        <string>%s</string>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					                    "        <key>clientName</key>\r\n" +
 | 
				
			||||||
                    "<key>clientName</key>" +
 | 
					                    "        <string>%s</string>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					                    "        <key>clientSecret</key>\r\n" +
 | 
				
			||||||
                    "<key>clientSecret</key>" +
 | 
					                    "        <string>%s</string>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					                    "        <key>apiDiscovery</key>\r\n" +
 | 
				
			||||||
                    "<key>accessTokenEndpoint</key>" +
 | 
					                    "        <string>%s</string>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					                    "    </dict>\r\n" +
 | 
				
			||||||
                    "<key>handshakeEndpoint</key>" +
 | 
					                    "  </dict>\r\n" +
 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					 | 
				
			||||||
                    "<key>examConfigEndpoint</key>" +
 | 
					 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					 | 
				
			||||||
                    "<key>pingEndpoint</key>" +
 | 
					 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					 | 
				
			||||||
                    "<key>eventEndpoint</key>" +
 | 
					 | 
				
			||||||
                    "<string>%s</string>" +
 | 
					 | 
				
			||||||
                    "</dict>" +
 | 
					 | 
				
			||||||
                    "</array>" +
 | 
					 | 
				
			||||||
                    "</dict>" +
 | 
					 | 
				
			||||||
                    "</plist>";
 | 
					                    "</plist>";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boolean hasSebClientConfigurationForInstitution(Long institutionId);
 | 
					    boolean hasSebClientConfigurationForInstitution(Long institutionId);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,6 @@ import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
import org.springframework.stereotype.Service;
 | 
					import org.springframework.stereotype.Service;
 | 
				
			||||||
import org.springframework.web.util.UriComponentsBuilder;
 | 
					import org.springframework.web.util.UriComponentsBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.API;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
 | 
					import ch.ethz.seb.sebserver.gbl.model.institution.Institution;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
 | 
					import ch.ethz.seb.sebserver.gbl.model.sebconfig.SebClientConfig;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
				
			||||||
| 
						 | 
					@ -54,7 +53,6 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
 | 
				
			||||||
    private final String httpScheme;
 | 
					    private final String httpScheme;
 | 
				
			||||||
    private final String serverAddress;
 | 
					    private final String serverAddress;
 | 
				
			||||||
    private final String serverPort;
 | 
					    private final String serverPort;
 | 
				
			||||||
    private final String sebClientAPIEndpoint;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected SebClientConfigServiceImpl(
 | 
					    protected SebClientConfigServiceImpl(
 | 
				
			||||||
            final InstitutionDAO institutionDAO,
 | 
					            final InstitutionDAO institutionDAO,
 | 
				
			||||||
| 
						 | 
					@ -64,8 +62,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
 | 
				
			||||||
            final ZipService zipService,
 | 
					            final ZipService zipService,
 | 
				
			||||||
            @Value("${sebserver.webservice.http.scheme}") final String httpScheme,
 | 
					            @Value("${sebserver.webservice.http.scheme}") final String httpScheme,
 | 
				
			||||||
            @Value("${server.address}") final String serverAddress,
 | 
					            @Value("${server.address}") final String serverAddress,
 | 
				
			||||||
            @Value("${server.port}") final String serverPort,
 | 
					            @Value("${server.port}") final String serverPort) {
 | 
				
			||||||
            @Value("${sebserver.webservice.api.exam.endpoint}") final String sebClientAPIEndpoint) {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.institutionDAO = institutionDAO;
 | 
					        this.institutionDAO = institutionDAO;
 | 
				
			||||||
        this.sebClientConfigDAO = sebClientConfigDAO;
 | 
					        this.sebClientConfigDAO = sebClientConfigDAO;
 | 
				
			||||||
| 
						 | 
					@ -75,7 +72,6 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
 | 
				
			||||||
        this.httpScheme = httpScheme;
 | 
					        this.httpScheme = httpScheme;
 | 
				
			||||||
        this.serverAddress = serverAddress;
 | 
					        this.serverAddress = serverAddress;
 | 
				
			||||||
        this.serverPort = serverPort;
 | 
					        this.serverPort = serverPort;
 | 
				
			||||||
        this.sebClientAPIEndpoint = sebClientAPIEndpoint;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					@ -136,11 +132,7 @@ public class SebClientConfigServiceImpl implements SebClientConfigService {
 | 
				
			||||||
                String.valueOf(config.institutionId),
 | 
					                String.valueOf(config.institutionId),
 | 
				
			||||||
                plainClientId,
 | 
					                plainClientId,
 | 
				
			||||||
                plainClientSecret,
 | 
					                plainClientSecret,
 | 
				
			||||||
                API.OAUTH_TOKEN_ENDPOINT,
 | 
					                "TODO:/exam-api/discovery");
 | 
				
			||||||
                this.sebClientAPIEndpoint + API.EXAM_API_HANDSHAKE_ENDPOINT,
 | 
					 | 
				
			||||||
                this.sebClientAPIEndpoint + API.EXAM_API_CONFIGURATION_REQUEST_ENDPOINT,
 | 
					 | 
				
			||||||
                this.sebClientAPIEndpoint + API.EXAM_API_PING_ENDPOINT,
 | 
					 | 
				
			||||||
                this.sebClientAPIEndpoint + API.EXAM_API_EVENT_ENDPOINT);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        PipedOutputStream pOut = null;
 | 
					        PipedOutputStream pOut = null;
 | 
				
			||||||
        PipedInputStream pIn = null;
 | 
					        PipedInputStream pIn = null;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,9 +27,9 @@ import org.springframework.web.bind.annotation.RestController;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.API;
 | 
					import ch.ethz.seb.sebserver.gbl.api.API;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage;
 | 
					import ch.ethz.seb.sebserver.gbl.api.APIMessage;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
 | 
					import ch.ethz.seb.sebserver.gbl.api.APIMessage.APIMessageException;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
 | 
					import ch.ethz.seb.sebserver.gbl.api.POSTMapper;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.api.authorization.PrivilegeType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Domain.EXAM;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Page;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Page;
 | 
				
			||||||
| 
						 | 
					@ -140,11 +140,16 @@ public class ExamAdministrationController extends ActivatableEntityController<Ex
 | 
				
			||||||
                Collections.reverse(exams);
 | 
					                Collections.reverse(exams);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            final int start = (pageNum - 1) * pSize;
 | 
				
			||||||
 | 
					            int end = start + pageSize;
 | 
				
			||||||
 | 
					            if (exams.size() < end) {
 | 
				
			||||||
 | 
					                end = exams.size();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return new Page<>(
 | 
					            return new Page<>(
 | 
				
			||||||
                    exams.size() / pSize,
 | 
					                    exams.size() / pSize,
 | 
				
			||||||
                    pageNum,
 | 
					                    pageNum,
 | 
				
			||||||
                    sort,
 | 
					                    sort,
 | 
				
			||||||
                    exams.subList(pageNum * pSize, pageNum * pSize + pSize));
 | 
					                    exams.subList(start, end));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,7 @@ server.servlet.context-path=/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
spring.datasource.initialize=true
 | 
					spring.datasource.initialize=true
 | 
				
			||||||
spring.datasource.initialization-mode=always
 | 
					spring.datasource.initialization-mode=always
 | 
				
			||||||
spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false&createDatabaseIfNotExist=true&default-character-set=utf8mb4
 | 
					spring.datasource.url=jdbc:mariadb://localhost:6603/SEBServer?useSSL=false
 | 
				
			||||||
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
 | 
					spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
 | 
				
			||||||
spring.datasource.platform=dev
 | 
					spring.datasource.platform=dev
 | 
				
			||||||
spring.datasource.hikari.max-lifetime=600000
 | 
					spring.datasource.hikari.max-lifetime=600000
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,6 +23,7 @@ sebserver.overall.status.inactive=Inactive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sebserver.overall.action.add=Add;
 | 
					sebserver.overall.action.add=Add;
 | 
				
			||||||
sebserver.overall.action.remove=Remove
 | 
					sebserver.overall.action.remove=Remove
 | 
				
			||||||
 | 
					sebserver.overall.action.select=Please Select
 | 
				
			||||||
 | 
					
 | 
				
			||||||
################################
 | 
					################################
 | 
				
			||||||
# Form validation and messages
 | 
					# Form validation and messages
 | 
				
			||||||
| 
						 | 
					@ -265,6 +266,7 @@ sebserver.exam.form.endtime=End Time
 | 
				
			||||||
sebserver.exam.form.status=Status
 | 
					sebserver.exam.form.status=Status
 | 
				
			||||||
sebserver.exam.form.type=Exam Type
 | 
					sebserver.exam.form.type=Exam Type
 | 
				
			||||||
sebserver.exam.form.supporter=Exam Supporter
 | 
					sebserver.exam.form.supporter=Exam Supporter
 | 
				
			||||||
 | 
					sebserver.exam.form.supporter.add=Add as supporter for this exam
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sebserver.exam.type.UNDEFINED=Not Defined
 | 
					sebserver.exam.type.UNDEFINED=Not Defined
 | 
				
			||||||
sebserver.exam.type.MANAGED=Managed
 | 
					sebserver.exam.type.MANAGED=Managed
 | 
				
			||||||
| 
						 | 
					@ -319,7 +321,9 @@ sebserver.exam.indicator.form.exam=Exam
 | 
				
			||||||
sebserver.exam.indicator.form.name=Name
 | 
					sebserver.exam.indicator.form.name=Name
 | 
				
			||||||
sebserver.exam.indicator.form.type=Type
 | 
					sebserver.exam.indicator.form.type=Type
 | 
				
			||||||
sebserver.exam.indicator.form.color=Default Color
 | 
					sebserver.exam.indicator.form.color=Default Color
 | 
				
			||||||
 | 
					sebserver.exam.indicator.form.color.action=Please select a color 
 | 
				
			||||||
sebserver.exam.indicator.form.thresholds=Thresholds
 | 
					sebserver.exam.indicator.form.thresholds=Thresholds
 | 
				
			||||||
 | 
					sebserver.exam.indicator.thresholds.select.color=Please select a color 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sebserver.exam.indicator.thresholds.list.title=Thresholds
 | 
					sebserver.exam.indicator.thresholds.list.title=Thresholds
 | 
				
			||||||
sebserver.exam.indicator.thresholds.list.value=Value
 | 
					sebserver.exam.indicator.thresholds.list.value=Value
 | 
				
			||||||
| 
						 | 
					@ -570,7 +574,7 @@ sebserver.examconfig.props.label.allowSwitchToApplications=Allow switching to th
 | 
				
			||||||
sebserver.examconfig.props.label.allowFlashFullscreen=Allow Flash to switch to fullscreen mode (Mac)
 | 
					sebserver.examconfig.props.label.allowFlashFullscreen=Allow Flash to switch to fullscreen mode (Mac)
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses.row.title=Permitted Processes
 | 
					sebserver.examconfig.props.label.permittedProcesses.row.title=Permitted Processes
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses=Permitted Processes
 | 
					sebserver.examconfig.props.label.permittedProcesses=Permitted Processes
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses.active=Activity 
 | 
					sebserver.examconfig.props.label.permittedProcesses.active=Active 
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses.os=OS
 | 
					sebserver.examconfig.props.label.permittedProcesses.os=OS
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses.os.0=Win
 | 
					sebserver.examconfig.props.label.permittedProcesses.os.0=Win
 | 
				
			||||||
sebserver.examconfig.props.label.permittedProcesses.os.1=OS X
 | 
					sebserver.examconfig.props.label.permittedProcesses.os.1=OS X
 | 
				
			||||||
| 
						 | 
					@ -594,7 +598,7 @@ sebserver.examconfig.props.label.permittedProcesses.strongKill=Force quit (risk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.row.title=Prohibited Processes
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.row.title=Prohibited Processes
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses=Prohibited Processes
 | 
					sebserver.examconfig.props.label.prohibitedProcesses=Prohibited Processes
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.active=Activity 
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.active=Active 
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.os=OS
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.os=OS
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.os.0=Win
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.os.0=Win
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.os.1=OS X
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.os.1=OS X
 | 
				
			||||||
| 
						 | 
					@ -604,16 +608,80 @@ sebserver.examconfig.props.label.prohibitedProcesses.originalName=Original Name
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.identifier=Identifier
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.identifier=Identifier
 | 
				
			||||||
sebserver.examconfig.props.label.prohibitedProcesses.strongKill=Force quit (risk of data loss)
 | 
					sebserver.examconfig.props.label.prohibitedProcesses.strongKill=Force quit (risk of data loss)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.group.urlFilter=Fitler
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterEnable=Activate URL Filtering
 | 
					sebserver.examconfig.props.label.URLFilterEnable=Activate URL Filtering
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterEnableContentFilter=Filter also embedded content
 | 
					sebserver.examconfig.props.label.URLFilterEnableContentFilter=Filter also embedded content
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules=Filter
 | 
					sebserver.examconfig.props.label.URLFilterRules=Filter
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.active=Activity
 | 
					sebserver.examconfig.props.label.URLFilterRules.row.title=URL Filter
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.URLFilterRules.active=Active
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.regex=Regex
 | 
					sebserver.examconfig.props.label.URLFilterRules.regex=Regex
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.expression=Expression
 | 
					sebserver.examconfig.props.label.URLFilterRules.expression=Expression
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.action=Action
 | 
					sebserver.examconfig.props.label.URLFilterRules.action=Action
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.action.0=Block
 | 
					sebserver.examconfig.props.label.URLFilterRules.action.0=Block
 | 
				
			||||||
sebserver.examconfig.props.label.URLFilterRules.action.1=Allow
 | 
					sebserver.examconfig.props.label.URLFilterRules.action.1=Allow
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.group.proxies=Proxies
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxySettingsPolicy=proxy settings policy
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxySettingsPolicy.0=Use system proxy setting
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxySettingsPolicy.0.tooltip=System proxy settings of the exam client computer are used
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxySettingsPolicy.1=Use SEB proxy settings
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxySettingsPolicy.1.tooltip=Proxy settings provided in these SEB settings are used
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxies=Double-click a protocol to configure:
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.ExcludeSimpleHostnames=Exclude simple hostnames
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.ExceptionsList=Bypass proxy settings for these hosts and domains
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.ExceptionsList.tooltip=Separate hosts / domains with comma
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPPassive=Use Passive FTP Mode (PASV)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxies.active=Active
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.proxies.TABLE_ENTRY=Protocol
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.autoDiscovery=Auto Proxy Discovery
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.AutoDiscoveryEnabled=Auto discovery enabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.autoConfiguration=Automatic Proxy Configuration
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.AutoConfigurationEnabled=Auto configuration enabeld
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.AutoConfigurationURL=Proxy configuration file URL
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.AutoConfigurationJavaScript=Proxy configuration JavaScript
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.http=Web Proxy (HTTP)
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPEnable=Web proxy eneabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPProxy=Web proxy server
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPPort=Web proxy port
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPRequiresPassword=Proxy server requires password
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPUsername=Username
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPPassword=Password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.https=Secure Web Proxy (HTTPS)
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSEnable=Secure web proxy eneabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSProxy=Secure web proxy server
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSPort=Secure web proxy port
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSRequiresPassword=Proxy server requires password
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSUsername=Username
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.HTTPSPassword=Password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.ftp=FTP Proxy
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPEnable=FTP proxy eneabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPProxy=FTP proxy server
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPPort=FTP proxy port
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPRequiresPassword=Proxy server requires password
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPUsername=Username
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.FTPPassword=Password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.socks=SOCKS Proxy
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSEnable=SOCKS proxy eneabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSProxy=SOCKS proxy server
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSPort=SOCKS proxy port
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSRequiresPassword=Proxy server requires password
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSUsername=Username
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.SOCKSPassword=Password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.rtsp=Streaming Proxy (RTSP)
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPEnable=RTSP proxy eneabled
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPProxy=RTSP proxy server
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPPort=RTSP proxy port
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPRequiresPassword=Proxy server requires password
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPUsername=Username
 | 
				
			||||||
 | 
					sebserver.examconfig.props.label.RTSPPassword=Password
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
sebserver.examconfig.props.group.servicePolicy=SEB Service policy
 | 
					sebserver.examconfig.props.group.servicePolicy=SEB Service policy
 | 
				
			||||||
sebserver.examconfig.props.label.sebServicePolicy.0=allow to run SEB without service
 | 
					sebserver.examconfig.props.label.sebServicePolicy.0=allow to run SEB without service
 | 
				
			||||||
sebserver.examconfig.props.label.sebServicePolicy.1=display warning when service is not running
 | 
					sebserver.examconfig.props.label.sebServicePolicy.1=display warning when service is not running
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
-- MySQL Script generated by MySQL Workbench
 | 
					-- MySQL Script generated by MySQL Workbench
 | 
				
			||||||
-- Fri May 24 11:57:07 2019
 | 
					-- Wed May 29 15:30:50 2019
 | 
				
			||||||
-- Model: New Model    Version: 1.0
 | 
					-- Model: New Model    Version: 1.0
 | 
				
			||||||
-- MySQL Workbench Forward Engineering
 | 
					-- MySQL Workbench Forward Engineering
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,13 +10,20 @@ SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Schema SEBServer
 | 
					-- Schema SEBServer
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
 | 
					DROP SCHEMA IF EXISTS `SEBServer` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `institution`
 | 
					-- Schema SEBServer
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `institution` ;
 | 
					CREATE SCHEMA IF NOT EXISTS `SEBServer` DEFAULT CHARACTER SET utf8mb4 ;
 | 
				
			||||||
 | 
					USE `SEBServer` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `institution` (
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
 | 
					-- Table `SEBServer`.`institution`
 | 
				
			||||||
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
 | 
					DROP TABLE IF EXISTS `SEBServer`.`institution` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`institution` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `name` VARCHAR(255) NOT NULL,
 | 
					  `name` VARCHAR(255) NOT NULL,
 | 
				
			||||||
  `url_suffix` VARCHAR(45) NULL,
 | 
					  `url_suffix` VARCHAR(45) NULL,
 | 
				
			||||||
| 
						 | 
					@ -29,11 +36,11 @@ CREATE TABLE IF NOT EXISTS `institution` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `lms_setup`
 | 
					-- Table `SEBServer`.`lms_setup`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `lms_setup` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`lms_setup` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `lms_setup` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`lms_setup` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `name` VARCHAR(255) NOT NULL,
 | 
					  `name` VARCHAR(255) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -47,18 +54,18 @@ CREATE TABLE IF NOT EXISTS `lms_setup` (
 | 
				
			||||||
  INDEX `setupInstitutionRef_idx` (`institution_id` ASC),
 | 
					  INDEX `setupInstitutionRef_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `setupInstitutionRef`
 | 
					  CONSTRAINT `setupInstitutionRef`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `exam`
 | 
					-- Table `SEBServer`.`exam`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `exam` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`exam` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `exam` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`exam` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `lms_setup_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `lms_setup_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -74,23 +81,23 @@ CREATE TABLE IF NOT EXISTS `exam` (
 | 
				
			||||||
  INDEX `institution_key_idx` (`institution_id` ASC),
 | 
					  INDEX `institution_key_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `examLmsSetupRef`
 | 
					  CONSTRAINT `examLmsSetupRef`
 | 
				
			||||||
    FOREIGN KEY (`lms_setup_id`)
 | 
					    FOREIGN KEY (`lms_setup_id`)
 | 
				
			||||||
    REFERENCES `lms_setup` (`id`)
 | 
					    REFERENCES `SEBServer`.`lms_setup` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `examInstitutionRef`
 | 
					  CONSTRAINT `examInstitutionRef`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `client_connection`
 | 
					-- Table `SEBServer`.`client_connection`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `client_connection` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`client_connection` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `client_connection` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`client_connection` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `exam_id` BIGINT UNSIGNED NULL,
 | 
					  `exam_id` BIGINT UNSIGNED NULL,
 | 
				
			||||||
  `status` VARCHAR(45) NOT NULL,
 | 
					  `status` VARCHAR(45) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -103,18 +110,18 @@ CREATE TABLE IF NOT EXISTS `client_connection` (
 | 
				
			||||||
  INDEX `connection_exam_ref_idx` (`exam_id` ASC),
 | 
					  INDEX `connection_exam_ref_idx` (`exam_id` ASC),
 | 
				
			||||||
  CONSTRAINT `clientConnectionExamRef`
 | 
					  CONSTRAINT `clientConnectionExamRef`
 | 
				
			||||||
    FOREIGN KEY (`exam_id`)
 | 
					    FOREIGN KEY (`exam_id`)
 | 
				
			||||||
    REFERENCES `exam` (`id`)
 | 
					    REFERENCES `SEBServer`.`exam` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `client_event`
 | 
					-- Table `SEBServer`.`client_event`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `client_event` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`client_event` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `client_event` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`client_event` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `connection_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `connection_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `user_identifier` VARCHAR(255) NOT NULL,
 | 
					  `user_identifier` VARCHAR(255) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -126,18 +133,18 @@ CREATE TABLE IF NOT EXISTS `client_event` (
 | 
				
			||||||
  INDEX `eventConnectionRef_idx` (`connection_id` ASC),
 | 
					  INDEX `eventConnectionRef_idx` (`connection_id` ASC),
 | 
				
			||||||
  CONSTRAINT `eventConnectionRef`
 | 
					  CONSTRAINT `eventConnectionRef`
 | 
				
			||||||
    FOREIGN KEY (`connection_id`)
 | 
					    FOREIGN KEY (`connection_id`)
 | 
				
			||||||
    REFERENCES `client_connection` (`id`)
 | 
					    REFERENCES `SEBServer`.`client_connection` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `indicator`
 | 
					-- Table `SEBServer`.`indicator`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `indicator` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`indicator` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `indicator` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`indicator` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `exam_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `exam_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `type` VARCHAR(45) NOT NULL,
 | 
					  `type` VARCHAR(45) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -147,18 +154,18 @@ CREATE TABLE IF NOT EXISTS `indicator` (
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  CONSTRAINT `exam_ref`
 | 
					  CONSTRAINT `exam_ref`
 | 
				
			||||||
    FOREIGN KEY (`exam_id`)
 | 
					    FOREIGN KEY (`exam_id`)
 | 
				
			||||||
    REFERENCES `exam` (`id`)
 | 
					    REFERENCES `SEBServer`.`exam` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `configuration_node`
 | 
					-- Table `SEBServer`.`configuration_node`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `configuration_node` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`configuration_node` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `configuration_node` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_node` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `template_id` BIGINT UNSIGNED NULL,
 | 
					  `template_id` BIGINT UNSIGNED NULL,
 | 
				
			||||||
| 
						 | 
					@ -171,18 +178,18 @@ CREATE TABLE IF NOT EXISTS `configuration_node` (
 | 
				
			||||||
  INDEX `configurationInstitutionRef_idx` (`institution_id` ASC),
 | 
					  INDEX `configurationInstitutionRef_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `configurationInstitutionRef`
 | 
					  CONSTRAINT `configurationInstitutionRef`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `configuration`
 | 
					-- Table `SEBServer`.`configuration`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `configuration` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`configuration` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `configuration` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `configuration_node_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `configuration_node_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -194,23 +201,23 @@ CREATE TABLE IF NOT EXISTS `configuration` (
 | 
				
			||||||
  INDEX `config_institution_ref_idx` (`institution_id` ASC),
 | 
					  INDEX `config_institution_ref_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `configuration_node_ref`
 | 
					  CONSTRAINT `configuration_node_ref`
 | 
				
			||||||
    FOREIGN KEY (`configuration_node_id`)
 | 
					    FOREIGN KEY (`configuration_node_id`)
 | 
				
			||||||
    REFERENCES `configuration_node` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration_node` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `config_institution_ref`
 | 
					  CONSTRAINT `config_institution_ref`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `configuration_attribute`
 | 
					-- Table `SEBServer`.`configuration_attribute`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `configuration_attribute` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`configuration_attribute` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `configuration_attribute` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_attribute` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `name` VARCHAR(45) NOT NULL,
 | 
					  `name` VARCHAR(45) NOT NULL,
 | 
				
			||||||
  `type` VARCHAR(45) NOT NULL,
 | 
					  `type` VARCHAR(45) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -223,52 +230,53 @@ CREATE TABLE IF NOT EXISTS `configuration_attribute` (
 | 
				
			||||||
  INDEX `parent_ref_idx` (`parent_id` ASC),
 | 
					  INDEX `parent_ref_idx` (`parent_id` ASC),
 | 
				
			||||||
  CONSTRAINT `parent_ref`
 | 
					  CONSTRAINT `parent_ref`
 | 
				
			||||||
    FOREIGN KEY (`parent_id`)
 | 
					    FOREIGN KEY (`parent_id`)
 | 
				
			||||||
    REFERENCES `configuration_attribute` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration_attribute` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `configuration_value`
 | 
					-- Table `SEBServer`.`configuration_value`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `configuration_value` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`configuration_value` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `configuration_value` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`configuration_value` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `configuration_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `configuration_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `configuration_attribute_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `configuration_attribute_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `list_index` INT NOT NULL DEFAULT 0,
 | 
					  `list_index` INT NOT NULL DEFAULT 0,
 | 
				
			||||||
  `value` VARCHAR(20000) NULL,
 | 
					  `value` VARCHAR(16000) NULL,
 | 
				
			||||||
 | 
					  `configuration_valuecol` VARCHAR(45) NULL,
 | 
				
			||||||
  PRIMARY KEY (`id`),
 | 
					  PRIMARY KEY (`id`),
 | 
				
			||||||
  INDEX `configuration_value_ref_idx` (`configuration_id` ASC),
 | 
					  INDEX `configuration_value_ref_idx` (`configuration_id` ASC),
 | 
				
			||||||
  INDEX `configuration_attribute_ref_idx` (`configuration_attribute_id` ASC),
 | 
					  INDEX `configuration_attribute_ref_idx` (`configuration_attribute_id` ASC),
 | 
				
			||||||
  INDEX `configuration_value_institution_ref_idx` (`institution_id` ASC),
 | 
					  INDEX `configuration_value_institution_ref_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `configuration_ref`
 | 
					  CONSTRAINT `configuration_ref`
 | 
				
			||||||
    FOREIGN KEY (`configuration_id`)
 | 
					    FOREIGN KEY (`configuration_id`)
 | 
				
			||||||
    REFERENCES `configuration` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `configuration_value_attribute_ref`
 | 
					  CONSTRAINT `configuration_value_attribute_ref`
 | 
				
			||||||
    FOREIGN KEY (`configuration_attribute_id`)
 | 
					    FOREIGN KEY (`configuration_attribute_id`)
 | 
				
			||||||
    REFERENCES `configuration_attribute` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration_attribute` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `configuration_value_institution_ref`
 | 
					  CONSTRAINT `configuration_value_institution_ref`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `view`
 | 
					-- Table `SEBServer`.`view`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `view` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`view` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `view` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`view` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `name` VARCHAR(255) NULL,
 | 
					  `name` VARCHAR(255) NULL,
 | 
				
			||||||
  `columns` INT NOT NULL,
 | 
					  `columns` INT NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -278,11 +286,11 @@ CREATE TABLE IF NOT EXISTS `view` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `orientation`
 | 
					-- Table `SEBServer`.`orientation`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `orientation` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`orientation` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `orientation` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`orientation` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `config_attribute_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `config_attribute_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `template_id` BIGINT UNSIGNED NULL,
 | 
					  `template_id` BIGINT UNSIGNED NULL,
 | 
				
			||||||
| 
						 | 
					@ -298,23 +306,23 @@ CREATE TABLE IF NOT EXISTS `orientation` (
 | 
				
			||||||
  INDEX `orientation_view_ref_idx` (`view_id` ASC),
 | 
					  INDEX `orientation_view_ref_idx` (`view_id` ASC),
 | 
				
			||||||
  CONSTRAINT `config_attribute_orientation_ref`
 | 
					  CONSTRAINT `config_attribute_orientation_ref`
 | 
				
			||||||
    FOREIGN KEY (`config_attribute_id`)
 | 
					    FOREIGN KEY (`config_attribute_id`)
 | 
				
			||||||
    REFERENCES `configuration_attribute` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration_attribute` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `orientation_view_ref`
 | 
					  CONSTRAINT `orientation_view_ref`
 | 
				
			||||||
    FOREIGN KEY (`view_id`)
 | 
					    FOREIGN KEY (`view_id`)
 | 
				
			||||||
    REFERENCES `view` (`id`)
 | 
					    REFERENCES `SEBServer`.`view` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `exam_configuration_map`
 | 
					-- Table `SEBServer`.`exam_configuration_map`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `exam_configuration_map` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`exam_configuration_map` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `exam_configuration_map` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`exam_configuration_map` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `exam_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `exam_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -327,28 +335,28 @@ CREATE TABLE IF NOT EXISTS `exam_configuration_map` (
 | 
				
			||||||
  INDEX `exam_config_institution_ref_idx` (`institution_id` ASC),
 | 
					  INDEX `exam_config_institution_ref_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `exam_map_ref`
 | 
					  CONSTRAINT `exam_map_ref`
 | 
				
			||||||
    FOREIGN KEY (`exam_id`)
 | 
					    FOREIGN KEY (`exam_id`)
 | 
				
			||||||
    REFERENCES `exam` (`id`)
 | 
					    REFERENCES `SEBServer`.`exam` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `configuration_map_ref`
 | 
					  CONSTRAINT `configuration_map_ref`
 | 
				
			||||||
    FOREIGN KEY (`configuration_node_id`)
 | 
					    FOREIGN KEY (`configuration_node_id`)
 | 
				
			||||||
    REFERENCES `configuration_node` (`id`)
 | 
					    REFERENCES `SEBServer`.`configuration_node` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION,
 | 
					    ON UPDATE NO ACTION,
 | 
				
			||||||
  CONSTRAINT `exam_config_institution_ref`
 | 
					  CONSTRAINT `exam_config_institution_ref`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `user`
 | 
					-- Table `SEBServer`.`user`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `user` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`user` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `user` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`user` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `uuid` VARCHAR(255) NOT NULL,
 | 
					  `uuid` VARCHAR(255) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -363,18 +371,18 @@ CREATE TABLE IF NOT EXISTS `user` (
 | 
				
			||||||
  INDEX `institutionRef_idx` (`institution_id` ASC),
 | 
					  INDEX `institutionRef_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `userInstitutionRef`
 | 
					  CONSTRAINT `userInstitutionRef`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `user_role`
 | 
					-- Table `SEBServer`.`user_role`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `user_role` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`user_role` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `user_role` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`user_role` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `user_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `user_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `role_name` VARCHAR(45) NOT NULL,
 | 
					  `role_name` VARCHAR(45) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -382,18 +390,18 @@ CREATE TABLE IF NOT EXISTS `user_role` (
 | 
				
			||||||
  INDEX `user_ref_idx` (`user_id` ASC),
 | 
					  INDEX `user_ref_idx` (`user_id` ASC),
 | 
				
			||||||
  CONSTRAINT `user_ref`
 | 
					  CONSTRAINT `user_ref`
 | 
				
			||||||
    FOREIGN KEY (`user_id`)
 | 
					    FOREIGN KEY (`user_id`)
 | 
				
			||||||
    REFERENCES `user` (`id`)
 | 
					    REFERENCES `SEBServer`.`user` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `oauth_access_token`
 | 
					-- Table `SEBServer`.`oauth_access_token`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `oauth_access_token` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`oauth_access_token` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `oauth_access_token` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`oauth_access_token` (
 | 
				
			||||||
  `token_id` VARCHAR(255) NULL,
 | 
					  `token_id` VARCHAR(255) NULL,
 | 
				
			||||||
  `token` BLOB NULL,
 | 
					  `token` BLOB NULL,
 | 
				
			||||||
  `authentication_id` VARCHAR(255) NULL,
 | 
					  `authentication_id` VARCHAR(255) NULL,
 | 
				
			||||||
| 
						 | 
					@ -405,11 +413,11 @@ CREATE TABLE IF NOT EXISTS `oauth_access_token` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `oauth_refresh_token`
 | 
					-- Table `SEBServer`.`oauth_refresh_token`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `oauth_refresh_token` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`oauth_refresh_token` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `oauth_refresh_token` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`oauth_refresh_token` (
 | 
				
			||||||
  `token_id` VARCHAR(255) NULL,
 | 
					  `token_id` VARCHAR(255) NULL,
 | 
				
			||||||
  `token` BLOB NULL,
 | 
					  `token` BLOB NULL,
 | 
				
			||||||
  `authentication` BLOB NULL)
 | 
					  `authentication` BLOB NULL)
 | 
				
			||||||
| 
						 | 
					@ -417,11 +425,11 @@ CREATE TABLE IF NOT EXISTS `oauth_refresh_token` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `threshold`
 | 
					-- Table `SEBServer`.`threshold`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `threshold` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`threshold` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `threshold` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`threshold` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `indicator_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `indicator_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `value` DECIMAL(10,4) NOT NULL,
 | 
					  `value` DECIMAL(10,4) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -430,18 +438,18 @@ CREATE TABLE IF NOT EXISTS `threshold` (
 | 
				
			||||||
  INDEX `indicator_threshold_id_idx` (`indicator_id` ASC),
 | 
					  INDEX `indicator_threshold_id_idx` (`indicator_id` ASC),
 | 
				
			||||||
  CONSTRAINT `indicator_threshold_id`
 | 
					  CONSTRAINT `indicator_threshold_id`
 | 
				
			||||||
    FOREIGN KEY (`indicator_id`)
 | 
					    FOREIGN KEY (`indicator_id`)
 | 
				
			||||||
    REFERENCES `indicator` (`id`)
 | 
					    REFERENCES `SEBServer`.`indicator` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `user_activity_log`
 | 
					-- Table `SEBServer`.`user_activity_log`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `user_activity_log` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`user_activity_log` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `user_activity_log` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`user_activity_log` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `user_uuid` VARCHAR(255) NOT NULL,
 | 
					  `user_uuid` VARCHAR(255) NOT NULL,
 | 
				
			||||||
  `timestamp` BIGINT NOT NULL,
 | 
					  `timestamp` BIGINT NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -454,11 +462,11 @@ CREATE TABLE IF NOT EXISTS `user_activity_log` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `additional_attributes`
 | 
					-- Table `SEBServer`.`additional_attributes`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `additional_attributes` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`additional_attributes` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `additional_attributes` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`additional_attributes` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL,
 | 
					  `id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `entity_type` VARCHAR(45) NOT NULL,
 | 
					  `entity_type` VARCHAR(45) NOT NULL,
 | 
				
			||||||
  `entity_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `entity_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -469,11 +477,11 @@ CREATE TABLE IF NOT EXISTS `additional_attributes` (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `seb_client_configuration`
 | 
					-- Table `SEBServer`.`seb_client_configuration`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `seb_client_configuration` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`seb_client_configuration` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `seb_client_configuration` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`seb_client_configuration` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
					  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
 | 
				
			||||||
  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
					  `institution_id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `name` VARCHAR(255) NOT NULL,
 | 
					  `name` VARCHAR(255) NOT NULL,
 | 
				
			||||||
| 
						 | 
					@ -486,18 +494,18 @@ CREATE TABLE IF NOT EXISTS `seb_client_configuration` (
 | 
				
			||||||
  INDEX `sebClientCredentialsInstitutionRef_idx` (`institution_id` ASC),
 | 
					  INDEX `sebClientCredentialsInstitutionRef_idx` (`institution_id` ASC),
 | 
				
			||||||
  CONSTRAINT `sebClientConfigInstitutionRef`
 | 
					  CONSTRAINT `sebClientConfigInstitutionRef`
 | 
				
			||||||
    FOREIGN KEY (`institution_id`)
 | 
					    FOREIGN KEY (`institution_id`)
 | 
				
			||||||
    REFERENCES `institution` (`id`)
 | 
					    REFERENCES `SEBServer`.`institution` (`id`)
 | 
				
			||||||
    ON DELETE NO ACTION
 | 
					    ON DELETE NO ACTION
 | 
				
			||||||
    ON UPDATE NO ACTION)
 | 
					    ON UPDATE NO ACTION)
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
-- Table `webservice_server_info`
 | 
					-- Table `SEBServer`.`webservice_server_info`
 | 
				
			||||||
-- -----------------------------------------------------
 | 
					-- -----------------------------------------------------
 | 
				
			||||||
DROP TABLE IF EXISTS `webservice_server_info` ;
 | 
					DROP TABLE IF EXISTS `SEBServer`.`webservice_server_info` ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE IF NOT EXISTS `webservice_server_info` (
 | 
					CREATE TABLE IF NOT EXISTS `SEBServer`.`webservice_server_info` (
 | 
				
			||||||
  `id` BIGINT UNSIGNED NOT NULL,
 | 
					  `id` BIGINT UNSIGNED NOT NULL,
 | 
				
			||||||
  `uuid` VARCHAR(255) NOT NULL,
 | 
					  `uuid` VARCHAR(255) NOT NULL,
 | 
				
			||||||
  `service_address` VARCHAR(255) NOT NULL,
 | 
					  `service_address` VARCHAR(255) NOT NULL,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,7 +233,7 @@ Text.error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Text[MULTI] {
 | 
					Text[MULTI] {
 | 
				
			||||||
    padding: 5px 10px 5px 10px;
 | 
					    padding: 5px 10px 5px 10px;
 | 
				
			||||||
    height: 50px;
 | 
					    height: 100px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Text[BORDER], Text[MULTI][BORDER] {
 | 
					Text[BORDER], Text[MULTI][BORDER] {
 | 
				
			||||||
| 
						 | 
					@ -250,6 +250,7 @@ Text[BORDER]:focused, Text[MULTI][BORDER]:focused {
 | 
				
			||||||
Text[BORDER]:disabled, Text[MULTI][BORDER]:disabled, Text[BORDER]:read-only,
 | 
					Text[BORDER]:disabled, Text[MULTI][BORDER]:disabled, Text[BORDER]:read-only,
 | 
				
			||||||
    Text[MULTI][BORDER]:read-only {
 | 
					    Text[MULTI][BORDER]:read-only {
 | 
				
			||||||
    box-shadow: none;
 | 
					    box-shadow: none;
 | 
				
			||||||
 | 
					    color: #CFCFCF;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue