JSON export for Config-Key generation

This commit is contained in:
anhefti 2019-07-25 16:40:23 +02:00
parent 6b9fc60981
commit 58c8b12ebe
20 changed files with 1034 additions and 181 deletions

View file

@ -246,6 +246,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId> <artifactId>spring-boot-starter-cache</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- NOTE since org.springframework.security.oauth is not fully migrated <!-- NOTE since org.springframework.security.oauth is not fully migrated
to spring-boot-starter-security we have to declare a separate version here. to spring-boot-starter-security we have to declare a separate version here.
This refers to the latest version of spring-security-oauth2 and should be This refers to the latest version of spring-security-oauth2 and should be

View file

@ -86,12 +86,18 @@ public class APIMessage implements Serializable {
public ResponseEntity<List<APIMessage>> createErrorResponse() { public ResponseEntity<List<APIMessage>> createErrorResponse() {
final APIMessage message = of(); final APIMessage message = of();
return new ResponseEntity<>(Arrays.asList(message), this.httpStatus); return new ResponseEntity<>(
Arrays.asList(message),
Utils.createJsonContentHeader(),
this.httpStatus);
} }
public ResponseEntity<Object> createErrorResponse(final String details, final String... attributes) { public ResponseEntity<Object> createErrorResponse(final String details, final String... attributes) {
final APIMessage message = of(details, attributes); final APIMessage message = of(details, attributes);
return new ResponseEntity<>(Arrays.asList(message), this.httpStatus); return new ResponseEntity<>(
Arrays.asList(message),
Utils.createJsonContentHeader(),
this.httpStatus);
} }
} }

View file

@ -8,8 +8,10 @@
package ch.ethz.seb.sebserver.gbl.model.sebconfig; package ch.ethz.seb.sebserver.gbl.model.sebconfig;
import java.text.Collator;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -36,6 +38,10 @@ public final class ConfigurationAttribute implements Entity, Comparable<Configur
private static final Logger log = LoggerFactory.getLogger(ConfigurationAttribute.class); private static final Logger log = LoggerFactory.getLogger(ConfigurationAttribute.class);
/** This is used to compare the attribute names for sorting used to generate the Config-Key
* See: https://www.safeexambrowser.org/developer/seb-config-key.html */
private static final Collator CULTURE_INVARIANT_COLLATOR = Collator.getInstance(Locale.ROOT);
/** This configuration attribute dependency key can be used to set a specific localized text key prefix for /** 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 * 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 * to multiply the resources for each attribute with the attribute name prefix, we can set a specific
@ -162,8 +168,9 @@ public final class ConfigurationAttribute implements Entity, Comparable<Configur
@Override @Override
public int compareTo(final ConfigurationAttribute attribute) { public int compareTo(final ConfigurationAttribute attribute) {
// TODO check if this is correct in reference to https://www.safeexambrowser.org/developer/seb-config-key.html return CULTURE_INVARIANT_COLLATOR.compare(
return this.name.compareToIgnoreCase(attribute.name); this.name,
attribute.name);
} }
@Override @Override

View file

@ -33,6 +33,9 @@ import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@ -391,4 +394,12 @@ public final class Utils {
} }
} }
public static final MultiValueMap<String, String> createJsonContentHeader() {
final MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
headers.set(
HttpHeaders.CONTENT_TYPE,
org.springframework.http.MediaType.APPLICATION_JSON_UTF8_VALUE);
return headers;
}
} }

View file

@ -10,7 +10,10 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
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;
@ -18,7 +21,14 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
/** Defines the interface of a XML converter to be used to convert /** Defines the interface of a XML converter to be used to convert
* ConfigurationValue for defined ConfigurationAttribute */ * ConfigurationValue for defined ConfigurationAttribute */
public interface XMLValueConverter { public interface AttributeValueConverter {
/** This can be overwritten if a XMLValueConverter needs the XMLValueConverterService.
* The XMLValueConverterService is then injected by its self on initialization.
*
* @param xmlValueConverterService */
default void init(final AttributeValueConverterService xmlValueConverterService) {
}
/** Gives a Set of AttributeType's a concrete converter is able to /** Gives a Set of AttributeType's a concrete converter is able to
* handle and convert ConfigurationValue of attributes of given types. * handle and convert ConfigurationValue of attributes of given types.
@ -26,26 +36,42 @@ public interface XMLValueConverter {
* @return a Set of supported AttributeType's of the converter */ * @return a Set of supported AttributeType's of the converter */
Set<AttributeType> types(); Set<AttributeType> types();
/** The name of the Converter. This can be used if a Converter is specific to /** The attribute names of the Converter. This can be used if a Converter is specific to
* an ConfigurationAttribute and not specific on a type of attribute. * an ConfigurationAttribute and not specific on a type of attribute.
* This must give either the name if a specific ConfigurationAttribute or null/emptyString * This must give either the name if a specific ConfigurationAttribute or empty set
* *
* @return The name of a specific ConfigurationAttribute the converter works for. */ * @return The name of a specific ConfigurationAttribute the converter works for. */
String name(); default Set<String> names() {
return Collections.emptySet();
}
/** Used to convert the a given ConfigurationAttribute / ConfigurationValue /** Used to convert the a given ConfigurationAttribute to plain XML text or block of SEB Configuration attribute.
* pair to plain XML text for block of this SEB Configuration attribute.
* *
* @param out The output stream to write the plain XML text block to * @param out The output stream to write the plain XML text block to
* @param attribute The ConfigurationAttribute containing all attribute information * @param attribute The ConfigurationAttribute containing all attribute information
* @param value The ConfigurationValue containing the value * @param valueSupplier The ConfigurationValue supplier
* @param xmlValueConverterService
* @throws IOException */ * @throws IOException */
void convertToXML( void convertToXML(
OutputStream out, OutputStream out,
ConfigurationAttribute attribute, ConfigurationAttribute attribute,
ConfigurationValue value) throws IOException; Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException;
/** Used to convert the a given ConfigurationAttribute to plain JSON text or block of SEB Configuration attribute.
*
* @param out The output stream to write the plain JSON text block to
* @param attribute The ConfigurationAttribute containing all attribute information
* @param valueSupplier The ConfigurationValue supplier
* @throws IOException */
void convertToJSON(
OutputStream out,
ConfigurationAttribute attribute,
Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException;
/** Get the real name of the SEB configuration attribute
* by cutting of the prefixed used for nested attributes
*
* @param attribute
* @return the SEB configuration attribute name */
default String extractName(final ConfigurationAttribute attribute) { default String extractName(final ConfigurationAttribute attribute) {
final int lastIndexOf = attribute.name.lastIndexOf('.'); final int lastIndexOf = attribute.name.lastIndexOf('.');
if (lastIndexOf > 0) { if (lastIndexOf > 0) {
@ -55,11 +81,8 @@ public interface XMLValueConverter {
} }
} }
/** This can be overwritten if a XMLValueConverter needs the XMLValueConverterService. default Stream<ConfigurationAttribute> convertAttribute(final ConfigurationAttribute attr) {
* The XMLValueConverterService is then injected by its self on initialization. return Stream.of(attr);
*
* @param xmlValueConverterService */
default void init(final XMLValueConverterService xmlValueConverterService) {
} }
} }

View file

@ -11,12 +11,12 @@ package ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
/** Interface of a SEB Exam Configuration XML conversion service */ /** Interface of a SEB Exam Configuration XML conversion service */
public interface XMLValueConverterService { public interface AttributeValueConverterService {
/** Use this to get a XMLValueConverter for a given ConfigurationAttribute. /** Use this to get a XMLValueConverter for a given ConfigurationAttribute.
* *
* @param attribute The ConfigurationAttribute instance * @param attribute The ConfigurationAttribute instance
* @return a XMLValueConverter for a given ConfigurationAttribute */ * @return a XMLValueConverter for a given ConfigurationAttribute */
XMLValueConverter getXMLConverter(ConfigurationAttribute attribute); AttributeValueConverter getAttributeValueConverter(ConfigurationAttribute attribute);
} }

View file

@ -12,7 +12,6 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -21,26 +20,26 @@ import org.springframework.stereotype.Service;
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.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverterService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService;
@Lazy @Lazy
@Service @Service
@WebServiceProfile @WebServiceProfile
public class XMLValueConverterServiceImpl implements XMLValueConverterService { public class AttributeValueConverterServiceImpl implements AttributeValueConverterService {
private static final Logger log = LoggerFactory.getLogger(XMLValueConverterServiceImpl.class); private static final Logger log = LoggerFactory.getLogger(AttributeValueConverterServiceImpl.class);
private final Map<String, XMLValueConverter> convertersByAttributeName; private final Map<String, AttributeValueConverter> convertersByAttributeName;
private final Map<AttributeType, XMLValueConverter> convertersByAttributeType; private final Map<AttributeType, AttributeValueConverter> convertersByAttributeType;
public XMLValueConverterServiceImpl(final Collection<XMLValueConverter> converters) { public AttributeValueConverterServiceImpl(final Collection<AttributeValueConverter> converters) {
this.convertersByAttributeName = new HashMap<>(); this.convertersByAttributeName = new HashMap<>();
this.convertersByAttributeType = new HashMap<>(); this.convertersByAttributeType = new HashMap<>();
for (final XMLValueConverter converter : converters) { for (final AttributeValueConverter converter : converters) {
converter.init(this); converter.init(this);
if (StringUtils.isNotBlank(converter.name())) { for (final String attributeName : converter.names()) {
this.convertersByAttributeName.put(converter.name(), converter); this.convertersByAttributeName.put(attributeName, converter);
} }
for (final AttributeType aType : converter.types()) { for (final AttributeType aType : converter.types()) {
@ -56,7 +55,7 @@ public class XMLValueConverterServiceImpl implements XMLValueConverterService {
} }
@Override @Override
public XMLValueConverter getXMLConverter(final ConfigurationAttribute attribute) { public AttributeValueConverter getAttributeValueConverter(final ConfigurationAttribute attribute) {
if (this.convertersByAttributeName.containsKey(attribute.name)) { if (this.convertersByAttributeName.containsKey(attribute.name)) {
return this.convertersByAttributeName.get(attribute.name); return this.convertersByAttributeName.get(attribute.name);
} }

View file

@ -15,6 +15,7 @@ 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 java.util.stream.Stream;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -32,7 +33,8 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverterService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService;
@Lazy @Lazy
@Component @Component
@ -51,18 +53,18 @@ public class ExamConfigIO {
private final ConfigurationAttributeDAO configurationAttributeDAO; private final ConfigurationAttributeDAO configurationAttributeDAO;
private final ConfigurationValueDAO configurationValueDAO; private final ConfigurationValueDAO configurationValueDAO;
private final ConfigurationDAO configurationDAO; private final ConfigurationDAO configurationDAO;
private final XMLValueConverterService xmlValueConverterService; private final AttributeValueConverterService attributeValueConverterService;
protected ExamConfigIO( protected ExamConfigIO(
final ConfigurationAttributeDAO configurationAttributeDAO, final ConfigurationAttributeDAO configurationAttributeDAO,
final ConfigurationValueDAO configurationValueDAO, final ConfigurationValueDAO configurationValueDAO,
final ConfigurationDAO configurationDAO, final ConfigurationDAO configurationDAO,
final XMLValueConverterService xmlValueConverterService) { final AttributeValueConverterService attributeValueConverterService) {
this.configurationAttributeDAO = configurationAttributeDAO; this.configurationAttributeDAO = configurationAttributeDAO;
this.configurationValueDAO = configurationValueDAO; this.configurationValueDAO = configurationValueDAO;
this.configurationDAO = configurationDAO; this.configurationDAO = configurationDAO;
this.xmlValueConverterService = xmlValueConverterService; this.attributeValueConverterService = attributeValueConverterService;
} }
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
@ -75,17 +77,11 @@ public class ExamConfigIO {
log.debug("Start export SEB plain XML configuration asynconously"); log.debug("Start export SEB plain XML configuration asynconously");
} }
// get all defined root configuration attributes // get all defined root configuration attributes prepared and sorted
final Map<Long, ConfigurationAttribute> attributes = this.configurationAttributeDAO.getAllRootAttributes() final List<ConfigurationAttribute> sortedAttributes = this.configurationAttributeDAO.getAllRootAttributes()
.getOrThrow() .getOrThrow()
.stream() .stream()
.collect(Collectors.toMap( .flatMap(this::convertAttribute)
ConfigurationAttribute::getId,
Function.identity()));
final List<ConfigurationAttribute> sortedAttributes = attributes
.values()
.stream()
.sorted() .sorted()
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -94,14 +90,8 @@ public class ExamConfigIO {
.getFollowupConfiguration(configurationNodeId) .getFollowupConfiguration(configurationNodeId)
.getOrThrow().id; .getOrThrow().id;
// get all values for that attributes for given configurationId final Function<ConfigurationAttribute, ConfigurationValue> configurationValueSupplier =
final Map<Long, ConfigurationValue> values = this.configurationValueDAO getConfigurationValueSupplier(institutionId, configurationId);
.allRootAttributeValues(institutionId, configurationId)
.getOrThrow()
.stream()
.collect(Collectors.toMap(
ConfigurationValue::getAttributeId,
Function.identity()));
try { try {
// write headers // write headers
@ -114,13 +104,10 @@ public class ExamConfigIO {
// write attributes // write attributes
for (final ConfigurationAttribute attribute : sortedAttributes) { for (final ConfigurationAttribute attribute : sortedAttributes) {
final ConfigurationValue configurationValue = values.get(attribute.id); this.attributeValueConverterService.getAttributeValueConverter(attribute).convertToXML(
if (configurationValue != null) { out,
this.xmlValueConverterService.getXMLConverter(attribute).convertToXML( attribute,
out, configurationValueSupplier);
attribute,
configurationValue);
}
} }
// plist close // plist close
@ -144,9 +131,34 @@ public class ExamConfigIO {
} }
} }
private Stream<ConfigurationAttribute> convertAttribute(final ConfigurationAttribute attr) {
final AttributeValueConverter attributeValueConverter =
this.attributeValueConverterService.getAttributeValueConverter(attr);
if (attributeValueConverter != null) {
return attributeValueConverter.convertAttribute(attr);
} else {
return Stream.of(attr);
}
}
@Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME) @Async(AsyncServiceSpringConfig.EXECUTOR_BEAN_NAME)
void importPlainXML(final InputStream in, final Long institutionId, final Long configurationNodeId) { void importPlainXML(final InputStream in, final Long institutionId, final Long configurationNodeId) {
// TODO version 1 // TODO version 1
} }
private Function<ConfigurationAttribute, ConfigurationValue> getConfigurationValueSupplier(
final Long institutionId,
final Long configurationId) {
final Map<Long, ConfigurationValue> mapping = this.configurationValueDAO
.allRootAttributeValues(institutionId, configurationId)
.getOrThrow()
.stream()
.collect(Collectors.toMap(
ConfigurationValue::getAttributeId,
Function.identity()));
return attr -> mapping.get(attr.id);
}
} }

View file

@ -161,6 +161,9 @@ public class SebExamConfigServiceImpl implements SebExamConfigService {
@Override @Override
public String generateConfigKey(final Long configurationNodeId) { public String generateConfigKey(final Long configurationNodeId) {
//DigestUtils.sha1Hex(data)
// TODO https://www.safeexambrowser.org/developer/seb-config-key.html // TODO https://www.safeexambrowser.org/developer/seb-config-key.html
throw new UnsupportedOperationException("TODO"); throw new UnsupportedOperationException("TODO");
} }

View file

@ -14,6 +14,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -25,23 +26,29 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class ArrayOfStringConverter implements XMLValueConverter { public class ArrayOfStringConverter implements AttributeValueConverter {
public static final String ATTRIBUTE_NAME = "ExceptionsList"; public static final Set<String> ATTRIBUTE_NAMES = Utils.immutableSetOf("ExceptionsList");
public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet( public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList( new HashSet<>(Arrays.asList(
AttributeType.MULTI_CHECKBOX_SELECTION, AttributeType.MULTI_CHECKBOX_SELECTION,
AttributeType.MULTI_SELECTION))); AttributeType.MULTI_SELECTION)));
private static final String TEMPLATE = "<key>%s</key><array>"; private static final String XML_TEMPLATE = "<key>%s</key><array>";
private static final String TEMPLATE_ENTRY = "<string>%s</string>"; private static final String XML_TEMPLATE_ENTRY = "<string>%s</string>";
private static final String TEMPLATE_EMPTY = "<key>%s</key><array></array>"; private static final String XML_TEMPLATE_EMPTY = "<key>%s</key><array></array>";
private static final String XML_ARRAY_CLOSE = "</array>";
private static final String JSON_TEMPLATE = "\"%s\":[";
private static final String JSON_TEMPLATE_ENTRY = "\"%s\"";
private static final String JSON_TEMPLATE_EMPTY = "\"%s\":[]";
private static final String JSON_ARRAY_CLOSE = "]";
@Override @Override
public Set<AttributeType> types() { public Set<AttributeType> types() {
@ -49,28 +56,63 @@ public class ArrayOfStringConverter implements XMLValueConverter {
} }
@Override @Override
public String name() { public Set<String> names() {
return ATTRIBUTE_NAME; return ATTRIBUTE_NAMES;
} }
@Override @Override
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), true);
}
@Override
public void convertToJSON(
final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), false);
}
private void convert(
final OutputStream out,
final ConfigurationAttribute attribute,
final ConfigurationValue value,
final boolean xml) throws IOException {
final String val = (value.value != null) ? value.value : attribute.getDefaultValue(); final String val = (value.value != null) ? value.value : attribute.getDefaultValue();
if (StringUtils.isNotBlank(val)) { if (StringUtils.isNotBlank(val)) {
final String[] values = StringUtils.split(val, Constants.LIST_SEPARATOR); final String[] values = StringUtils.split(val, Constants.LIST_SEPARATOR);
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append(String.format(TEMPLATE, extractName(attribute))); sb.append(String.format(
(xml) ? XML_TEMPLATE : JSON_TEMPLATE,
extractName(attribute)));
for (final String v : values) { for (final String v : values) {
sb.append(String.format(TEMPLATE_ENTRY, v)); sb.append(String.format(
(xml) ? XML_TEMPLATE_ENTRY : JSON_TEMPLATE_ENTRY,
v));
if (!xml) {
sb.append(Constants.LIST_SEPARATOR);
}
} }
sb.append("</array>");
if (!xml) {
// delete tailing LIST_SEPARATOR (',') from loop
sb.deleteCharAt(sb.length() - 1);
}
sb.append((xml) ? XML_ARRAY_CLOSE : JSON_ARRAY_CLOSE);
out.write(Utils.toByteArray(sb.toString())); out.write(Utils.toByteArray(sb.toString()));
} else { } else {
out.write(Utils.toByteArray(String.format(TEMPLATE_EMPTY, extractName(attribute)))); out.write(Utils.toByteArray(String.format(
(xml) ? XML_TEMPLATE_EMPTY : JSON_TEMPLATE_EMPTY,
extractName(attribute))));
} }
} }

View file

@ -14,8 +14,8 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -25,23 +25,19 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class BooleanConverter implements XMLValueConverter { public class BooleanConverter implements AttributeValueConverter {
public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet( public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList( new HashSet<>(Arrays.asList(
AttributeType.CHECKBOX))); AttributeType.CHECKBOX)));
private static final String TEMPLATE = "<key>%s</key><%s />"; private static final String XML_TEMPLATE = "<key>%s</key><%s />";
private static final String JSON_TEMPLATE = "\"%s\":%s";
@Override
public String name() {
return StringUtils.EMPTY;
}
@Override @Override
public Set<AttributeType> types() { public Set<AttributeType> types() {
@ -52,14 +48,31 @@ public class BooleanConverter implements XMLValueConverter {
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), XML_TEMPLATE);
}
@Override
public void convertToJSON(
final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), JSON_TEMPLATE);
}
private void convert(
final OutputStream out,
final ConfigurationAttribute attribute,
final ConfigurationValue value,
final String template) throws IOException {
out.write(Utils.toByteArray( out.write(Utils.toByteArray(
String.format( String.format(
TEMPLATE, template,
extractName(attribute), extractName(attribute),
(value.value != null) ? value.value : Constants.FALSE_STRING))); (value.value != null) ? value.value : Constants.FALSE_STRING)));
} }
} }

View file

@ -14,8 +14,10 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils; 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;
@ -24,12 +26,14 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class IntegerConverter implements XMLValueConverter { public class IntegerConverter implements AttributeValueConverter {
private static final Logger log = LoggerFactory.getLogger(IntegerConverter.class);
public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet( public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList( new HashSet<>(Arrays.asList(
@ -38,31 +42,52 @@ public class IntegerConverter implements XMLValueConverter {
AttributeType.SINGLE_SELECTION, AttributeType.SINGLE_SELECTION,
AttributeType.RADIO_SELECTION))); AttributeType.RADIO_SELECTION)));
private static final String TEMPLATE = "<key>%s</key><integer>%s</integer>"; private static final String XML_TEMPLATE = "<key>%s</key><integer>%s</integer>";
private static final String TEMPLATE_EMPTY = "<key>%s</key><integer />"; private static final String JSON_TEMPLATE = "\"%s\":%s";
@Override @Override
public Set<AttributeType> types() { public Set<AttributeType> types() {
return SUPPORTED_TYPES; return SUPPORTED_TYPES;
} }
@Override
public String name() {
return StringUtils.EMPTY;
}
@Override @Override
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), XML_TEMPLATE);
}
@Override
public void convertToJSON(
final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), JSON_TEMPLATE);
}
private void convert(
final OutputStream out,
final ConfigurationAttribute attribute,
final ConfigurationValue value,
final String template) throws IOException {
final String val = (value.value != null) ? value.value : attribute.getDefaultValue(); final String val = (value.value != null) ? value.value : attribute.getDefaultValue();
if (StringUtils.isNotBlank(val)) { int intVal = 0;
out.write(Utils.toByteArray(String.format(TEMPLATE, extractName(attribute), val)));
} else { try {
out.write(Utils.toByteArray(String.format(TEMPLATE_EMPTY, extractName(attribute)))); intVal = Integer.parseInt(val);
} catch (final NumberFormatException nfe) {
log.error("Failed to convert SEB configuration attribute value of type integer: {}", val, nfe);
intVal = 0;
} }
out.write(Utils.toByteArray(String.format(
template,
extractName(attribute),
intVal)));
} }
} }

View file

@ -12,6 +12,8 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -22,20 +24,28 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class KioskModeConverter implements XMLValueConverter { public class KioskModeConverter implements AttributeValueConverter {
public static final String NAME = "kioskMode"; public static final String ATTR_NAME_KIOSK_MODE = "kioskMode";
public static final String ATTR_NAME_CREATE_NEW_DESKTOP = "createNewDesktop";
public static final String ATTR_NAME_KILL_SHELL = "killExplorerShell";
private static final String TEMPLATE = "<key>createNewDesktop</key><%s /><key>killExplorerShell</key><%s />"; public static final Set<String> NAMES = Utils.immutableSetOf(
ATTR_NAME_KIOSK_MODE,
ATTR_NAME_CREATE_NEW_DESKTOP,
ATTR_NAME_KILL_SHELL);
private static final String XML_TEMPLATE = "<key>%s</key><%s />";
private static final String JSON_TEMPLATE = "\"%s\":%s";
@Override @Override
public String name() { public Set<String> names() {
return NAME; return NAMES;
} }
@Override @Override
@ -43,18 +53,53 @@ public class KioskModeConverter implements XMLValueConverter {
return Collections.emptySet(); return Collections.emptySet();
} }
@Override
public Stream<ConfigurationAttribute> convertAttribute(final ConfigurationAttribute attr) {
return Stream.of(
convertFrom(attr, ATTR_NAME_CREATE_NEW_DESKTOP),
convertFrom(attr, ATTR_NAME_KILL_SHELL));
}
private ConfigurationAttribute convertFrom(final ConfigurationAttribute attr, final String name) {
return new ConfigurationAttribute(
attr.id, attr.parentId, name,
attr.type, attr.resources, attr.validator,
attr.dependencies, attr.defaultValue);
}
@Override @Override
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
final String val = value.getValue(); convert(out, valueSupplier.apply(attribute), attribute.name, XML_TEMPLATE);
out.write(Utils.toByteArray( }
String.format(
TEMPLATE, @Override
(val != null == "0".equals(val)) ? Constants.TRUE_STRING : Constants.FALSE_STRING, public void convertToJSON(
(val != null == "1".equals(val)) ? Constants.TRUE_STRING : Constants.FALSE_STRING))); final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, valueSupplier.apply(attribute), attribute.name, JSON_TEMPLATE);
}
private void convert(
final OutputStream out,
final ConfigurationValue value,
final String name,
final String template) throws IOException {
final String val = (ATTR_NAME_CREATE_NEW_DESKTOP.equals(name))
? value.getValue() == null || "0".equals(value.getValue())
? Constants.TRUE_STRING
: Constants.FALSE_STRING
: value.getValue() == null || "0".equals(value.getValue())
? Constants.FALSE_STRING
: Constants.TRUE_STRING;
out.write(Utils.toByteArray(String.format(template, name, val)));
} }
} }

View file

@ -14,6 +14,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@ -24,12 +25,12 @@ import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile; import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
import ch.ethz.seb.sebserver.gbl.util.Utils; import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class StringConverter implements XMLValueConverter { public class StringConverter implements AttributeValueConverter {
public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet( public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList( new HashSet<>(Arrays.asList(
@ -39,32 +40,61 @@ public class StringConverter implements XMLValueConverter {
AttributeType.DECIMAL, AttributeType.DECIMAL,
AttributeType.COMBO_SELECTION))); AttributeType.COMBO_SELECTION)));
private static final String TEMPLATE = "<key>%s</key><string>%s</string>"; private static final String XML_TEMPLATE = "<key>%s</key><string>%s</string>";
private static final String TEMPLATE_EMPTY = "<key>%s</key><string />"; private static final String XML_TEMPLATE_EMPTY = "<key>%s</key><string />";
private static final String JSON_TEMPLATE = "\"%s\":\"%s\"";
private static final String JSON_TEMPLATE_EMPTY = "\"%s\":";
@Override @Override
public Set<AttributeType> types() { public Set<AttributeType> types() {
return SUPPORTED_TYPES; return SUPPORTED_TYPES;
} }
@Override
public String name() {
return StringUtils.EMPTY;
}
@Override @Override
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(
out,
attribute,
valueSupplier.apply(attribute),
XML_TEMPLATE, XML_TEMPLATE_EMPTY);
}
@Override
public void convertToJSON(
final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(
out,
attribute,
valueSupplier.apply(attribute),
JSON_TEMPLATE, JSON_TEMPLATE_EMPTY);
}
private void convert(
final OutputStream out,
final ConfigurationAttribute attribute,
final ConfigurationValue value,
final String template,
final String emptyTemplate) throws IOException {
final String val = (value.value != null) ? value.value : attribute.getDefaultValue(); final String val = (value.value != null) ? value.value : attribute.getDefaultValue();
if (StringUtils.isNotBlank(val)) { if (StringUtils.isNotBlank(val)) {
out.write(Utils.toByteArray(String.format(TEMPLATE, extractName(attribute), val))); out.write(Utils.toByteArray(String.format(
template,
extractName(attribute),
val)));
} else { } else {
out.write(Utils.toByteArray(String.format(TEMPLATE_EMPTY, extractName(attribute)))); out.write(Utils.toByteArray(String.format(
emptyTemplate,
extractName(attribute))));
} }
} }
} }

View file

@ -13,16 +13,18 @@ import java.io.OutputStream;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
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.StringUtils;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import ch.ethz.seb.sebserver.gbl.Constants;
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.ConfigurationValue; import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationValue;
@ -31,13 +33,13 @@ import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.FilterMap;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverter; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.XMLValueConverterService; import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService;
@Lazy @Lazy
@Component @Component
@WebServiceProfile @WebServiceProfile
public class TableConverter implements XMLValueConverter { public class TableConverter implements AttributeValueConverter {
public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet( public static final Set<AttributeType> SUPPORTED_TYPES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList( new HashSet<>(Arrays.asList(
@ -45,16 +47,23 @@ public class TableConverter implements XMLValueConverter {
AttributeType.INLINE_TABLE, AttributeType.INLINE_TABLE,
AttributeType.COMPOSITE_TABLE))); AttributeType.COMPOSITE_TABLE)));
private static final String KEY_TEMPLATE = "<key>%s</key>"; private static final String XML_KEY_TEMPLATE = "<key>%s</key>";
private static final byte[] ARRAY_START = Utils.toByteArray("<array>"); private static final byte[] XML_ARRAY_START = Utils.toByteArray("<array>");
private static final byte[] ARRAY_END = Utils.toByteArray("</array>"); private static final byte[] XML_ARRAY_END = Utils.toByteArray("</array>");
private static final byte[] DICT_START = Utils.toByteArray("<dict>"); private static final byte[] XML_DICT_START = Utils.toByteArray("<dict>");
private static final byte[] DICT_END = Utils.toByteArray("</dict>"); private static final byte[] XML_DICT_END = Utils.toByteArray("</dict>");
private static final byte[] EMPTY_ARRAY = Utils.toByteArray("<array />"); private static final byte[] XML_EMPTY_ARRAY = Utils.toByteArray("<array />");
private static final String JSON_KEY_TEMPLATE = "\"%s\":";
private static final byte[] JSON_ARRAY_START = Utils.toByteArray("[");
private static final byte[] JSON_ARRAY_END = Utils.toByteArray("]");
private static final byte[] JSON_DICT_START = Utils.toByteArray("{");
private static final byte[] JSON_DICT_END = Utils.toByteArray("}");
private static final byte[] JSON_EMPTY_ARRAY = Utils.toByteArray("[]");
private final ConfigurationAttributeDAO configurationAttributeDAO; private final ConfigurationAttributeDAO configurationAttributeDAO;
private final ConfigurationValueDAO configurationValueDAO; private final ConfigurationValueDAO configurationValueDAO;
private XMLValueConverterService xmlValueConverterService; private AttributeValueConverterService attributeValueConverterService;
public TableConverter( public TableConverter(
final ConfigurationAttributeDAO configurationAttributeDAO, final ConfigurationAttributeDAO configurationAttributeDAO,
@ -65,8 +74,8 @@ public class TableConverter implements XMLValueConverter {
} }
@Override @Override
public void init(final XMLValueConverterService xmlValueConverterService) { public void init(final AttributeValueConverterService attributeValueConverterService) {
this.xmlValueConverterService = xmlValueConverterService; this.attributeValueConverterService = attributeValueConverterService;
} }
@Override @Override
@ -74,76 +83,127 @@ public class TableConverter implements XMLValueConverter {
return SUPPORTED_TYPES; return SUPPORTED_TYPES;
} }
@Override
public String name() {
return StringUtils.EMPTY;
}
@Override @Override
public void convertToXML( public void convertToXML(
final OutputStream out, final OutputStream out,
final ConfigurationAttribute attribute, final ConfigurationAttribute attribute,
final ConfigurationValue value) throws IOException { final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
out.write(Utils.toByteArray(String.format(KEY_TEMPLATE, extractName(attribute)))); convert(out, attribute, valueSupplier.apply(attribute), true);
}
@Override
public void convertToJSON(
final OutputStream out,
final ConfigurationAttribute attribute,
final Function<ConfigurationAttribute, ConfigurationValue> valueSupplier) throws IOException {
convert(out, attribute, valueSupplier.apply(attribute), false);
}
private void convert(
final OutputStream out,
final ConfigurationAttribute attribute,
final ConfigurationValue value,
final boolean xml) throws IOException {
final List<List<ConfigurationValue>> values = this.configurationValueDAO.getOrderedTableValues( final List<List<ConfigurationValue>> values = this.configurationValueDAO.getOrderedTableValues(
value.institutionId, value.institutionId,
value.configurationId, value.configurationId,
attribute.id).getOrThrow(); attribute.id)
.getOrThrow();
if (values == null || values.isEmpty()) { final boolean noValues = CollectionUtils.isEmpty(values);
out.write(EMPTY_ARRAY);
out.flush();
return;
}
if (attribute.type != AttributeType.COMPOSITE_TABLE) { if (attribute.type != AttributeType.COMPOSITE_TABLE) {
out.write(ARRAY_START);
out.write(Utils.toByteArray(String.format(
(xml) ? XML_KEY_TEMPLATE : JSON_KEY_TEMPLATE,
extractName(attribute))));
if (noValues) {
out.write((xml) ? XML_EMPTY_ARRAY : JSON_EMPTY_ARRAY);
out.flush();
return;
} else {
out.write((xml) ? XML_ARRAY_START : JSON_ARRAY_START);
}
} else {
if (noValues) {
return;
} else {
out.write(Utils.toByteArray(String.format(
(xml) ? XML_KEY_TEMPLATE : JSON_KEY_TEMPLATE,
extractName(attribute))));
}
} }
writeRows( writeRows(
out, out,
getAttributes(attribute), getSortedChildAttributes(attribute),
values, values,
this.xmlValueConverterService); this.attributeValueConverterService,
xml);
if (attribute.type != AttributeType.COMPOSITE_TABLE) { if (attribute.type != AttributeType.COMPOSITE_TABLE) {
out.write(ARRAY_END); out.write((xml) ? XML_ARRAY_END : JSON_ARRAY_END);
} }
out.flush(); out.flush();
} }
private Map<Long, ConfigurationAttribute> getAttributes(final ConfigurationAttribute attribute) {
return this.configurationAttributeDAO
.allMatching(new FilterMap().putIfAbsent(
ConfigurationAttribute.FILTER_ATTR_PARENT_ID,
attribute.getModelId()))
.getOrThrow()
.stream()
.collect(Collectors.toMap(
attr -> attr.id,
Function.identity()));
}
private void writeRows( private void writeRows(
final OutputStream out, final OutputStream out,
final Map<Long, ConfigurationAttribute> attributeMap, final Map<Long, ConfigurationAttribute> attributeMap,
final List<List<ConfigurationValue>> values, final List<List<ConfigurationValue>> values,
final XMLValueConverterService xmlValueConverterService) throws IOException { final AttributeValueConverterService attributeValueConverterService,
final boolean xml) throws IOException {
for (final List<ConfigurationValue> rowValues : values) { final Iterator<List<ConfigurationValue>> irows = values.iterator();
out.write(DICT_START);
for (final ConfigurationValue value : rowValues) { while (irows.hasNext()) {
final List<ConfigurationValue> rowValues = irows.next();
out.write((xml) ? XML_DICT_START : JSON_DICT_START);
final Iterator<ConfigurationValue> ivalue = rowValues.iterator();
while (ivalue.hasNext()) {
final ConfigurationValue value = ivalue.next();
final ConfigurationAttribute attr = attributeMap.get(value.attributeId); final ConfigurationAttribute attr = attributeMap.get(value.attributeId);
final XMLValueConverter converter = xmlValueConverterService.getXMLConverter(attr); final AttributeValueConverter converter =
converter.convertToXML(out, attr, value); attributeValueConverterService.getAttributeValueConverter(attr);
if (xml) {
converter.convertToXML(out, attr, a -> value);
} else {
converter.convertToJSON(out, attr, a -> value);
}
if (!xml && ivalue.hasNext()) {
out.write(Utils.toByteArray(Constants.LIST_SEPARATOR));
}
} }
out.write(DICT_END); out.write((xml) ? XML_DICT_END : JSON_DICT_END);
if (!xml && irows.hasNext()) {
out.write(Utils.toByteArray(Constants.LIST_SEPARATOR));
}
out.flush(); out.flush();
} }
} }
private Map<Long, ConfigurationAttribute> getSortedChildAttributes(final ConfigurationAttribute attribute) {
return this.configurationAttributeDAO
.allMatching(new FilterMap().putIfAbsent(
ConfigurationAttribute.FILTER_ATTR_PARENT_ID,
attribute.getModelId()))
.getOrThrow()
.stream()
.sorted()
.collect(Collectors.toMap(
attr -> attr.id,
Function.identity()));
}
} }

View file

@ -31,6 +31,7 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExcep
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.APIMessage.FieldValidationException; import ch.ethz.seb.sebserver.gbl.api.APIMessage.FieldValidationException;
import ch.ethz.seb.sebserver.gbl.util.Utils;
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException; import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.PermissionDeniedException;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException; import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ResourceNotFoundException;
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationException; import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationException;
@ -51,7 +52,10 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
log.error("Unexpected generic error catched at the API endpoint: ", ex); log.error("Unexpected generic error catched at the API endpoint: ", ex);
final List<APIMessage> errors = Arrays.asList(APIMessage.ErrorMessage.GENERIC.of(ex.getMessage())); final List<APIMessage> errors = Arrays.asList(APIMessage.ErrorMessage.GENERIC.of(ex.getMessage()));
return new ResponseEntity<>(errors, status); return new ResponseEntity<>(
errors,
Utils.createJsonContentHeader(),
status);
} }
@Override @Override
@ -67,7 +71,10 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
.map(field -> APIMessage.fieldValidationError(field)) .map(field -> APIMessage.fieldValidationError(field))
.collect(Collectors.toList()); .collect(Collectors.toList());
return new ResponseEntity<>(valErrors, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(
valErrors,
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST);
} }
@ExceptionHandler(OAuth2Exception.class) @ExceptionHandler(OAuth2Exception.class)
@ -77,7 +84,10 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
log.error("OAuth2Exception: ", ex); log.error("OAuth2Exception: ", ex);
final APIMessage message = APIMessage.ErrorMessage.UNAUTHORIZED.of(ex.getMessage()); final APIMessage message = APIMessage.ErrorMessage.UNAUTHORIZED.of(ex.getMessage());
return new ResponseEntity<>(message, HttpStatus.UNAUTHORIZED); return new ResponseEntity<>(
message,
Utils.createJsonContentHeader(),
HttpStatus.UNAUTHORIZED);
} }
@ExceptionHandler(BeanValidationException.class) @ExceptionHandler(BeanValidationException.class)
@ -91,7 +101,10 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
.map(field -> APIMessage.fieldValidationError(field)) .map(field -> APIMessage.fieldValidationError(field))
.collect(Collectors.toList()); .collect(Collectors.toList());
return new ResponseEntity<>(valErrors, HttpStatus.BAD_REQUEST); return new ResponseEntity<>(
valErrors,
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST);
} }
@ExceptionHandler(ResourceNotFoundException.class) @ExceptionHandler(ResourceNotFoundException.class)
@ -149,6 +162,7 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
return new ResponseEntity<>( return new ResponseEntity<>(
ex.getAPIMessages(), ex.getAPIMessages(),
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST); HttpStatus.BAD_REQUEST);
} }
@ -159,6 +173,7 @@ public class APIExceptionHandler extends ResponseEntityExceptionHandler {
return new ResponseEntity<>( return new ResponseEntity<>(
Arrays.asList(ex.apiMessage), Arrays.asList(ex.apiMessage),
Utils.createJsonContentHeader(),
HttpStatus.BAD_REQUEST); HttpStatus.BAD_REQUEST);
} }

View file

@ -0,0 +1,68 @@
/*
* 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.webservice.servicelayer.sebconfig.impl;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.AttributeType;
import ch.ethz.seb.sebserver.gbl.model.sebconfig.ConfigurationAttribute;
public class ConfigAttributeSortOrderTest {
@Test
public void testSortOrder() throws Exception {
// test example from: https://www.safeexambrowser.org/developer/seb-config-key.html
// For example the key <key>allowWlan</key> comes before <key>allowWLAN</key>
final ConfigurationAttribute aa = new ConfigurationAttribute(
1L,
null,
"aa",
AttributeType.CHECKBOX,
null, null, null, "false");
final ConfigurationAttribute allowWlan = new ConfigurationAttribute(
1L,
null,
"allowWlan",
AttributeType.CHECKBOX,
null, null, null, "false");
final ConfigurationAttribute allowWLAN = new ConfigurationAttribute(
1L,
null,
"allowWLAN",
AttributeType.CHECKBOX,
null, null, null, "false");
final ConfigurationAttribute zz = new ConfigurationAttribute(
1L,
null,
"zz",
AttributeType.CHECKBOX,
null, null, null, "false");
final List<ConfigurationAttribute> list = Arrays.asList(zz, allowWLAN, aa, allowWlan);
Collections.sort(list);
assertEquals(
"[aa, allowWlan, allowWLAN, zz]",
list.stream()
.map(ConfigurationAttribute::getName)
.collect(Collectors.toList())
.toString());
}
}

View file

@ -0,0 +1,161 @@
/*
* 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.webservice.servicelayer.sebconfig.impl.converter;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream;
import org.junit.Test;
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.ConfigurationValue;
public class ArrayOfStringConverterTest {
@Test
public void testXML() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToXML(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, "one,two,tree"));
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>attribute</key><array><string>one</string><string>two</string><string>tree</string></array>",
xmlString);
}
@Test
public void testEmptyXML() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToXML(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, ""));
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>attribute</key><array></array>",
xmlString);
}
@Test
public void testNullXML() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToXML(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, null));
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>attribute</key><array><string>defaultValue</string></array>",
xmlString);
}
@Test
public void testJSON() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToJSON(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, "one,two,tree"));
final String xmlString = new String(out.toByteArray());
assertEquals(
"\"attribute\":[\"one\",\"two\",\"tree\"]",
xmlString);
}
@Test
public void testEmptyJSON() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToJSON(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, ""));
final String xmlString = new String(out.toByteArray());
assertEquals(
"\"attribute\":[]",
xmlString);
}
@Test
public void testNullJSON() throws Exception {
final ArrayOfStringConverter arrayOfStringConverter = new ArrayOfStringConverter();
final ConfigurationAttribute attribute = new ConfigurationAttribute(
1L,
null,
"attribute",
AttributeType.CHECKBOX,
null, null, null, "defaultValue");
final ByteArrayOutputStream out = new ByteArrayOutputStream();
arrayOfStringConverter.convertToJSON(
out,
attribute,
attr -> new ConfigurationValue(1l, 1l, 1l, 1l, 1, null));
final String xmlString = new String(out.toByteArray());
assertEquals(
"\"attribute\":[\"defaultValue\"]",
xmlString);
}
}

View file

@ -0,0 +1,329 @@
/*
* 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.webservice.servicelayer.sebconfig.impl.converter;
import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.mockito.Mockito;
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.ConfigurationValue;
import ch.ethz.seb.sebserver.gbl.util.Result;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationAttributeDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ConfigurationValueDAO;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverter;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.AttributeValueConverterService;
import ch.ethz.seb.sebserver.webservice.servicelayer.sebconfig.impl.AttributeValueConverterServiceImpl;
public class TableConverterTest {
// ********************************
// **** table
// ********************************
private final ConfigurationAttribute TABLE_ATTR =
new ConfigurationAttribute(1L, null, "table", AttributeType.TABLE, null, null, null, null);
private final ConfigurationValue TABLE_VALUE =
new ConfigurationValue(1L, 1L, 1L, 1L, 0, null);
private final ConfigurationAttribute COLUMN_ATTR_1 =
new ConfigurationAttribute(2L, 1L, "attr1", AttributeType.TEXT_FIELD, null, null, null, null);
private final ConfigurationAttribute COLUMN_ATTR_2 =
new ConfigurationAttribute(3L, 1L, "attr2", AttributeType.TEXT_FIELD, null, null, null, null);
private final ConfigurationValue ROW_1_ATTR_1 =
new ConfigurationValue(2L, 1L, 1L, 2L, 0, "1");
private final ConfigurationValue ROW_1_ATTR_2 =
new ConfigurationValue(3L, 1L, 1L, 3L, 0, "2");
private final ConfigurationValue ROW_2_ATTR_1 =
new ConfigurationValue(4L, 1L, 1L, 2L, 1, "3");
private final ConfigurationValue ROW_2_ATTR_2 =
new ConfigurationValue(5L, 1L, 1L, 3L, 1, "4");
private final Collection<ConfigurationAttribute> TABLE_COLUMNS = Arrays.asList(
this.COLUMN_ATTR_1,
this.COLUMN_ATTR_2);
private final List<List<ConfigurationValue>> TABLE_VALUES = Arrays.asList(
Arrays.asList(this.ROW_1_ATTR_1, this.ROW_1_ATTR_2),
Arrays.asList(this.ROW_2_ATTR_1, this.ROW_2_ATTR_2));
// ********************************
// **** Composite table
// ********************************
private final ConfigurationAttribute COMPOSITE_TABLE_ATTR =
new ConfigurationAttribute(1L, null, "table", AttributeType.COMPOSITE_TABLE, null, null, null, null);
private final ConfigurationValue COMPOSITE_TABLE_VALUE =
new ConfigurationValue(1L, 1L, 1L, 1L, 0, null);
private final ConfigurationAttribute COMPOSITE_COLUMN_ATTR_1 =
new ConfigurationAttribute(2L, 1L, "attr1", AttributeType.TEXT_FIELD, null, null, null, null);
private final ConfigurationAttribute COMPOSITE_COLUMN_ATTR_2 =
new ConfigurationAttribute(3L, 1L, "attr2", AttributeType.TEXT_FIELD, null, null, null, null);
private final ConfigurationValue COMPOSITE_ROW_1_ATTR_1 =
new ConfigurationValue(2L, 1L, 1L, 2L, 0, "1");
private final ConfigurationValue COMPOSITE_ROW_1_ATTR_2 =
new ConfigurationValue(3L, 1L, 1L, 3L, 0, "2");
private final Collection<ConfigurationAttribute> COMPOSITE_TABLE_ENTRIES = Arrays.asList(
this.COMPOSITE_COLUMN_ATTR_1,
this.COMPOSITE_COLUMN_ATTR_2);
private final List<List<ConfigurationValue>> COMPOSITE_TABLE_VALUES = Arrays.asList(
Arrays.asList(this.COMPOSITE_ROW_1_ATTR_1, this.COMPOSITE_ROW_1_ATTR_2));
@Test
public void testXMLNormalTable() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.TABLE_COLUMNS));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(this.TABLE_VALUES));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToXML(out, this.TABLE_ATTR, attr -> this.TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>table</key>"
+ "<array>"
+ "<dict>"
+ "<key>attr1</key>"
+ "<string>1</string>"
+ "<key>attr2</key>"
+ "<string>2</string>"
+ "</dict>"
+ "<dict>"
+ "<key>attr1</key>"
+ "<string>3</string>"
+ "<key>attr2</key>"
+ "<string>4</string>"
+ "</dict>"
+ "</array>",
xmlString);
}
@Test
public void testXMLNormalTableNoValues() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.TABLE_COLUMNS));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(Collections.emptyList()));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToXML(out, this.TABLE_ATTR, attr -> this.TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>table</key><array />",
xmlString);
}
@Test
public void testXMLCompositeTable() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.COMPOSITE_TABLE_ENTRIES));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(this.COMPOSITE_TABLE_VALUES));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToXML(out, this.COMPOSITE_TABLE_ATTR, attr -> this.COMPOSITE_TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
assertEquals(
"<key>table</key>"
+ "<dict>"
+ "<key>attr1</key>"
+ "<string>1</string>"
+ "<key>attr2</key>"
+ "<string>2</string>"
+ "</dict>",
xmlString);
}
@Test
public void testXMLCompositeTableEmpty() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.COMPOSITE_TABLE_ENTRIES));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(Collections.emptyList()));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToXML(out, this.COMPOSITE_TABLE_ATTR, attr -> this.COMPOSITE_TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
assertEquals(
"",
xmlString);
}
@Test
public void testJSONNormalTable() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.TABLE_COLUMNS));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(this.TABLE_VALUES));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToJSON(out, this.TABLE_ATTR, attr -> this.TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
// expected : "table":[{"attr1":"1","attr2":"2"},{"attr1":"3","attr2":"4"}]
assertEquals(
"\"table\":[{\"attr1\":\"1\",\"attr2\":\"2\"},{\"attr1\":\"3\",\"attr2\":\"4\"}]",
xmlString);
}
@Test
public void testJSONNormalTableEmpty() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.TABLE_COLUMNS));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(Collections.emptyList()));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToJSON(out, this.TABLE_ATTR, attr -> this.TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
// expected : "table":[]
assertEquals(
"\"table\":[]",
xmlString);
}
@Test
public void testJSONCompositeTable() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.COMPOSITE_TABLE_ENTRIES));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(this.COMPOSITE_TABLE_VALUES));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToJSON(out, this.COMPOSITE_TABLE_ATTR, attr -> this.COMPOSITE_TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
// expected : "table":{"attr1":"1","attr2":"2"}
assertEquals(
"\"table\":{\"attr1\":\"1\",\"attr2\":\"2\"}",
xmlString);
}
@Test
public void testJSONCompositeTableEmpty() throws Exception {
final ConfigurationAttributeDAO configurationAttributeDAO =
Mockito.mock(ConfigurationAttributeDAO.class);
Mockito.when(configurationAttributeDAO.allMatching(Mockito.any()))
.thenReturn(Result.of(this.COMPOSITE_TABLE_ENTRIES));
final ConfigurationValueDAO configurationValueDAO =
Mockito.mock(ConfigurationValueDAO.class);
Mockito.when(configurationValueDAO.getOrderedTableValues(1L, 1L, 1L))
.thenReturn(Result.of(Collections.emptyList()));
final TableConverter tableConverter = new TableConverter(configurationAttributeDAO, configurationValueDAO);
tableConverter.init(createAttributeValueConverterService());
final ByteArrayOutputStream out = new ByteArrayOutputStream();
tableConverter.convertToJSON(out, this.COMPOSITE_TABLE_ATTR, attr -> this.COMPOSITE_TABLE_VALUE);
final String xmlString = new String(out.toByteArray());
// expected :
assertEquals(
"",
xmlString);
}
private AttributeValueConverterService createAttributeValueConverterService() {
final List<AttributeValueConverter> converter = new ArrayList<>();
converter.add(new StringConverter());
return new AttributeValueConverterServiceImpl(converter);
}
}