SEBSERV-240 implementation
This commit is contained in:
		
							parent
							
								
									6d56e71dbe
								
							
						
					
					
						commit
						a35ba48844
					
				
					 15 changed files with 263 additions and 49 deletions
				
			
		| 
						 | 
					@ -213,6 +213,7 @@ public final class API {
 | 
				
			||||||
    public static final String EXAM_PROCTORING_ATTR_ALLOW_CHAT = "allow_chat";
 | 
					    public static final String EXAM_PROCTORING_ATTR_ALLOW_CHAT = "allow_chat";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String SEB_CLIENT_CONNECTION_ENDPOINT = "/seb-client-connection";
 | 
					    public static final String SEB_CLIENT_CONNECTION_ENDPOINT = "/seb-client-connection";
 | 
				
			||||||
 | 
					    public static final String SEB_CLIENT_CONNECTION_DATA_ENDPOINT = "/data";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String SEB_CLIENT_EVENT_ENDPOINT = "/seb-client-event";
 | 
					    public static final String SEB_CLIENT_EVENT_ENDPOINT = "/seb-client-event";
 | 
				
			||||||
    public static final String SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT = "/search";
 | 
					    public static final String SEB_CLIENT_EVENT_SEARCH_PATH_SEGMENT = "/search";
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,10 +17,12 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 | 
				
			||||||
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.api.EntityType;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.GrantEntity;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@JsonIgnoreProperties(ignoreUnknown = true)
 | 
					@JsonIgnoreProperties(ignoreUnknown = true)
 | 
				
			||||||
public class ClientConnectionData {
 | 
					public class ClientConnectionData implements GrantEntity {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static final String ATTR_CLIENT_CONNECTION = "cData";
 | 
					    public static final String ATTR_CLIENT_CONNECTION = "cData";
 | 
				
			||||||
    public static final String ATTR_INDICATOR_VALUE = "iValues";
 | 
					    public static final String ATTR_INDICATOR_VALUE = "iValues";
 | 
				
			||||||
| 
						 | 
					@ -48,7 +50,7 @@ public class ClientConnectionData {
 | 
				
			||||||
        this.indicatorValues = Utils.immutableListOf(indicatorValues);
 | 
					        this.indicatorValues = Utils.immutableListOf(indicatorValues);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected ClientConnectionData(
 | 
					    public ClientConnectionData(
 | 
				
			||||||
            final ClientConnection clientConnection,
 | 
					            final ClientConnection clientConnection,
 | 
				
			||||||
            final List<? extends IndicatorValue> indicatorValues) {
 | 
					            final List<? extends IndicatorValue> indicatorValues) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +60,26 @@ public class ClientConnectionData {
 | 
				
			||||||
        this.indicatorValues = Utils.immutableListOf(indicatorValues);
 | 
					        this.indicatorValues = Utils.immutableListOf(indicatorValues);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public EntityType entityType() {
 | 
				
			||||||
 | 
					        return this.clientConnection.entityType();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getName() {
 | 
				
			||||||
 | 
					        return this.clientConnection.getName();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getModelId() {
 | 
				
			||||||
 | 
					        return this.clientConnection.getModelId();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Long getInstitutionId() {
 | 
				
			||||||
 | 
					        return this.clientConnection.getInstitutionId();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @JsonProperty(ATTR_MISSING_PING)
 | 
					    @JsonProperty(ATTR_MISSING_PING)
 | 
				
			||||||
    public Boolean getMissingPing() {
 | 
					    public Boolean getMissingPing() {
 | 
				
			||||||
        return this.missingPing;
 | 
					        return this.missingPing;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,15 +9,20 @@
 | 
				
			||||||
package ch.ethz.seb.sebserver.gui.content.monitoring;
 | 
					package ch.ethz.seb.sebserver.gui.content.monitoring;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
 | 
					import java.util.function.Function;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.eclipse.swt.widgets.Composite;
 | 
				
			||||||
import org.springframework.beans.factory.annotation.Value;
 | 
					import org.springframework.beans.factory.annotation.Value;
 | 
				
			||||||
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.Constants;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
					import ch.ethz.seb.sebserver.gbl.model.Domain;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
					import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
 | 
					import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.IndicatorValue;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
 | 
					import ch.ethz.seb.sebserver.gui.content.action.ActionDefinition;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.ResourceService;
 | 
					import ch.ethz.seb.sebserver.gui.service.ResourceService;
 | 
				
			||||||
| 
						 | 
					@ -29,7 +34,7 @@ import ch.ethz.seb.sebserver.gui.service.page.TemplateComposer;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
 | 
					import ch.ethz.seb.sebserver.gui.service.push.ServerPushService;
 | 
				
			||||||
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.exam.GetIndicators;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.exam.GetIndicators;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetClientConnectionPage;
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.session.GetFinishedExamClientConnectionPage;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
 | 
					import ch.ethz.seb.sebserver.gui.table.ColumnDefinition;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
 | 
					import ch.ethz.seb.sebserver.gui.table.ColumnDefinition.TableFilterAttribute;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gui.table.TableBuilder;
 | 
					import ch.ethz.seb.sebserver.gui.table.TableBuilder;
 | 
				
			||||||
| 
						 | 
					@ -91,29 +96,33 @@ public class FinishedExam implements TemplateComposer {
 | 
				
			||||||
                .call()
 | 
					                .call()
 | 
				
			||||||
                .getOrThrow();
 | 
					                .getOrThrow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final TableBuilder<ClientConnection> tableBuilder =
 | 
					        final Composite content = this.pageService.getWidgetFactory().defaultPageLayout(
 | 
				
			||||||
                this.pageService.entityTableBuilder(restService.getRestCall(GetClientConnectionPage.class))
 | 
					                pageContext.getParent(),
 | 
				
			||||||
 | 
					                TITLE_TEXT_KEY);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final TableBuilder<ClientConnectionData> tableBuilder =
 | 
				
			||||||
 | 
					                this.pageService.entityTableBuilder(restService.getRestCall(GetFinishedExamClientConnectionPage.class))
 | 
				
			||||||
                        .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
 | 
					                        .withEmptyMessage(EMPTY_LIST_TEXT_KEY)
 | 
				
			||||||
                        .withPaging(10)
 | 
					                        .withPaging(this.pageSize)
 | 
				
			||||||
                        .withStaticFilter(ClientConnection.FILTER_ATTR_EXAM_ID, examKey.modelId)
 | 
					                        .withStaticFilter(ClientConnection.FILTER_ATTR_EXAM_ID, examKey.modelId)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        .withColumn(new ColumnDefinition<>(
 | 
					                        .withColumn(new ColumnDefinition<ClientConnectionData>(
 | 
				
			||||||
                                Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
 | 
					                                Domain.CLIENT_CONNECTION.ATTR_EXAM_USER_SESSION_ID,
 | 
				
			||||||
                                TABLE_COLUMN_NAME,
 | 
					                                TABLE_COLUMN_NAME,
 | 
				
			||||||
                                ClientConnection::getUserSessionId)
 | 
					                                c -> c.clientConnection.getUserSessionId())
 | 
				
			||||||
                                        .withFilter(this.nameFilter))
 | 
					                                        .withFilter(this.nameFilter))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        .withColumn(new ColumnDefinition<>(
 | 
					                        .withColumn(new ColumnDefinition<ClientConnectionData>(
 | 
				
			||||||
                                ClientConnection.ATTR_INFO,
 | 
					                                ClientConnection.ATTR_INFO,
 | 
				
			||||||
                                TABLE_COLUMN_INFO,
 | 
					                                TABLE_COLUMN_INFO,
 | 
				
			||||||
                                ClientConnection::getInfo)
 | 
					                                c -> c.clientConnection.getInfo())
 | 
				
			||||||
                                        .withFilter(this.infoFilter))
 | 
					                                        .withFilter(this.infoFilter))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        .withColumn(new ColumnDefinition<ClientConnection>(
 | 
					                        .withColumn(new ColumnDefinition<ClientConnectionData>(
 | 
				
			||||||
                                Domain.CLIENT_CONNECTION.ATTR_STATUS,
 | 
					                                Domain.CLIENT_CONNECTION.ATTR_STATUS,
 | 
				
			||||||
                                TABLE_COLUMN_STATUS,
 | 
					                                TABLE_COLUMN_STATUS,
 | 
				
			||||||
                                row -> this.pageService.getResourceService()
 | 
					                                row -> this.pageService.getResourceService()
 | 
				
			||||||
                                        .localizedClientConnectionStatusName(row.getStatus()))
 | 
					                                        .localizedClientConnectionStatusName(row.clientConnection.getStatus()))
 | 
				
			||||||
                                                .withFilter(this.statusFilter))
 | 
					                                                .withFilter(this.statusFilter))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        .withDefaultAction(t -> actionBuilder
 | 
					                        .withDefaultAction(t -> actionBuilder
 | 
				
			||||||
| 
						 | 
					@ -121,7 +130,25 @@ public class FinishedExam implements TemplateComposer {
 | 
				
			||||||
                                .withParentEntityKey(examKey)
 | 
					                                .withParentEntityKey(examKey)
 | 
				
			||||||
                                .create());
 | 
					                                .create());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        tableBuilder.compose(pageContext);
 | 
					        indicators.stream().forEach(indicator -> {
 | 
				
			||||||
 | 
					            tableBuilder.withColumn(new ColumnDefinition<>(
 | 
				
			||||||
 | 
					                    indicator.name,
 | 
				
			||||||
 | 
					                    new LocTextKey(indicator.name),
 | 
				
			||||||
 | 
					                    indicatorValueFunction(indicator)));
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        tableBuilder.compose(pageContext.copyOf(content));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Function<ClientConnectionData, String> indicatorValueFunction(final Indicator indicator) {
 | 
				
			||||||
 | 
					        return clientConnectionData -> {
 | 
				
			||||||
 | 
					            return clientConnectionData.indicatorValues
 | 
				
			||||||
 | 
					                    .stream()
 | 
				
			||||||
 | 
					                    .filter(indicatorValue -> indicatorValue.getIndicatorId().equals(indicator.id))
 | 
				
			||||||
 | 
					                    .findFirst()
 | 
				
			||||||
 | 
					                    .map(iv -> IndicatorValue.getDisplayValue(iv, indicator.type))
 | 
				
			||||||
 | 
					                    .orElse(Constants.EMPTY_NOTE);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2022 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.remote.webservice.api.session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpMethod;
 | 
				
			||||||
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.core.type.TypeReference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.api.API;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Lazy
 | 
				
			||||||
 | 
					@Component
 | 
				
			||||||
 | 
					@GuiProfile
 | 
				
			||||||
 | 
					public class GetFinishedExamClientConnection extends RestCall<ClientConnectionData> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GetFinishedExamClientConnection() {
 | 
				
			||||||
 | 
					        super(new TypeKey<>(
 | 
				
			||||||
 | 
					                CallType.GET_SINGLE,
 | 
				
			||||||
 | 
					                EntityType.CLIENT_CONNECTION,
 | 
				
			||||||
 | 
					                new TypeReference<ClientConnectionData>() {
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                HttpMethod.GET,
 | 
				
			||||||
 | 
					                MediaType.APPLICATION_FORM_URLENCODED,
 | 
				
			||||||
 | 
					                API.SEB_CLIENT_CONNECTION_ENDPOINT
 | 
				
			||||||
 | 
					                        + API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT
 | 
				
			||||||
 | 
					                        + API.MODEL_ID_VAR_PATH_SEGMENT);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,41 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2022 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.remote.webservice.api.session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.springframework.context.annotation.Lazy;
 | 
				
			||||||
 | 
					import org.springframework.http.HttpMethod;
 | 
				
			||||||
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
 | 
					import org.springframework.stereotype.Component;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.fasterxml.jackson.core.type.TypeReference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.api.API;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.Page;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.profile.GuiProfile;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gui.service.remote.webservice.api.RestCall;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Lazy
 | 
				
			||||||
 | 
					@Component
 | 
				
			||||||
 | 
					@GuiProfile
 | 
				
			||||||
 | 
					public class GetFinishedExamClientConnectionPage extends RestCall<Page<ClientConnectionData>> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public GetFinishedExamClientConnectionPage() {
 | 
				
			||||||
 | 
					        super(new TypeKey<>(
 | 
				
			||||||
 | 
					                CallType.GET_PAGE,
 | 
				
			||||||
 | 
					                EntityType.CLIENT_CONNECTION,
 | 
				
			||||||
 | 
					                new TypeReference<Page<ClientConnectionData>>() {
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                HttpMethod.GET,
 | 
				
			||||||
 | 
					                MediaType.APPLICATION_FORM_URLENCODED,
 | 
				
			||||||
 | 
					                API.SEB_CLIENT_CONNECTION_ENDPOINT + API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -13,6 +13,7 @@ import java.util.Collection;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
					import ch.ethz.seb.sebserver.gbl.model.EntityKey;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,4 +185,11 @@ public interface SEBClientConnectionService {
 | 
				
			||||||
     * @param instructionConfirm the instruction confirm identifier */
 | 
					     * @param instructionConfirm the instruction confirm identifier */
 | 
				
			||||||
    void confirmInstructionDone(String connectionToken, String instructionConfirm);
 | 
					    void confirmInstructionDone(String connectionToken, String instructionConfirm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /** Use this to get the get the specific indicator values for a given client connection.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param clientConnection The client connection values
 | 
				
			||||||
 | 
					     * @return Result refer to ClientConnectionData instance containing the given clientConnection plus the indicator
 | 
				
			||||||
 | 
					     *         values or to an error when happened */
 | 
				
			||||||
 | 
					    Result<ClientConnectionData> getIndicatorValues(final ClientConnection clientConnection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,8 +54,14 @@ public class ClientIndicatorFactory {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<ClientIndicator> createFor(final ClientConnection clientConnection) {
 | 
					    public List<ClientIndicator> createFor(final ClientConnection clientConnection) {
 | 
				
			||||||
        final List<ClientIndicator> result = new ArrayList<>();
 | 
					        return createFor(clientConnection, false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public List<ClientIndicator> createFor(
 | 
				
			||||||
 | 
					            final ClientConnection clientConnection,
 | 
				
			||||||
 | 
					            final boolean enableCachingOverride) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final List<ClientIndicator> result = new ArrayList<>();
 | 
				
			||||||
        if (clientConnection.examId == null) {
 | 
					        if (clientConnection.examId == null) {
 | 
				
			||||||
            return result;
 | 
					            return result;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -82,7 +88,7 @@ public class ClientIndicatorFactory {
 | 
				
			||||||
                            indicatorDef,
 | 
					                            indicatorDef,
 | 
				
			||||||
                            clientConnection.id,
 | 
					                            clientConnection.id,
 | 
				
			||||||
                            clientConnection.status.clientActiveStatus,
 | 
					                            clientConnection.status.clientActiveStatus,
 | 
				
			||||||
                            this.enableCaching);
 | 
					                            this.enableCaching || enableCachingOverride);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    result.add(indicator);
 | 
					                    result.add(indicator);
 | 
				
			||||||
                } catch (final Exception e) {
 | 
					                } catch (final Exception e) {
 | 
				
			||||||
| 
						 | 
					@ -111,7 +117,7 @@ public class ClientIndicatorFactory {
 | 
				
			||||||
                        indicator,
 | 
					                        indicator,
 | 
				
			||||||
                        clientConnection.id,
 | 
					                        clientConnection.id,
 | 
				
			||||||
                        clientConnection.status.clientActiveStatus,
 | 
					                        clientConnection.status.clientActiveStatus,
 | 
				
			||||||
                        this.enableCaching);
 | 
					                        this.enableCaching || enableCachingOverride);
 | 
				
			||||||
                result.add(pingIndicator);
 | 
					                result.add(pingIndicator);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,6 +74,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
 | 
				
			||||||
    private final SEBClientConfigDAO sebClientConfigDAO;
 | 
					    private final SEBClientConfigDAO sebClientConfigDAO;
 | 
				
			||||||
    private final SEBClientInstructionService sebInstructionService;
 | 
					    private final SEBClientInstructionService sebInstructionService;
 | 
				
			||||||
    private final ExamAdminService examAdminService;
 | 
					    private final ExamAdminService examAdminService;
 | 
				
			||||||
 | 
					    private final ClientIndicatorFactory clientIndicatorFactory;
 | 
				
			||||||
    // TODO get rid of this dependency and use application events for signaling client connection state changes
 | 
					    // TODO get rid of this dependency and use application events for signaling client connection state changes
 | 
				
			||||||
    private final DistributedIndicatorValueService distributedPingCache;
 | 
					    private final DistributedIndicatorValueService distributedPingCache;
 | 
				
			||||||
    private final boolean isDistributedSetup;
 | 
					    private final boolean isDistributedSetup;
 | 
				
			||||||
| 
						 | 
					@ -84,6 +85,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
 | 
				
			||||||
            final SEBClientConfigDAO sebClientConfigDAO,
 | 
					            final SEBClientConfigDAO sebClientConfigDAO,
 | 
				
			||||||
            final SEBClientInstructionService sebInstructionService,
 | 
					            final SEBClientInstructionService sebInstructionService,
 | 
				
			||||||
            final ExamAdminService examAdminService,
 | 
					            final ExamAdminService examAdminService,
 | 
				
			||||||
 | 
					            final ClientIndicatorFactory clientIndicatorFactory,
 | 
				
			||||||
            final DistributedIndicatorValueService distributedPingCache) {
 | 
					            final DistributedIndicatorValueService distributedPingCache) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.examSessionService = examSessionService;
 | 
					        this.examSessionService = examSessionService;
 | 
				
			||||||
| 
						 | 
					@ -94,6 +96,7 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
 | 
				
			||||||
        this.sebClientConfigDAO = sebClientConfigDAO;
 | 
					        this.sebClientConfigDAO = sebClientConfigDAO;
 | 
				
			||||||
        this.sebInstructionService = sebInstructionService;
 | 
					        this.sebInstructionService = sebInstructionService;
 | 
				
			||||||
        this.examAdminService = examAdminService;
 | 
					        this.examAdminService = examAdminService;
 | 
				
			||||||
 | 
					        this.clientIndicatorFactory = clientIndicatorFactory;
 | 
				
			||||||
        this.distributedPingCache = distributedPingCache;
 | 
					        this.distributedPingCache = distributedPingCache;
 | 
				
			||||||
        this.isDistributedSetup = sebInstructionService.getWebserviceInfo().isDistributed();
 | 
					        this.isDistributedSetup = sebInstructionService.getWebserviceInfo().isDistributed();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -702,6 +705,13 @@ public class SEBClientConnectionServiceImpl implements SEBClientConnectionServic
 | 
				
			||||||
        this.sebInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
 | 
					        this.sebInstructionService.confirmInstructionDone(connectionToken, instructionConfirm);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Result<ClientConnectionData> getIndicatorValues(final ClientConnection clientConnection) {
 | 
				
			||||||
 | 
					        return Result.tryCatch(() -> new ClientConnectionData(
 | 
				
			||||||
 | 
					                clientConnection,
 | 
				
			||||||
 | 
					                this.clientIndicatorFactory.createFor(clientConnection, true)));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void checkExamRunning(final Long examId) {
 | 
					    private void checkExamRunning(final Long examId) {
 | 
				
			||||||
        if (examId != null && !this.examSessionService.isExamRunning(examId)) {
 | 
					        if (examId != null && !this.examSessionService.isExamRunning(examId)) {
 | 
				
			||||||
            examNotRunningException(examId);
 | 
					            examNotRunningException(examId);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static final Logger log = LoggerFactory.getLogger(AbstractClientIndicator.class);
 | 
					    private static final Logger log = LoggerFactory.getLogger(AbstractClientIndicator.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected final DistributedIndicatorValueService distributedPingCache;
 | 
					    protected final DistributedIndicatorValueService distributedIndicatorValueService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected Long indicatorId = -1L;
 | 
					    protected Long indicatorId = -1L;
 | 
				
			||||||
    protected Long examId = -1L;
 | 
					    protected Long examId = -1L;
 | 
				
			||||||
| 
						 | 
					@ -38,9 +38,9 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected long lastUpdate = 0;
 | 
					    protected long lastUpdate = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public AbstractClientIndicator(final DistributedIndicatorValueService distributedPingCache) {
 | 
					    public AbstractClientIndicator(final DistributedIndicatorValueService distributedIndicatorValueService) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.distributedPingCache = distributedPingCache;
 | 
					        this.distributedIndicatorValueService = distributedIndicatorValueService;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,8 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!this.cachingEnabled && this.active) {
 | 
					        if (!this.cachingEnabled && this.active) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                this.ditributedIndicatorValueRecordId = this.distributedPingCache.initIndicatorForConnection(
 | 
					                this.ditributedIndicatorValueRecordId =
 | 
				
			||||||
 | 
					                        this.distributedIndicatorValueService.initIndicatorForConnection(
 | 
				
			||||||
                                connectionId,
 | 
					                                connectionId,
 | 
				
			||||||
                                getType(),
 | 
					                                getType(),
 | 
				
			||||||
                                initValue());
 | 
					                                initValue());
 | 
				
			||||||
| 
						 | 
					@ -94,7 +95,7 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            this.ditributedIndicatorValueRecordId = this.distributedPingCache.initIndicatorForConnection(
 | 
					            this.ditributedIndicatorValueRecordId = this.distributedIndicatorValueService.initIndicatorForConnection(
 | 
				
			||||||
                    this.connectionId,
 | 
					                    this.connectionId,
 | 
				
			||||||
                    getType(),
 | 
					                    getType(),
 | 
				
			||||||
                    initValue());
 | 
					                    initValue());
 | 
				
			||||||
| 
						 | 
					@ -126,18 +127,18 @@ public abstract class AbstractClientIndicator implements ClientIndicator {
 | 
				
			||||||
    public double getValue() {
 | 
					    public double getValue() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.initialized && !this.cachingEnabled && this.active
 | 
					        if (this.initialized && !this.cachingEnabled && this.active
 | 
				
			||||||
                && this.lastUpdate != this.distributedPingCache.lastUpdate()) {
 | 
					                && this.lastUpdate != this.distributedIndicatorValueService.lastUpdate()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (this.ditributedIndicatorValueRecordId == null) {
 | 
					            if (this.ditributedIndicatorValueRecordId == null) {
 | 
				
			||||||
                this.tryRecoverIndicatorRecord();
 | 
					                this.tryRecoverIndicatorRecord();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            final Long indicatorValue = this.distributedPingCache
 | 
					            final Long indicatorValue = this.distributedIndicatorValueService
 | 
				
			||||||
                    .getIndicatorValue(this.ditributedIndicatorValueRecordId);
 | 
					                    .getIndicatorValue(this.ditributedIndicatorValueRecordId);
 | 
				
			||||||
            if (indicatorValue != null) {
 | 
					            if (indicatorValue != null) {
 | 
				
			||||||
                this.currentValue = indicatorValue.doubleValue();
 | 
					                this.currentValue = indicatorValue.doubleValue();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.lastUpdate = this.distributedPingCache.lastUpdate();
 | 
					            this.lastUpdate = this.distributedIndicatorValueService.lastUpdate();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return this.currentValue;
 | 
					        return this.currentValue;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,7 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // update active indicator value record on persistent when caching is not enabled
 | 
					            // update active indicator value record on persistent when caching is not enabled
 | 
				
			||||||
            if (this.active && this.ditributedIndicatorValueRecordId != null) {
 | 
					            if (this.active && this.ditributedIndicatorValueRecordId != null) {
 | 
				
			||||||
                this.distributedPingCache.updateIndicatorValue(
 | 
					                this.distributedIndicatorValueService.updateIndicatorValue(
 | 
				
			||||||
                        this.ditributedIndicatorValueRecordId,
 | 
					                        this.ditributedIndicatorValueRecordId,
 | 
				
			||||||
                        numberOfLogs.longValue());
 | 
					                        numberOfLogs.longValue());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ public abstract class AbstractLogLevelCountIndicator extends AbstractLogIndicato
 | 
				
			||||||
    private void valueChanged(final String eventText) {
 | 
					    private void valueChanged(final String eventText) {
 | 
				
			||||||
        if (this.tags == null || this.tags.length == 0 || hasTag(eventText)) {
 | 
					        if (this.tags == null || this.tags.length == 0 || hasTag(eventText)) {
 | 
				
			||||||
            if (super.ditributedIndicatorValueRecordId != null) {
 | 
					            if (super.ditributedIndicatorValueRecordId != null) {
 | 
				
			||||||
                this.distributedPingCache.incrementIndicatorValue(super.ditributedIndicatorValueRecordId);
 | 
					                this.distributedIndicatorValueService.incrementIndicatorValue(super.ditributedIndicatorValueRecordId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.currentValue = getValue() + 1d;
 | 
					            this.currentValue = getValue() + 1d;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator {
 | 
				
			||||||
    private void valueChanged(final String text, final double value) {
 | 
					    private void valueChanged(final String text, final double value) {
 | 
				
			||||||
        if (this.tags == null || this.tags.length == 0 || hasTag(text)) {
 | 
					        if (this.tags == null || this.tags.length == 0 || hasTag(text)) {
 | 
				
			||||||
            if (super.ditributedIndicatorValueRecordId != null) {
 | 
					            if (super.ditributedIndicatorValueRecordId != null) {
 | 
				
			||||||
                if (!this.distributedPingCache.updateIndicatorValueAsync(
 | 
					                if (!this.distributedIndicatorValueService.updateIndicatorValueAsync(
 | 
				
			||||||
                        this.ditributedIndicatorValueRecordId,
 | 
					                        this.ditributedIndicatorValueRecordId,
 | 
				
			||||||
                        Double.valueOf(value).longValue())) {
 | 
					                        Double.valueOf(value).longValue())) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,7 @@ public abstract class AbstractLogNumberIndicator extends AbstractLogIndicator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // update active indicator value record on persistent when caching is not enabled
 | 
					                // update active indicator value record on persistent when caching is not enabled
 | 
				
			||||||
                if (this.active && this.ditributedIndicatorValueRecordId != null) {
 | 
					                if (this.active && this.ditributedIndicatorValueRecordId != null) {
 | 
				
			||||||
                    this.distributedPingCache.updateIndicatorValue(
 | 
					                    this.distributedIndicatorValueService.updateIndicatorValue(
 | 
				
			||||||
                            this.ditributedIndicatorValueRecordId,
 | 
					                            this.ditributedIndicatorValueRecordId,
 | 
				
			||||||
                            numericValue.longValue());
 | 
					                            numericValue.longValue());
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,6 @@ import java.util.Collections;
 | 
				
			||||||
import java.util.EnumSet;
 | 
					import java.util.EnumSet;
 | 
				
			||||||
import java.util.Set;
 | 
					import java.util.Set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.exam.Indicator;
 | 
					 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientEvent.EventType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public abstract class AbstractPingIndicator extends AbstractClientIndicator {
 | 
					public abstract class AbstractPingIndicator extends AbstractClientIndicator {
 | 
				
			||||||
| 
						 | 
					@ -23,16 +22,6 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator {
 | 
				
			||||||
        super(distributedPingCache);
 | 
					        super(distributedPingCache);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void init(
 | 
					 | 
				
			||||||
            final Indicator indicatorDefinition,
 | 
					 | 
				
			||||||
            final Long connectionId,
 | 
					 | 
				
			||||||
            final boolean active,
 | 
					 | 
				
			||||||
            final boolean cachingEnabled) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        super.init(indicatorDefinition, connectionId, active, cachingEnabled);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Set<EventType> observedEvents() {
 | 
					    public Set<EventType> observedEvents() {
 | 
				
			||||||
        return this.EMPTY_SET;
 | 
					        return this.EMPTY_SET;
 | 
				
			||||||
| 
						 | 
					@ -50,7 +39,7 @@ public abstract class AbstractPingIndicator extends AbstractClientIndicator {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.distributedPingCache.updatePingAsync(this.ditributedIndicatorValueRecordId);
 | 
					            this.distributedIndicatorValueService.updatePingAsync(this.ditributedIndicatorValueRecordId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,8 +35,8 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private boolean hidden = false;
 | 
					    private boolean hidden = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public PingIntervalClientIndicator(final DistributedIndicatorValueService distributedPingCache) {
 | 
					    public PingIntervalClientIndicator(final DistributedIndicatorValueService distributedIndicatorValueService) {
 | 
				
			||||||
        super(distributedPingCache);
 | 
					        super(distributedIndicatorValueService);
 | 
				
			||||||
        this.cachingEnabled = true;
 | 
					        this.cachingEnabled = true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,7 +83,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (this.initialized && !this.cachingEnabled && this.active
 | 
					        if (this.initialized && !this.cachingEnabled && this.active
 | 
				
			||||||
                && this.lastUpdate != this.distributedPingCache.lastUpdate()) {
 | 
					                && this.lastUpdate != this.distributedIndicatorValueService.lastUpdate()) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            final long currentTimeMillis = DateTimeUtils.currentTimeMillis();
 | 
					            final long currentTimeMillis = DateTimeUtils.currentTimeMillis();
 | 
				
			||||||
            this.currentValue = computeValueAt(currentTimeMillis);
 | 
					            this.currentValue = computeValueAt(currentTimeMillis);
 | 
				
			||||||
| 
						 | 
					@ -110,7 +110,7 @@ public final class PingIntervalClientIndicator extends AbstractPingIndicator {
 | 
				
			||||||
    public final double computeValueAt(final long timestamp) {
 | 
					    public final double computeValueAt(final long timestamp) {
 | 
				
			||||||
        if (super.ditributedIndicatorValueRecordId != null) {
 | 
					        if (super.ditributedIndicatorValueRecordId != null) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            final Long lastPing = this.distributedPingCache
 | 
					            final Long lastPing = this.distributedIndicatorValueService
 | 
				
			||||||
                    .getIndicatorValue(super.ditributedIndicatorValueRecordId);
 | 
					                    .getIndicatorValue(super.ditributedIndicatorValueRecordId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return (lastPing != null)
 | 
					            return (lastPing != null)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,26 +12,37 @@ import java.util.Collection;
 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.stream.Collectors;
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import javax.servlet.http.HttpServletRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.apache.commons.lang3.StringUtils;
 | 
					import org.apache.commons.lang3.StringUtils;
 | 
				
			||||||
import org.mybatis.dynamic.sql.SqlTable;
 | 
					import org.mybatis.dynamic.sql.SqlTable;
 | 
				
			||||||
 | 
					import org.springframework.http.MediaType;
 | 
				
			||||||
 | 
					import org.springframework.util.MultiValueMap;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.PathVariable;
 | 
				
			||||||
import org.springframework.web.bind.annotation.RequestMapping;
 | 
					import org.springframework.web.bind.annotation.RequestMapping;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RequestMethod;
 | 
				
			||||||
 | 
					import org.springframework.web.bind.annotation.RequestParam;
 | 
				
			||||||
import org.springframework.web.bind.annotation.RestController;
 | 
					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.API.BulkActionType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.API.BulkActionType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
					import ch.ethz.seb.sebserver.gbl.api.EntityType;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
 | 
					import ch.ethz.seb.sebserver.gbl.model.EntityDependency;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.Page;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnection;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.gbl.model.session.ClientConnectionData;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
 | 
					import ch.ethz.seb.sebserver.gbl.model.user.UserRole;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
					import ch.ethz.seb.sebserver.gbl.profile.WebServiceProfile;
 | 
				
			||||||
import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
					import ch.ethz.seb.sebserver.gbl.util.Result;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordDynamicSqlSupport;
 | 
					import ch.ethz.seb.sebserver.webservice.datalayer.batis.mapper.ClientConnectionRecordDynamicSqlSupport;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.PaginationService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.AuthorizationService;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.authorization.UserService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.bulkaction.BulkActionService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.dao.ClientConnectionDAO;
 | 
				
			||||||
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.dao.UserActivityLogDAO;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.dao.UserActivityLogDAO;
 | 
				
			||||||
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.session.SEBClientConnectionService;
 | 
				
			||||||
import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
 | 
					import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@WebServiceProfile
 | 
					@WebServiceProfile
 | 
				
			||||||
| 
						 | 
					@ -39,13 +50,16 @@ import ch.ethz.seb.sebserver.webservice.servicelayer.validation.BeanValidationSe
 | 
				
			||||||
@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_CONNECTION_ENDPOINT)
 | 
					@RequestMapping("${sebserver.webservice.api.admin.endpoint}" + API.SEB_CLIENT_CONNECTION_ENDPOINT)
 | 
				
			||||||
public class ClientConnectionController extends ReadonlyEntityController<ClientConnection, ClientConnection> {
 | 
					public class ClientConnectionController extends ReadonlyEntityController<ClientConnection, ClientConnection> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final SEBClientConnectionService sebClientConnectionService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected ClientConnectionController(
 | 
					    protected ClientConnectionController(
 | 
				
			||||||
            final AuthorizationService authorization,
 | 
					            final AuthorizationService authorization,
 | 
				
			||||||
            final BulkActionService bulkActionService,
 | 
					            final BulkActionService bulkActionService,
 | 
				
			||||||
            final ClientConnectionDAO clientConnectionDAO,
 | 
					            final ClientConnectionDAO clientConnectionDAO,
 | 
				
			||||||
            final UserActivityLogDAO userActivityLogDAO,
 | 
					            final UserActivityLogDAO userActivityLogDAO,
 | 
				
			||||||
            final PaginationService paginationService,
 | 
					            final PaginationService paginationService,
 | 
				
			||||||
            final BeanValidationService beanValidationService) {
 | 
					            final BeanValidationService beanValidationService,
 | 
				
			||||||
 | 
					            final SEBClientConnectionService sebClientConnectionService) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        super(authorization,
 | 
					        super(authorization,
 | 
				
			||||||
                bulkActionService,
 | 
					                bulkActionService,
 | 
				
			||||||
| 
						 | 
					@ -53,6 +67,60 @@ public class ClientConnectionController extends ReadonlyEntityController<ClientC
 | 
				
			||||||
                userActivityLogDAO,
 | 
					                userActivityLogDAO,
 | 
				
			||||||
                paginationService,
 | 
					                paginationService,
 | 
				
			||||||
                beanValidationService);
 | 
					                beanValidationService);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.sebClientConnectionService = sebClientConnectionService;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @RequestMapping(
 | 
				
			||||||
 | 
					            path = API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT,
 | 
				
			||||||
 | 
					            method = RequestMethod.GET,
 | 
				
			||||||
 | 
					            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
 | 
				
			||||||
 | 
					            produces = MediaType.APPLICATION_JSON_VALUE)
 | 
				
			||||||
 | 
					    public Page<ClientConnectionData> getClientConnectionDataPage(
 | 
				
			||||||
 | 
					            @RequestParam(
 | 
				
			||||||
 | 
					                    name = API.PARAM_INSTITUTION_ID,
 | 
				
			||||||
 | 
					                    required = true,
 | 
				
			||||||
 | 
					                    defaultValue = UserService.USERS_INSTITUTION_AS_DEFAULT) final Long institutionId,
 | 
				
			||||||
 | 
					            @RequestParam(name = Page.ATTR_PAGE_NUMBER, required = false) final Integer pageNumber,
 | 
				
			||||||
 | 
					            @RequestParam(name = Page.ATTR_PAGE_SIZE, required = false) final Integer pageSize,
 | 
				
			||||||
 | 
					            @RequestParam(name = Page.ATTR_SORT, required = false) final String sort,
 | 
				
			||||||
 | 
					            @RequestParam final MultiValueMap<String, String> allRequestParams,
 | 
				
			||||||
 | 
					            final HttpServletRequest request) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // at least current user must have read access for specified entity type within its own institution
 | 
				
			||||||
 | 
					        checkReadPrivilege(institutionId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final FilterMap filterMap = new FilterMap(allRequestParams, request.getQueryString());
 | 
				
			||||||
 | 
					        populateFilterMap(filterMap, institutionId, sort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        final Page<ClientConnectionData> page = this.paginationService.getPage(
 | 
				
			||||||
 | 
					                pageNumber,
 | 
				
			||||||
 | 
					                pageSize,
 | 
				
			||||||
 | 
					                sort,
 | 
				
			||||||
 | 
					                getSQLTableOfEntity().name(),
 | 
				
			||||||
 | 
					                () -> getAllData(filterMap))
 | 
				
			||||||
 | 
					                .getOrThrow();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return page;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @RequestMapping(
 | 
				
			||||||
 | 
					            path = API.SEB_CLIENT_CONNECTION_DATA_ENDPOINT + API.MODEL_ID_VAR_PATH_SEGMENT,
 | 
				
			||||||
 | 
					            method = RequestMethod.GET,
 | 
				
			||||||
 | 
					            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
 | 
				
			||||||
 | 
					            produces = MediaType.APPLICATION_JSON_VALUE)
 | 
				
			||||||
 | 
					    public ClientConnectionData getClientConnectionDataBy(@PathVariable final String modelId) {
 | 
				
			||||||
 | 
					        return this.sebClientConnectionService
 | 
				
			||||||
 | 
					                .getIndicatorValues(super.getBy(modelId))
 | 
				
			||||||
 | 
					                .getOrThrow();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private Result<Collection<ClientConnectionData>> getAllData(final FilterMap filterMap) {
 | 
				
			||||||
 | 
					        return getAll(filterMap)
 | 
				
			||||||
 | 
					                .map(connection -> connection.stream()
 | 
				
			||||||
 | 
					                        .map(this.sebClientConnectionService::getIndicatorValues)
 | 
				
			||||||
 | 
					                        .flatMap(Result::onErrorLogAndSkip)
 | 
				
			||||||
 | 
					                        .collect(Collectors.toList()));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ sebserver.webservice.clean-db-on-startup=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# webservice configuration
 | 
					# webservice configuration
 | 
				
			||||||
sebserver.init.adminaccount.gen-on-init=false
 | 
					sebserver.init.adminaccount.gen-on-init=false
 | 
				
			||||||
sebserver.webservice.distributed=false
 | 
					sebserver.webservice.distributed=true
 | 
				
			||||||
#sebserver.webservice.master.delay.threshold=10000
 | 
					#sebserver.webservice.master.delay.threshold=10000
 | 
				
			||||||
sebserver.webservice.http.external.scheme=http
 | 
					sebserver.webservice.http.external.scheme=http
 | 
				
			||||||
sebserver.webservice.http.external.servername=localhost
 | 
					sebserver.webservice.http.external.servername=localhost
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue