/*
* Copyright 2015-2017 Hewlett Packard Enterprise Development Company, L.P.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License.
*/
package com.hp.autonomy.frontend.find.core.web;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.hp.autonomy.frontend.configuration.ConfigService;
import com.hp.autonomy.frontend.configuration.LoginTypes;
import com.hp.autonomy.frontend.configuration.authentication.AuthenticationConfig;
import com.hp.autonomy.frontend.find.core.beanconfiguration.AppConfiguration;
import com.hp.autonomy.frontend.find.core.configuration.FindConfig;
import com.hp.autonomy.frontend.find.core.configuration.FindConfigBuilder;
import com.hp.autonomy.frontend.find.core.export.service.MetadataNode;
import com.hp.autonomy.searchcomponents.core.config.FieldInfo;
import com.hp.autonomy.searchcomponents.core.fields.FieldDisplayNameGenerator;
import com.hpe.bigdata.frontend.spring.authentication.AuthenticationInformationRetriever;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import static com.hp.autonomy.frontend.find.core.metrics.MetricsConfiguration.FIND_METRICS_ENABLED_PROPERTY;
public abstract class FindController<C extends FindConfig<C, B>, B extends FindConfigBuilder<C, B>> {
public static final String APP_PATH = "/public";
public static final String LOGIN_PATH = "/login";
public static final String DEFAULT_LOGIN_PAGE = "/loginPage";
public static final String CONFIG_PATH = "/config";
protected final ConfigService<C> configService;
private final ControllerUtils controllerUtils;
private final AuthenticationInformationRetriever<?, ? extends Principal> authenticationInformationRetriever;
private final ConfigService<? extends AuthenticationConfig<?>> authenticationConfigService;
private final FieldDisplayNameGenerator fieldDisplayNameGenerator;
@Value(AppConfiguration.GIT_COMMIT_PROPERTY)
private String gitCommit;
@Value(AppConfiguration.APPLICATION_RELEASE_VERSION_PROPERTY)
private String releaseVersion;
@Value(FIND_METRICS_ENABLED_PROPERTY)
private boolean metricsEnabled;
protected FindController(final ControllerUtils controllerUtils,
final AuthenticationInformationRetriever<?, ? extends Principal> authenticationInformationRetriever,
final ConfigService<? extends AuthenticationConfig<?>> authenticationConfigService,
final ConfigService<C> configService,
final FieldDisplayNameGenerator fieldDisplayNameGenerator) {
this.controllerUtils = controllerUtils;
this.authenticationInformationRetriever = authenticationInformationRetriever;
this.authenticationConfigService = authenticationConfigService;
this.configService = configService;
this.fieldDisplayNameGenerator = fieldDisplayNameGenerator;
}
protected abstract Map<String, Object> getPublicConfig();
protected abstract List<MetadataNode> getMetadataNodes();
@RequestMapping("/")
public void index(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
final String contextPath = request.getContextPath();
if(LoginTypes.DEFAULT.equals(authenticationConfigService.getConfig().getAuthentication().getMethod())) {
response.sendRedirect(contextPath + DEFAULT_LOGIN_PAGE);
} else {
response.sendRedirect(contextPath + APP_PATH);
}
}
@RequestMapping(value = APP_PATH + "/**", method = RequestMethod.GET)
public ModelAndView mainPage(final HttpServletRequest request) throws JsonProcessingException {
final String username = authenticationInformationRetriever.getAuthentication().getName();
final Collection<String> roles = authenticationInformationRetriever.getAuthentication()
.getAuthorities()
.stream()
.map((Function<GrantedAuthority, String>)GrantedAuthority::getAuthority)
.collect(Collectors.toCollection(LinkedList::new));
final FindConfig<C, B> findConfig = configService.getConfig();
final Map<String, Object> config = new HashMap<>();
config.put(MvcConstants.APPLICATION_PATH.value(), APP_PATH);
config.put(MvcConstants.USERNAME.value(), username);
config.put(MvcConstants.ROLES.value(), roles);
config.put(MvcConstants.GIT_COMMIT.value(), gitCommit);
config.put(MvcConstants.RELEASE_VERSION.value(), releaseVersion);
config.put(MvcConstants.METRICS_ENABLED.value(), metricsEnabled);
config.put(MvcConstants.MAP.value(), findConfig.getMap());
config.put(MvcConstants.UI_CUSTOMIZATION.value(), findConfig.getUiCustomization());
config.put(MvcConstants.SAVED_SEARCH_CONFIG.value(), findConfig.getSavedSearchConfig());
config.put(MvcConstants.MIN_SCORE.value(), findConfig.getMinScore());
config.put(MvcConstants.FIELDS_INFO.value(), getFieldConfigWithDisplayNames(findConfig));
config.put(MvcConstants.TOPIC_MAP_MAX_RESULTS.value(), findConfig.getTopicMapMaxResults());
config.put(MvcConstants.METADATA_FIELD_INFO.value(), getMetadataNodeInfo());
config.putAll(getPublicConfig());
final Map<String, Object> attributes = new HashMap<>();
attributes.put(MvcConstants.GIT_COMMIT.value(), gitCommit);
attributes.put(MvcConstants.CONFIG.value(), controllerUtils.convertToJson(config));
attributes.put(MvcConstants.BASE_URL.value(), RequestUtils.buildBaseUrl(request));
return new ModelAndView(ViewNames.APP.viewName(), attributes);
}
@RequestMapping(value = LOGIN_PATH, method = RequestMethod.GET)
public ModelAndView login() {
final Map<String, Object> attributes = new HashMap<>();
attributes.put(MvcConstants.GIT_COMMIT.value(), gitCommit);
return new ModelAndView(ViewNames.LOGIN.viewName(), attributes);
}
@RequestMapping(value = CONFIG_PATH, method = RequestMethod.GET)
public ModelAndView config() {
final Map<String, Object> attributes = new HashMap<>();
attributes.put(MvcConstants.GIT_COMMIT.value(), gitCommit);
return new ModelAndView(ViewNames.CONFIG.viewName(), attributes);
}
private Map<String, FieldInfo<?>> getMetadataNodeInfo() {
return getMetadataNodes().stream()
.collect(toLinkedMap(MetadataNode::getName, node -> FieldInfo.builder()
.id(node.getName())
.displayName(node.getDisplayName())
.type(node.getFieldType())
.build()));
}
private Map<String, FieldInfo<?>> getFieldConfigWithDisplayNames(final FindConfig<C, B> findConfig) {
return findConfig.getFieldsInfo().getFieldConfig().entrySet().stream()
.collect(toLinkedMap(Map.Entry::getKey, entry -> entry.getValue().toBuilder()
.displayName(Optional.ofNullable(entry.getValue().getDisplayName())
.orElseGet(() -> fieldDisplayNameGenerator.prettifyFieldName(entry.getValue().getId())))
.build()));
}
private <T, K, U> Collector<T, ?, Map<K, U>> toLinkedMap(
final Function<? super T, ? extends K> keyMapper,
final Function<? super T, ? extends U> valueMapper) {
return Collectors.toMap(keyMapper, valueMapper,
(u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
},
LinkedHashMap::new);
}
}