Commit b2ae983d authored by bnimajneb's avatar bnimajneb
Browse files

translation service | 

cachestats service | 
more data
parent 7ac872a4
......@@ -133,6 +133,34 @@ public enum SumarisServerConfigurationOption implements ConfigOptionDef {
String.class,
false),
SECURITY_MOCK_USERNAME(
"sumaris.server.security.mock.username",
"sumaris.server.config.option.security.mock.username.description",
"demo",
String.class,
false),
SECURITY_MOCK_PASSWORD(
"sumaris.server.security.mock.password",
"sumaris.server.config.option.security.mock.password.description",
"demo",
String.class,
false),
SECURITY_MOCK_USER_ID(
"sumaris.server.security.mock.userId",
"sumaris.server.config.option.security.mock.userId.description",
"263",
Integer.class,
false),
UI_SECURITY_TYPE(
"sumaris.server.security.type",
"sumaris.server.config.option.security.type.description",
"mock",
String.class,
false),
;
/** Configuration key. */
......
......@@ -23,6 +23,7 @@ package net.sumaris.server.http.graphql;
*/
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
......@@ -37,13 +38,16 @@ import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.*;
import java.util.stream.Stream;
@RestController
public class GraphQLRestController {
private static final Logger log = LoggerFactory.getLogger(GraphQLRestController.class);
private static final List<Locale> AVAILABLE_LANG = Lists.newArrayList( Locale.FRENCH, Locale.ENGLISH );
private final GraphQL graphQL;
private final ObjectMapper objectMapper;
......@@ -59,11 +63,17 @@ public class GraphQLRestController {
@PostMapping(value = GraphQLPaths.BASE_PATH, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@ResponseBody
public Map<String, Object> indexFromAnnotated(@RequestBody Map<String, Object> request, HttpServletRequest rawRequest) {
Map<String, Object> variables = GraphQLHelper.getVariables(request, objectMapper);
String lang = findLanguageFromHttpHeaders(rawRequest, AVAILABLE_LANG);
ExecutionResult executionResult = graphQL.execute(ExecutionInput.newExecutionInput()
.query((String)request.get("query"))
.operationName((String)request.get("operationName"))
.variables(GraphQLHelper.getVariables(request, objectMapper))
.context(rawRequest)
.variables(variables)
.context(lang)
.build());
return GraphQLHelper.processExecutionResult(executionResult);
......@@ -71,4 +81,37 @@ public class GraphQLRestController {
/* -- private methods -- */
/**
* This method sort languages by the book
* ex : Accept-Language: de; q=1.0, en; q=0.5
* would prioritize 'de' because 'q=1.0' is higher priority than 'q=0.5'
*
* @param rawRequest the httpRequest containing the Accept-Language headers to use
* @return the lang suffix
*/
protected String findLanguageFromHttpHeaders(HttpServletRequest rawRequest, List<Locale> available){
String acceptedLang = rawRequest.getHeader("Accept-Language");
return Stream.of(acceptedLang.split(","))
.map(s -> {
String[] split = s.trim().split(";");
if (!(split.length > 1))
return null;
String[] subSplit = split[1].split("=");
if (!(subSplit.length > 1))
return null;
Double v = Double.parseDouble(subSplit[1]);
return new AbstractMap.SimpleEntry<>(split[0], v);
})
.filter(Objects::nonNull)
.filter(l -> available.stream() .anyMatch(loca ->
l.getKey().startsWith(loca.toString())))
.sorted((f1, f2) -> Double.compare(f2.getValue(), f1.getValue() ))
.map(AbstractMap.SimpleEntry::getKey)
.findFirst()
.orElse("en-GB"); // FIXME default value from ... ?
}
}
......@@ -24,6 +24,7 @@ package net.sumaris.server.http.graphql.administration;
import com.google.common.base.Preconditions;
import io.leangen.graphql.annotations.*;
import net.sf.ehcache.CacheManager;
import net.sumaris.core.dao.technical.SortDirection;
import net.sumaris.core.exception.SumarisTechnicalException;
import net.sumaris.core.model.administration.programStrategy.AcquisitionLevel;
......@@ -33,6 +34,7 @@ import net.sumaris.core.service.administration.PersonService;
import net.sumaris.core.service.administration.programStrategy.ProgramService;
import net.sumaris.core.service.administration.programStrategy.StrategyService;
import net.sumaris.core.service.referential.ReferentialService;
import net.sumaris.core.service.technical.EhCacheStatistics;
import net.sumaris.core.util.crypto.MD5Util;
import net.sumaris.core.vo.administration.programStrategy.PmfmStrategyVO;
import net.sumaris.core.vo.administration.programStrategy.ProgramVO;
......@@ -46,6 +48,7 @@ import net.sumaris.server.config.SumarisServerConfiguration;
import net.sumaris.server.http.rest.RestPaths;
import net.sumaris.server.http.security.IsAdmin;
import net.sumaris.server.http.security.IsGuest;
import net.sumaris.server.http.security.IsUser;
import net.sumaris.server.service.administration.AccountService;
import net.sumaris.server.service.technical.ChangesPublisherService;
import org.apache.commons.lang3.StringUtils;
......@@ -59,6 +62,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Service
......@@ -299,7 +303,7 @@ public class AdministrationGraphQLService {
public List<PmfmStrategyVO> getProgramPmfms(
@GraphQLArgument(name = "program", description = "A valid program code") String programLabel,
@GraphQLArgument(name = "acquisitionLevel", description = "A valid acquisition level (e.g. 'TRIP', 'OPERATION', 'PHYSICAL_GEAR')") String acquisitionLevel
) {
, String locale) {
Preconditions.checkNotNull(programLabel, "Missing program");
ProgramVO program = programService.getByLabel(programLabel);
......@@ -307,7 +311,7 @@ public class AdministrationGraphQLService {
// ALl pmfm from the program
if (StringUtils.isBlank(acquisitionLevel)) {
List<PmfmStrategyVO> res = strategyService.getPmfmStrategies(program.getId());
List<PmfmStrategyVO> res = strategyService.getPmfmStrategies(program.getId(), locale);
return res;
}
......@@ -329,6 +333,16 @@ public class AdministrationGraphQLService {
}
@Autowired
protected EhCacheStatistics cacheStatistics;
@GraphQLQuery(name = "getCacheStats", description = "Get cache statistics")
public Map<String,Long> getCacheStats( ) {
return cacheStatistics.getCacheDetails();
}
public DepartmentVO fillLogo(DepartmentVO department) {
if (department != null && department.isHasLogo() && StringUtils.isBlank(department.getLogo()) && StringUtils.isNotBlank(department.getLabel())) {
department.setLogo(departmentLogoUrl.replace("{label}", department.getLabel()));
......
......@@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Repository;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
......@@ -80,7 +81,7 @@ public class ProgramDaoImpl extends HibernateDaoSupport implements ProgramDao {
.setParameter(labelParam, label);
try {
return toProgramVO(q.getSingleResult());
} catch(EmptyResultDataAccessException e) {
} catch(NoResultException | EmptyResultDataAccessException e) {
return null;
}
}
......
......@@ -36,7 +36,7 @@ import java.util.List;
public interface StrategyDao {
@Cacheable(cacheNames = CacheNames.PMFM_BY_PROGRAM_ID, key = "#programId", unless = "#result == null")
List<PmfmStrategyVO> getPmfmStrategies(int programId);
List<PmfmStrategyVO> getPmfmStrategies(int programId, String locale);
List<PmfmStrategyVO> getPmfmStrategiesByAcquisitionLevel(int programId, int acquisitionLevelId);
......
......@@ -35,6 +35,7 @@ import net.sumaris.core.model.referential.*;
import net.sumaris.core.model.referential.gear.Gear;
import net.sumaris.core.model.referential.pmfm.Parameter;
import net.sumaris.core.model.referential.pmfm.Pmfm;
import net.sumaris.core.service.referential.TranslationService;
import net.sumaris.core.vo.administration.programStrategy.PmfmStrategyVO;
import net.sumaris.core.vo.referential.ParameterValueType;
import net.sumaris.core.vo.referential.ReferentialVO;
......@@ -61,6 +62,11 @@ public class StrategyDaoImpl extends HibernateDaoSupport implements StrategyDao
@Autowired
private ReferentialDao referentialDao;
@Autowired
private TranslationService translate;
private int unitIdNone;
@PostConstruct
......@@ -69,7 +75,7 @@ public class StrategyDaoImpl extends HibernateDaoSupport implements StrategyDao
}
@Override
public List<PmfmStrategyVO> getPmfmStrategies(int programId) {
public List<PmfmStrategyVO> getPmfmStrategies(int programId, String locale) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<PmfmStrategy> query = builder.createQuery(PmfmStrategy.class);
......@@ -93,6 +99,10 @@ public class StrategyDaoImpl extends HibernateDaoSupport implements StrategyDao
.setParameter(programIdParam, programId)
.getResultStream()
.map(this::toPmfmStrategyVO)
.map(x->{
translate.translateReferentials(x.getQualitativeValues(), "fr");
return x;
})
.collect(Collectors.toList());
}
......@@ -123,6 +133,7 @@ public class StrategyDaoImpl extends HibernateDaoSupport implements StrategyDao
.setParameter(acquisitionLevelIdParam, acquisitionLevelId)
.getResultStream()
.map(this::toPmfmStrategyVO)
.collect(Collectors.toList());
}
......
......@@ -124,6 +124,18 @@ public class CacheConfiguration {
return Caches.createEternalHeapCache(ehcache(), CacheNames.TAXON_NAME_BY_TAXON_REFERENCE_ID, 600);
}
@Bean
public EhCacheFactoryBean translationsAll() {
return Caches.createEternalHeapCache(ehcache(), CacheNames.TRANSLATIONS, 2);
}
@Bean
public EhCacheFactoryBean translationsById() {
return Caches.createEternalHeapCache(ehcache(), CacheNames.TRANSLATIONS_BY_ID, 600);
}
/* protected */
protected net.sf.ehcache.CacheManager ehcache() {
return cacheManager != null ? cacheManager : ehcacheFactory().getObject();
......
......@@ -39,4 +39,9 @@ public interface CacheNames {
String QUERY_CACHE_NAME = "org.hibernate.cache.spi.QueryResultsRegion";
String TIMESTAMPS_REGION_CACHE_NAME = "org.hibernate.cache.spi.TimestampsRegion";
String TRANSLATIONS = "net.sumaris.core.dao.referential.Translations";
String TRANSLATIONS_BY_ID = "net.sumaris.core.dao.referential.TranslationsById";
}
......@@ -45,7 +45,7 @@ import net.sumaris.core.model.referential.taxon.TaxonGroup;
import net.sumaris.core.model.referential.taxon.TaxonGroupType;
import net.sumaris.core.model.referential.taxon.TaxonName;
import net.sumaris.core.model.referential.taxon.TaxonomicLevel;
import net.sumaris.core.model.referential.transcribing.TranscribingItem;
import net.sumaris.core.model.referential.transcribing.*;
import net.sumaris.core.vo.filter.ReferentialFilterVO;
import net.sumaris.core.vo.referential.IReferentialVO;
import net.sumaris.core.vo.referential.ReferentialTypeVO;
......@@ -104,9 +104,13 @@ public class ReferentialDaoImpl extends HibernateDaoSupport implements Referenti
// Program/strategy
Program.class,
Strategy.class,
AcquisitionLevel.class
//test
, TranscribingItem.class
AcquisitionLevel.class,
// Transcribing
TranscribingItemType.class,
TranscribingSide.class,
TranscribingSystem.class,
ObjectType.class
), Class::getSimpleName);
private Map<String, PropertyDescriptor> levelPropertyNameMap = initLevelPropertyNameMap();
......@@ -132,7 +136,11 @@ public class ReferentialDaoImpl extends HibernateDaoSupport implements Referenti
I18n.n("sumaris.persistence.table.qualitativeValue");
I18n.n("sumaris.persistence.table.program");
I18n.n("sumaris.persistence.table.acquisitionLevel");
I18n.n("sumaris.persistence.table.transcribingItem");
//I18n.n("sumaris.persistence.table.transcribingItem");
I18n.n("sumaris.persistence.table.transcribingItemType");
I18n.n("sumaris.persistence.table.transcribingSystem");
I18n.n("sumaris.persistence.table.transcribingSide");
I18n.n("sumaris.persistence.table.objectType");
}
protected static Map<String, PropertyDescriptor> initLevelPropertyNameMap() {
......@@ -154,6 +162,7 @@ public class ReferentialDaoImpl extends HibernateDaoSupport implements Referenti
result.put(TaxonName.class.getSimpleName(), BeanUtils.getPropertyDescriptor(TaxonGroup.class, TaxonName.PROPERTY_TAXONOMIC_LEVEL));
result.put(Strategy.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Strategy.class, Strategy.PROPERTY_PROGRAM));
result.put(Metier.class.getSimpleName(), BeanUtils.getPropertyDescriptor(Metier.class, Metier.PROPERTY_GEAR));
result.put(TranscribingItemType.class.getSimpleName(), BeanUtils.getPropertyDescriptor(TranscribingItemType.class, TranscribingItemType.PROPERTY_OBJECT_TYPE));
return result;
}
......
package net.sumaris.core.dao.referential;
import net.sumaris.core.dao.cache.CacheNames;
import net.sumaris.core.model.referential.transcribing.Translate;
import org.springframework.cache.annotation.Cacheable;
import java.util.List;
import java.util.Optional;
public interface TranslationDao {
public List<Translate> getTranslations();
public Optional<Translate> getTranslation(String typeName, String objectId, String locale);
public Optional<String> getTranslationOf(String typeName, String objectId, String locale);
public void printAll();
}
package net.sumaris.core.dao.referential;
import net.sumaris.core.dao.cache.CacheNames;
import net.sumaris.core.dao.technical.hibernate.HibernateDaoSupport;
import net.sumaris.core.model.referential.transcribing.Translate;
import net.sumaris.core.model.referential.transcribing.TranscribingItem;
import net.sumaris.core.model.referential.transcribing.TranscribingItemType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import javax.annotation.PostConstruct;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Repository("translationDao")
public class TranslationDaoImpl extends HibernateDaoSupport implements TranslationDao {
private static final Logger log = LoggerFactory.getLogger(TranslationDaoImpl.class);
@Cacheable(cacheNames = CacheNames.TRANSLATIONS)
public List<Translate> getTranslations() {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery query = builder.createQuery(Translate.class);
Root<TranscribingItem> transcribe = query.from(TranscribingItem.class);
Join<TranscribingItem, TranscribingItemType> typeJoin = transcribe.join(TranscribingItem.PROPERTY_TYPE, JoinType.INNER);
query.multiselect(
transcribe.get(TranscribingItem.PROPERTY_OBJECT_ID),
transcribe.get(TranscribingItem.PROPERTY_EXTERNAL_CODE),
typeJoin.get(TranscribingItemType.PROPERTY_LABEL),
typeJoin.get(TranscribingItemType.PROPERTY_ID)
);
// query.where(predicates.stream().toArray(Predicate[]::new));
TypedQuery<Translate> typedQuery = entityManager.createQuery(query);
return typedQuery.getResultList();
}
@Override
@Cacheable(cacheNames = CacheNames.TRANSLATIONS_BY_ID, key = "#typeName + '_' + #objectId")
public Optional<Translate> getTranslation(String typeName, String objectId, String locale) {
String loc = locale.substring(0, 2).toUpperCase();
//log.info("Searching translation for " + table + " " + loc + " item " + id);
return getTranslations().stream()
.filter(t -> t.getObjectId().equals(objectId))
.filter(t -> t.getTypeName().equals(typeName + "." + loc) ||
t.getTypeName().equals(typeName + "_" + loc))
//.peek(x -> log.info("Found translation for " + x.toString()))
.findAny()
;
}
@Cacheable(cacheNames = CacheNames.TRANSLATIONS_BY_ID, key = "#typeName + '_' + #objectId")
public Optional<String> getTranslationOf(String typeName, String objectId, String locale) {
log.info("all translations:\n" + getTranslations().stream()
.map(Translate::toString)
.collect(Collectors.joining("\n")));
return getTranslation(typeName, objectId, locale).map(Translate::getExternalCode);
}
public void printAll() {
log.info("all translations:\n" + getTranslations().stream()
.map(Translate::toString)
.collect(Collectors.joining("\n")));
}
private void voiid() {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
List<Integer> xParam2 = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19));
CriteriaQuery<TranscribingItem> itemsQ = builder.createQuery(TranscribingItem.class);
Root<TranscribingItem> rootIT = itemsQ.from(TranscribingItem.class);
Expression xp = rootIT.get(TranscribingItem.PROPERTY_TYPE).get(TranscribingItemType.PROPERTY_ID).in(xParam2);
CriteriaQuery<TranscribingItem> joined = itemsQ.select(rootIT).where(xp);
log.info("test my request " + getEntityManager()
.createQuery(joined)
.getResultStream()
.map(ti -> ti.getId() + " " + ti.getObjectId() + " " + ti.getExternalCode())
.collect(Collectors.joining("\n")));
}
}
package net.sumaris.core.model.referential.transcribing;
/*-
* #%L
* SUMARiS:: Core
* %%
* Copyright (C) 2018 SUMARiS Consortium
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import lombok.Data;
import net.sumaris.core.model.referential.IItemReferentialEntity;
import net.sumaris.core.model.referential.Status;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@Table(name = "object_type")
public class ObjectType implements IItemReferentialEntity {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@Column(name = "creation_date", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
@Column(name = "update_date")
@Temporal(TemporalType.TIMESTAMP)
private Date updateDate;
@Column(nullable = false, length = LENGTH_LABEL)
private String label;
@Column(nullable = false, length = LENGTH_NAME)
private String name;
@Column
private String description;
@Column(length = LENGTH_COMMENTS)
private String comments;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status_fk", nullable = false)
private Status status;
}
......@@ -23,48 +23,48 @@ package net.sumaris.core.model.referential.transcribing;
*/
import lombok.Data;
import net.sumaris.core.dao.technical.model.IUpdateDateEntityBean;
import net.sumaris.core.model.referential.IItemReferentialEntity;
import net.sumaris.core.model.referential.Status;
import net.sumaris.core.model.referential.ValidityStatus;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@Table(name = "transcribing_item")
public class TranscribingItem implements IItemReferentialEntity {
@Table(name = "transcribing_item", uniqueConstraints={
@UniqueConstraint(columnNames = {"object_id", "external_code", "transcribing_item_type_fk"})
})
public class TranscribingItem implements IUpdateDateEntityBean<Integer, Date> {
public static final String PROPERTY_TYPE = "type";
public static final String PROPERTY_EXTERNAL_CODE = "externalCode";
public static final String PROPERTY_OBJECT_ID = "objectId";
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "status_fk", nullable = false)
private Status status;
@Column(name = "creation_date", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date creationDate;