diff --git a/CHANGELOG b/CHANGELOG index 23f682142be771adf7bdd821d793d104544ec423..58f8734fe19016b816bff246dcf1330e6a4dbec9 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,16 @@ minerva (12.0.0) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 14 Dec 2017 16:00:00 +0200 +minerva (11.0.7) stable; urgency=medium + * Bug fix: redirection added when anonymous tries to access secured map + * Bug fix: loading time of custom overlays is reduced + * Bug fix: there should be no problem with symlink when upgrading debian + package + * Bug fix: number of services changed API address to https: pmceurope + (pubmed), uniprot, ensembl, hgnc, recon, ctd database + + -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 18 Jan 2018 16:00:00 +0200 + minerva (11.0.6) stable; urgency=medium * Bug fix: fix a bug when entering invalid mirna id diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/cache/PermanentDatabaseLevelCache.java b/annotation/src/main/java/lcsb/mapviewer/annotation/cache/PermanentDatabaseLevelCache.java index 08c0fabbfe8fa51f82996ee01cbe73c63facd78b..986b24bc69cd2ba2108e176e2b59129f321b5adb 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/cache/PermanentDatabaseLevelCache.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/cache/PermanentDatabaseLevelCache.java @@ -45,29 +45,29 @@ public class PermanentDatabaseLevelCache extends XmlParser /** * This class represents new thread task for quering database. - * + * * @author Piotr Gawron - * + * */ private final class QueryTask implements Callable<CacheQuery> { /** * Identifier of cached entry. - * + * * @see CacheQuery#query */ private String query; /** * Type of cached entry. - * + * * @see CacheQuery#type */ private CacheType type; /** * Default constructor. - * + * * @param query * {@link #query} * @param type @@ -79,45 +79,47 @@ public class PermanentDatabaseLevelCache extends XmlParser this.type = type; } - @Override - public CacheQuery call() throws Exception { - logger.debug("Query task call"); - dbUtils.createSessionForCurrentThread(); - logger.debug("Query task session started"); - CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); - logger.debug("Query task data retrieved"); - dbUtils.closeSessionForCurrentThread(); - logger.debug("Query task return"); - return entry; - } + @Override + public CacheQuery call() throws Exception { + logger.debug("Query task call"); + try { + dbUtils.createSessionForCurrentThread(); + logger.debug("Query task session started"); + CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); + logger.debug("Query task data retrieved"); + return entry; + } finally { + dbUtils.closeSessionForCurrentThread(); + } + } } /** * This class represents new thread task for refreshing element in db. - * + * * @author Piotr Gawron - * + * */ private final class RefreshTask implements Callable<CacheQuery> { /** * Identifier of cached entry. - * + * * @see CacheQuery#query */ private String query; /** * Type of cached entry. - * + * * @see CacheQuery#type */ private CacheType type; /** * Default constructor. - * + * * @param query * {@link #query} * @param type @@ -183,42 +185,42 @@ public class PermanentDatabaseLevelCache extends XmlParser /** * This class represents new thread task for adding entry to database. - * + * * @author Piotr Gawron - * + * */ private final class AddTask implements Callable<CacheQuery> { /** * Identifier of cached entry. - * + * * @see CacheQuery#query */ private String query; /** * Type of cached entry. - * + * * @see CacheQuery#type */ private CacheType type; /** * Value to cache. - * + * * @see CacheQuery#value */ private String value; /** * How long should the entry be valid in days. - * + * */ private int validDays; /** * Default constructor. - * + * * @param query * {@link #query} * @param type @@ -234,57 +236,60 @@ public class PermanentDatabaseLevelCache extends XmlParser this.validDays = validDays; } - @Override - public CacheQuery call() throws Exception { - logger.debug("Add task call"); - dbUtils.createSessionForCurrentThread(); - CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); - - if (entry == null) { - entry = new CacheQuery(); - entry.setQuery((String) query); - entry.setAccessed(Calendar.getInstance()); - } else { - entry.setAccessed(Calendar.getInstance()); - } - entry.setValue(value); - entry.setType(type); - Calendar expires = Calendar.getInstance(); - expires.add(Calendar.DAY_OF_MONTH, validDays); - entry.setExpires(expires); - - getCacheQueryDao().add(entry); - dbUtils.closeSessionForCurrentThread(); - return entry; - } + @Override + public CacheQuery call() throws Exception { + logger.debug("Add task call"); + try { + dbUtils.createSessionForCurrentThread(); + CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); + + if (entry == null) { + entry = new CacheQuery(); + entry.setQuery((String) query); + entry.setAccessed(Calendar.getInstance()); + } else { + entry.setAccessed(Calendar.getInstance()); + } + entry.setValue(value); + entry.setType(type); + Calendar expires = Calendar.getInstance(); + expires.add(Calendar.DAY_OF_MONTH, validDays()); + entry.setExpires(expires); + + getCacheQueryDao().add(entry); + return entry; + } finally { + dbUtils.closeSessionForCurrentThread(); + } + } } /** * This class represents new thread task for removing entry from database. - * + * * @author Piotr Gawron - * + * */ private final class RemoveTask implements Callable<CacheQuery> { /** * Identifier of cached entry. - * + * * @see CacheQuery#query */ private String query; /** * Type of cached entry. - * + * * @see CacheQuery#type */ private CacheType type; /** * Default constructor. - * + * * @param query * {@link #query} * @param type @@ -296,25 +301,28 @@ public class PermanentDatabaseLevelCache extends XmlParser this.type = type; } - @Override - public CacheQuery call() throws Exception { - logger.debug("Remove task call"); - dbUtils.createSessionForCurrentThread(); - CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); - if (entry != null) { - getCacheQueryDao().delete(entry); - } - dbUtils.closeSessionForCurrentThread(); - return entry; - } + @Override + public CacheQuery call() throws Exception { + logger.debug("Remove task call"); + try { + dbUtils.createSessionForCurrentThread(); + CacheQuery entry = getCacheQueryDao().getByQuery((String) query, type); + if (entry != null) { + getCacheQueryDao().delete(entry); + } + return entry; + } finally { + dbUtils.closeSessionForCurrentThread(); + } + } } /** * This class represents new thread task for invalidating entry in database. - * + * * @author Piotr Gawron - * + * */ private final class InvalidateTask implements Callable<CacheQuery> { @@ -330,7 +338,7 @@ public class PermanentDatabaseLevelCache extends XmlParser /** * Default constructor. - * + * * @param query * {@link #query} * @param type @@ -529,7 +537,7 @@ public class PermanentDatabaseLevelCache extends XmlParser /** * Executes and returns result of the task provided in the parameter. This * method is blocking (it's waiting for the results). - * + * * @param task * task to be executed * @return value returned by the task diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/cache/WebPageDownloader.java b/annotation/src/main/java/lcsb/mapviewer/annotation/cache/WebPageDownloader.java index c03944fd8fb1507836139a32d05ffcde9b3864d3..5f468f1ad11eb4a49bf8d5599622191751bfe16a 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/cache/WebPageDownloader.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/cache/WebPageDownloader.java @@ -20,8 +20,8 @@ import org.apache.log4j.Logger; import lcsb.mapviewer.annotation.services.WrongResponseCodeIOException; /** - * This class helps to download webpages. The pages are downloaded in separate - * thred, due to the fact that sometimes java socket can hang (related JVM bug: + * This class helps to download web pages. The pages are downloaded in separate + * thread, due to the fact that sometimes java socket can hang (related JVM bug: * https://bugs.openjdk.java.net/browse/JDK-8075484 ). * * @author Piotr Gawron @@ -40,13 +40,13 @@ public class WebPageDownloader { /** * Hard timeout (threads are terminated) of http connection that access data - * across internet. + * across Internet. */ private static final int HTTP_CONNECTION_TIMEOUT_SEC = 120; /** * How much time should the thread sleep before another try to access the - * webpage that thrown INTERNAL SERVER ERROR http response. + * web page that thrown INTERNAL SERVER ERROR http response. */ private static final int HTTP_INTERNAL_ERROR_RECONNECT_SLEEP_TIME = 2000; @@ -55,15 +55,15 @@ public class WebPageDownloader { * receiving INTERNAL SERVER ERROR http response. */ private static final int HTTP_INTERNAL_ERROR_RECONNECT_TIMES = 2; - - - + + + /** - * Returns content of the webpage identified by url using GET. + * Returns content of the web page identified by url. * * @param accessUrl - * url of a webpage - * @return content of the webpage identified by url + * url of a web page + * @return content of the web page identified by url * @throws IOException * thrown when there is any problem with accessing webpage */ @@ -71,18 +71,18 @@ public class WebPageDownloader { return getFromNetwork(accessUrl, "GET", null); } - + /** - * Returns content of the webpage identified by url. The HTTP query is done + * Returns content of the webpage identified by url. The HTTP query is done * using the provided POST if postData is not null. - * - * + * + * * @param accessUrl * url of a webpage * @param httpRequestMethod * type of HTTP request (GET, POST, PUT, PATCH, DELETE, ...) * @param data - * string to be sent in the body of the + * string to be sent in the body of the * @return content of the webpage identified by url * @throws IOException * thrown when there is any problem with accessing webpage @@ -90,7 +90,7 @@ public class WebPageDownloader { public String getFromNetwork(String accessUrl, String httpRequestMethod, String data) throws IOException { /** - * Tasks that retrieves content from webpage + * Tasks that retrieves content from web page * * @author Piotr Gawron * @@ -107,17 +107,17 @@ public class WebPageDownloader { // connect to the server, if HTTP_INTERNAL_ERROR occurred then try to // reconnect HTTP_INTERNAL_ERROR_RECONNECT_TIMES times while (code == HttpURLConnection.HTTP_INTERNAL_ERROR || code == HttpURLConnection.HTTP_NOT_FOUND) { - urlConn = openConnection(accessUrl); + urlConn = openConnection(accessUrl); urlConn.addRequestProperty("User-Agent", "minerva-framework"); - + urlConn.setRequestMethod(httpRequestMethod); - if (data != null) { - urlConn.setDoOutput(true); + if (data != null) { + urlConn.setDoOutput(true); DataOutputStream wr = new DataOutputStream(urlConn.getOutputStream()); wr.writeBytes(data); - wr.close(); + wr.close(); } - + try { urlConn.connect(); code = urlConn.getResponseCode(); @@ -174,7 +174,7 @@ public class WebPageDownloader { * argument. * * @param accessUrl - * url to the webpagae + * url to the web page * @return {@link HttpURLConnection connection} to the url given in the * argument * @throws MalformedURLException diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChemicalParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChemicalParser.java index 20351481b2d36412f64f2277bafa28ca1d9a6bdc..81d15a4530cfe77dae90131724c5513680f7b4ef 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChemicalParser.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/ChemicalParser.java @@ -69,18 +69,18 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Home page of ctd database. */ - static final String URL = "http://ctdbase.org/"; + static final String URL = "https://ctdbase.org/"; /** * URL to get a list of chemicals by disease id. */ - public static final String DISEASE_URL = "http://ctdbase.org/detail.go?6578706f7274=1&d-1332398-e=5&view=chem&" + public static final String DISEASE_URL = "https://ctdbase.org/detail.go?6578706f7274=1&d-1332398-e=5&view=chem&" + "type=disease&acc=MESH%3A"; /** * URL to get a list of chemicals by gene id. */ - public static final String DISEASE_GENE_URL = "http://ctdbase.org/detail.go?slimTerm=all&6578706f7274=1&qid=3464576&" + public static final String DISEASE_GENE_URL = "https://ctdbase.org/detail.go?slimTerm=all&6578706f7274=1&qid=3464576&" + "d-1332398-e=5&view=disease&type=gene&assnType=curated&acc="; /** @@ -173,7 +173,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic private MeSHParser meshParser; /** - * + * */ public ChemicalParser() { super(ChemicalParser.class); @@ -252,7 +252,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Serializes list of chemicalId-chemicalName pairs. - * + * * @param chemicals * list of objects to serialize * @return serialized string @@ -267,7 +267,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Deserializes list of chemicalId-chemicalName pairs. - * + * * @param chemicalNode * string to deserialize * @return list of chemicalId-chemicalName pairs @@ -420,7 +420,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Method that creates chemical from a tab separated row from ctd database. Data * looks like (line wrapping added for clarity): - * + * * <pre> 1. Disease Name Disease ID Direct Evidence Inference Network Inference Score Reference Count 2. Drug-Induced Liver Injury MESH:D056486 1-(2-trifluoromethoxyphenyl)-2-nitroethanone|1,4-bis(2-(3,5-dichloropyridyloxy))benzene| @@ -433,7 +433,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic pirinixic acid|Polyphenols|Polysaccharides|potassium chromate(VI)|propiconazole|Quercetin|resveratrol|rosiglitazone|Rotenone| Streptozocin|Tetrachlorodibenzodioxin|titanium dioxide|Tretinoin|usnic acid|Valproic Acid|Vincristine|Zinc|zinc chloride 190.67 634 * </pre> - * + * * @param lineValues * line split by tab separator * @param chemID @@ -480,7 +480,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic if (entrez == null) { invalidHgnc.add(md); } else { - String query = "http://ctdbase.org/detail.go?type=gene&view=ixn&chemAcc=" + chemID.getResource() + "&acc=" + String query = "https://ctdbase.org/detail.go?type=gene&view=ixn&chemAcc=" + chemID.getResource() + "&acc=" + entrez.getResource(); String referencesPage = getWebPageContent(query); Matcher matcher = pattern.matcher(referencesPage); @@ -488,7 +488,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic idx.add(matcher.group(1)); } for (String string : idx) { - String query2 = "http://ctdbase.org/detail.go?6578706f7274=1&d-1340579-e=5&type=relationship&ixnId=" + String query2 = "https://ctdbase.org/detail.go?6578706f7274=1&d-1340579-e=5&type=relationship&ixnId=" + string; String referencesPage2 = getWebPageContent(query2); String[] lines = referencesPage2.split("\n"); @@ -535,7 +535,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Returns list of chemicals for given set of target genes related to the * disease. - * + * * @param targets * set of target genes * @param diseaseMiriam @@ -592,7 +592,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Return list of chemical names that interact with a target. - * + * * @param diseaseMiriam * we want to get chemicals in context of the disease * @param target @@ -631,7 +631,7 @@ public class ChemicalParser extends CachableInterface implements IExternalServic /** * Returns list of chemicals that interact with a target. - * + * * @param target * target for which we are looking for chemicals * @param disease diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java index 851847b75d185a38b232e0edeefcd26a044e60e5..0fbcd7a00e507a8d95cb43a2491c02a565fc1610 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParser.java @@ -29,7 +29,7 @@ import lcsb.mapviewer.model.map.MiriamType; /** * This class is a backend to publically available pubmed API in - * <a href="http://europepmc.org/RestfulWebService">Europe PubMed Central </a>. + * <a href="https://europepmc.org/RestfulWebService">Europe PubMed Central </a>. * * @author Piotr Gawron * @@ -55,7 +55,9 @@ public class PubmedParser extends CachableInterface implements IExternalService /** * Version of the remote API thnat is supported by this connecting class. */ - static final String SUPPORTED_VERSION = "5.2.1"; + static final String SUPPORTED_VERSION = "5.2.2"; + + static final String API_URL = "https://www.ebi.ac.uk/europepmc/webservices/rest/"; /** * Connector used for accessing data from miriam registry. @@ -131,7 +133,7 @@ public class PubmedParser extends CachableInterface implements IExternalService result = new Article(); try { - String url = "http://www.ebi.ac.uk/europepmc/webservices/rest/search/resulttype=core&query=" + String url = API_URL+"search/resulttype=core&query=" + java.net.URLEncoder.encode("src:med ext_id:" + id, "UTF-8"); String content = getWebPageContent(url); @@ -261,7 +263,7 @@ public class PubmedParser extends CachableInterface implements IExternalService @Override public ExternalServiceStatus getServiceStatus() { - ExternalServiceStatus status = new ExternalServiceStatus("Europe PubMed Central", "http://europepmc.org/RestfulWebService"); + ExternalServiceStatus status = new ExternalServiceStatus("Europe PubMed Central", "https://europepmc.org/RestfulWebService"); GeneralCacheInterface cacheCopy = getCache(); this.setCache(null); @@ -292,7 +294,7 @@ public class PubmedParser extends CachableInterface implements IExternalService */ public String getApiVersion() throws PubmedSearchException { try { - String url = "http://www.ebi.ac.uk/europepmc/webservices/rest/search/resulttype=core&query=src%3Amed+ext_id%3A23644949"; + String url = API_URL+"search/resulttype=core&query=src%3Amed+ext_id%3A23644949"; String content = getWebPageContent(url); diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotator.java index 27cd669cc89e4ef80fd72248a15226dfb7a12941..07692f2bf2b14a16a8667aafc10c6b81f7897694 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotator.java @@ -29,7 +29,7 @@ import lcsb.mapviewer.modelutils.map.ElementUtils; /** * This class is responsible for connecting to - * <a href="http://rest.ensembl.org">Ensembl API</a> and annotate elements with + * <a href="https://rest.ensembl.org">Ensembl API</a> and annotate elements with * information taken from this service. * * @@ -41,12 +41,12 @@ public class EnsemblAnnotator extends ElementAnnotator implements IExternalServi /** * Version of the rest API that is supported by this annotator. */ - static final String SUPPORTED_VERSION = "6.1"; + static final String SUPPORTED_VERSION = "6.2"; /** - * Url address of ensembl restfull service. + * Url address of ensembl restful service. */ - private static final String REST_SERVICE_URL = "http://rest.ensembl.org/xrefs/id/"; + private static final String REST_SERVICE_URL = "https://rest.ensembl.org/xrefs/id/"; /** * Suffix that is needed for getting proper result using @@ -57,7 +57,7 @@ public class EnsemblAnnotator extends ElementAnnotator implements IExternalServi /** * Url used for retrieving version of the restful API. */ - private static final String REST_SERVICE_VERSION_URL = "http://rest.ensembl.org/info/rest?content-type=text/xml"; + private static final String REST_SERVICE_VERSION_URL = "https://rest.ensembl.org/info/rest?content-type=text/xml"; /** * Default constructor. diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotator.java index 4010497e526fa1ac097b6113b18f6f1235d2c928..b7cd593c8d99a78aeea7d1b947a28397df869160 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/HgncAnnotator.java @@ -16,6 +16,7 @@ import lcsb.mapviewer.annotation.services.ExternalServiceStatus; import lcsb.mapviewer.annotation.services.ExternalServiceStatusType; import lcsb.mapviewer.annotation.services.IExternalService; import lcsb.mapviewer.annotation.services.MiriamConnector; +import lcsb.mapviewer.annotation.services.WrongResponseCodeIOException; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.common.exception.InvalidXmlSchemaException; import lcsb.mapviewer.model.map.BioEntity; @@ -31,7 +32,7 @@ import lcsb.mapviewer.modelutils.map.ElementUtils; /** * This class is responsible for connecting to - * <a href="http://rest.genenames.org/">HGNC restfull API</a> and annotate + * <a href="https://rest.genenames.org/">HGNC restfull API</a> and annotate * elements with information taken from this service. * * @@ -43,7 +44,7 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService /** * Address of HGNC API that should be used for retrieving data. */ - private static final String REST_API_URL = "http://rest.genenames.org/fetch/"; + private static final String REST_API_URL = "https://rest.genenames.org/fetch/"; @Autowired private MiriamConnector miriamConnector; @@ -236,19 +237,21 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService } } - } - } - } - } - } catch (Exception e) { - throw new AnnotatorException(e); - } - } - } + } + } + } + } + } catch (WrongResponseCodeIOException e) { + logger.warn(prefix + "Cannot find information for element."); + } catch (Exception e) { + throw new AnnotatorException(e); + } + } + } /** * Creates query url for given {@link MiriamType#HGNC} identifier. - * + * * @param id * {@link MiriamType#HGNC} identifier * @return url to restful api webpage for given identifier @@ -259,7 +262,7 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService /** * Creates query url for given {@link MiriamType#HGNC_SYMBOL}. - * + * * @param name * {@link MiriamType#HGNC_SYMBOL} * @return url to restful api webpage for given hgnc symbol @@ -271,7 +274,7 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService /** * Converts {@link MiriamType#HGNC}/{@link MiriamType#HGNC_SYMBOL} identifier * into list of {@link MiriamType#UNIPROT} identifiers. - * + * * @param miriamData * {@link MiriamData} with {@link MiriamType#HGNC} identifier * @return list of {@link MiriamData} with {@link MiriamType#UNIPROT} @@ -301,38 +304,41 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService } else { Node entry = getNode("doc", resultNode.getChildNodes()); - NodeList list = entry.getChildNodes(); - for (int i = 0; i < list.getLength(); i++) { - Node node = list.item(i); - if (node.getNodeType() == Node.ELEMENT_NODE) { - if (node.getNodeName().equals("arr")) { - String type = getNodeAttr("name", node); - if (type.equals("uniprot_ids")) { - NodeList uniprotList = node.getChildNodes(); - for (int j = 0; j < uniprotList.getLength(); j++) { - Node uniprotNode = uniprotList.item(j); - if (uniprotNode.getNodeType() == Node.ELEMENT_NODE) { - if (uniprotNode.getNodeName().equals("str")) { - result.add(new MiriamData(MiriamType.UNIPROT, uniprotNode.getTextContent())); - } - } - } - } - } - } - } - } - return result; - } catch (Exception e) { - throw new AnnotatorException(e); - } + NodeList list = entry.getChildNodes(); + for (int i = 0; i < list.getLength(); i++) { + Node node = list.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + if (node.getNodeName().equals("arr")) { + String type = getNodeAttr("name", node); + if (type.equals("uniprot_ids")) { + NodeList uniprotList = node.getChildNodes(); + for (int j = 0; j < uniprotList.getLength(); j++) { + Node uniprotNode = uniprotList.item(j); + if (uniprotNode.getNodeType() == Node.ELEMENT_NODE) { + if (uniprotNode.getNodeName().equals("str")) { + result.add(new MiriamData(MiriamType.UNIPROT, uniprotNode.getTextContent())); + } + } + } + } + } + } + } + } + return result; + } catch (WrongResponseCodeIOException e) { + logger.warn("No HGNC data found for id: "+miriamData); + return new ArrayList<>(); + } catch (Exception e) { + throw new AnnotatorException(e); + } } /** * Converts {@link MiriamType#HGNC} identifier into * {@link MiriamType#HGNC_SYMBOL}. - * + * * @param miriamData * {@link MiriamData} with {@link MiriamType#HGNC} identifier * @return {@link MiriamData} with {@link MiriamType#HGNC_SYMBOL} @@ -381,7 +387,7 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService /** * Returns <code>true</code> if the {@link MiriamData} given in the parameter is * a valid {@link MiriamType#HGNC} or {@link MiriamType#HGNC_SYMBOL}. - * + * * @param md * {@link MiriamData} to validate * @return <code>true</code> if the {@link MiriamData} given in the parameter is @@ -403,7 +409,7 @@ public class HgncAnnotator extends ElementAnnotator implements IExternalService /** * Transforms HGNC symbol into {@link MiriamType#ENTREZ} identifier. - * + * * @param md * hgnc symbol * @return {@link MiriamType#ENTREZ} identifier for a given hgnc symbol diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java index 3e26f3006a7d190ec35450ba5f9c388cc2d4e8af..c006d49ed4106d58c1323c1bf5dcd930001bcf36 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/ReconAnnotator.java @@ -43,7 +43,7 @@ public class ReconAnnotator extends ElementAnnotator implements IExternalService /** * Address of annotation rest service for reactions. */ - private static final String REACTION_ANNOTATION_URL_PREFIX = "http://vmh.uni.lu/_api/reactions/?page_size=10000&format=json&search="; + private static final String REACTION_ANNOTATION_URL_PREFIX = "https://vmh.uni.lu/_api/reactions/?page_size=10000&format=json&search="; /** * Class used for some simple operations on {@link BioEntity} elements. diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java index 997494bd6562f088eb1fd2a0ce46aa3f15912f6b..332354bed41576191fcd66fc72d10f5f8e4eacf1 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/UniprotAnnotator.java @@ -134,7 +134,7 @@ public class UniprotAnnotator extends ElementAnnotator implements IExternalServi * @return url to uniprot restfull API about uniprot entry */ private String getUniprotUrl(String uniprotId) { - return "http://www.uniprot.org/uniprot/" + uniprotId + ".txt"; + return "https://www.uniprot.org/uniprot/" + uniprotId + ".txt"; } /** diff --git a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChemicalParserTest.java b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChemicalParserTest.java index 36e85c27dbde7245cabfc955df81540b5f293fa1..8b318a426b463aa72401a8eaf6c93e6d022e445e 100644 --- a/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChemicalParserTest.java +++ b/annotation/src/test/java/lcsb/mapviewer/annotation/services/ChemicalParserTest.java @@ -193,7 +193,7 @@ public class ChemicalParserTest extends AnnotationTestFunctions { } } - + @Test public void testGetChemicalBySynonym() throws Exception { try { @@ -209,7 +209,7 @@ public class ChemicalParserTest extends AnnotationTestFunctions { } } - + @Test public void testFindByInvalidIdFromChemicalList() throws Exception { @@ -584,7 +584,7 @@ public class ChemicalParserTest extends AnnotationTestFunctions { // remove info about single publication from cache (so we will have to download // it) chemicalParser.getCache().removeByQuery( - "http://ctdbase.org/detail.go?6578706f7274=1&d-1340579-e=5&type=relationship&ixnId=4802115", + "https://ctdbase.org/detail.go?6578706f7274=1&d-1340579-e=5&type=relationship&ixnId=4802115", chemicalParser.getCacheType()); // disallow to use cache for first query (it will be directly about drug), diff --git a/debian/template/postinst b/debian/template/postinst index 44228b77f9db6a5d9d50ee43d4917a886fe73f9e..2f2c3863a88d87c25e0f49a67687296261a2a16e 100644 --- a/debian/template/postinst +++ b/debian/template/postinst @@ -64,7 +64,7 @@ case "$1" in #availble when new war is deployed from debian package, so tomcat will catch SQL exception and stop deployment invoke-rc.d $TOMCAT_PACKAGE stop || true rm -rf /var/lib/$TOMCAT_PACKAGE/webapps/minerva - ln -s /usr/share/minerva/minerva.war /var/lib/$TOMCAT_PACKAGE/webapps/minerva.war + ln -sf /usr/share/minerva/minerva.war /var/lib/$TOMCAT_PACKAGE/webapps/minerva.war invoke-rc.d $TOMCAT_PACKAGE start ;; *) diff --git a/frontend-js/src/main/js/GuiConnector.js b/frontend-js/src/main/js/GuiConnector.js index 34f05f2b6725a81a42e0403dad51c5a388a024ec..c3b40206069b7aa812bba3f7df4999fd97bbcd54 100644 --- a/frontend-js/src/main/js/GuiConnector.js +++ b/frontend-js/src/main/js/GuiConnector.js @@ -175,6 +175,33 @@ GuiConnector.prototype.hideProcessing = function () { $(self._processingDialog).dialog("close"); }; +GuiConnector.prototype.alert = function (error, redirectIfSecurityError) { + if (redirectIfSecurityError === undefined) { + redirectIfSecurityError = false; + } + if (redirectIfSecurityError && error instanceof SecurityError && ServerConnector.getSessionData().getLogin() === "anonymous") { + window.location.href = ServerConnector.getServerBaseUrl() + "login.xhtml?from=" + encodeURI(window.location.href); + } else { + var self = returnThisOrSingleton(this); + logger.error(error); + if (self._errorDialog === undefined) { + self._errorDialog = document.createElement("div"); + self._errorDialogContent = document.createElement("div"); + self._errorDialog.appendChild(self._errorDialogContent); + document.body.appendChild(self._errorDialog); + $(self._errorDialog).dialog({ + classes: { + "ui-dialog": "ui-state-error" + }, + modal: true, + title: "ERROR" + }).siblings('.ui-dialog-titlebar').css("background", "red"); + } + self._errorDialogContent.innerHTML = self.getErrorMessageForError(error); + $(self._errorDialog).dialog("open"); + } +}; + GuiConnector.prototype.getErrorMessageForError = function (error) { var message = error; if (message instanceof SecurityError) { @@ -200,27 +227,6 @@ GuiConnector.prototype.getErrorMessageForError = function (error) { return message; }; -GuiConnector.prototype.alert = function (error) { - var self = returnThisOrSingleton(this); - logger.error(error); - if (self._errorDialog === undefined) { - self._errorDialog = document.createElement("div"); - self._errorDialogContent = document.createElement("div"); - self._errorDialog.appendChild(self._errorDialogContent); - document.body.appendChild(self._errorDialog); - $(self._errorDialog).dialog({ - classes: { - "ui-dialog": "ui-state-error" - }, - modal: true, - title: "ERROR" - }).siblings('.ui-dialog-titlebar').css("background", "red"); - } - self._errorDialogContent.innerHTML = self.getErrorMessageForError(error); - $(self._errorDialog).dialog("open"); - -}; - GuiConnector.prototype.info = function (message) { var self = returnThisOrSingleton(this); if (self._infoDialog === undefined) { diff --git a/frontend-js/src/test/js/minerva-test.js b/frontend-js/src/test/js/minerva-test.js index 9c743127841a5697b4725329b25ad589302997dc..fd53d158f8fde5b329803cefb433c6bb179b17bf 100644 --- a/frontend-js/src/test/js/minerva-test.js +++ b/frontend-js/src/test/js/minerva-test.js @@ -1,268 +1,293 @@ -"use strict"; - -require("./mocha-config"); - -var minerva = require('../../main/js/minerva'); -var ServerConnectorMock = require('./ServerConnector-mock'); -var ProxyAccessPlugin = require('./plugin/ProxyAccessPlugin'); - -var chai = require('chai'); -var assert = chai.assert; -var logger = require('./logger'); - -describe('minerva global', function () { - beforeEach(function () { - global.ServerConnector = undefined; - }); - - afterEach(function () { - global.ServerConnector = ServerConnectorMock; - }); - - describe('create', function () { - it('default', function () { - var options = null; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - - return minerva.create(options); - }).then(function (result) { - assert.ok(result); - assert.equal(logger.getWarnings().length, 0); - return result.destroy(); - }); - }); - it('invalid projectId', function () { - var options = { - projectId: "unknownId", - element: testDiv - }; - return minerva.create(options).then(function () { - assert.ok(false); - }, function (error) { - assert.ok(error.message.indexOf("Project with given id doesn't exist") >= 0); - }); - }); - it('with overview', function () { - helper.setUrl("http://test/?id=complex_model_with_images"); - var customMap; - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createOptions(project); - - return minerva.create(options); - }).then(function (result) { - customMap = result; - assert.ok(result); - assert.equal(logger.getWarnings().length, 0); - var showOverviewButton = document.getElementsByName("showOverviewButton")[0]; - return showOverviewButton.onclick(); - }).then(function () { - return customMap.destroy(); - }); - }); - }); - - - it("showComments", function () { - var options = null; - var map ; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - return minerva.create(options); - }).then(function (result) { - map = result; - var commentCheckbox = document.getElementsByName("commentCheckbox")[0]; - commentCheckbox.checked = true; - return commentCheckbox.onclick(); - }).then(function () { - assert.ok(ServerConnectorMock.getSessionData(options.getProject()).getShowComments()); - return map.destroy(); - }); - }); - - describe("constructor", function () { - - it("with GET zoom param", function () { - helper.setUrl("http://test/?zoom=5"); - var options; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - return minerva.create(options); - }).then(function (result) { - var sessionData = ServerConnectorMock.getSessionData(options.getProject()); - assert.equal(sessionData.getZoomLevel(options.getProject().getModel()), 5); - return result.destroy(); - }); - }); - - it("with GET coordinates param", function () { - helper.setUrl("http://test/?x=5&y=6"); - var options; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - return minerva.create(options); - }).then(function (result) { - var center = ServerConnectorMock.getSessionData(options.getProject()).getCenter(options.getProject().getModel()); - assert.ok(center instanceof google.maps.Point); - assert.equal(center.x, 5); - assert.equal(center.y, 6); - return result.destroy(); - }); - }); - - it("simple", function () { - var options = { - projectId: "sample", - element: testDiv - }; - return minerva.create(options).then(function (result) { - assert.ok(result); - result.destroy(); - }); - }); - }); - - it('create with layout', function () { - var layout, project, plugin, map; - return ServerConnectorMock.getProject().then(function (result) { - project = result; - var options = helper.createCustomMapOptions(project); - - plugin = new ProxyAccessPlugin({}); - options.getPlugins().push(plugin); - - layout = project.getModel().getLayouts()[1]; - - helper.setUrl("http://test/?layout=" + layout.getName()); - - return minerva.create(options); - }).then(function (result) { - map = result; - assert.ok(result); - // input file is not available so it's the background - return plugin.getMinervaPluginProxy().project.map.getVisibleDataOverlays(); - }).then(function (visibleDataOverlays) { - // input file is available so it's not the background file but overlay - assert.equal(visibleDataOverlays.length, 0); - assert.equal(ServerConnectorMock.getSessionData(project).getSelectedBackgroundOverlay(), layout.getId()); - assert.equal(logger.getWarnings().length, 0); - return map.destroy(); - }); - }); - - it('create with layout from session data', function () { - var layout; - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - - layout = project.getModel().getLayouts()[1]; - - ServerConnectorMock.getSessionData(project).setSelectedBackgroundOverlay(layout.getId()); - - return minerva.create(options); - }).then(function (result) { - assert.equal(ServerConnectorMock.getSessionData().getSelectedBackgroundOverlay(), layout.getId()); - return result.destroy(); - }); - }); - - it('create with layout 2', function () { - helper.setUrl("http://test/?layout=xxx"); - var globalObject, plugin; - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - plugin = new ProxyAccessPlugin(); - options.getPlugins().push(plugin); - return minerva.create(options); - }).then(function (result) { - globalObject = result; - assert.ok(result); - return plugin.getMinervaPluginProxy().project.map.getVisibleDataOverlays(); - }).then(function (visibleDataOverlays) { - // input file is available so it's not the background file but overlay - assert.equal(visibleDataOverlays.length, 1); - assert.equal(logger.getWarnings().length, 0); - return globalObject.destroy(); - }); - }); - - it('create with search overlay and GET search param', function () { - helper.setUrl("http://test/?search=s1"); - - var globalObject, plugin; - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - plugin = new ProxyAccessPlugin(); - options.getPlugins().push(plugin); - return minerva.create(options); - }).then(function (result) { - globalObject = result; - return plugin.getMinervaPluginProxy().project.map.getHighlightedBioEntities("search"); - }).then(function (elements) { - assert.ok(elements.length > 0); - return globalObject.destroy(); - }); - }); - - it('create with show submodel GET param', function () { - helper.setUrl("http://test/?submap=15781"); - - var project = helper.createProject(); - project.getModel().setId(15781); - - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - - return minerva.create(options); - }).then(function (result) { - return result.destroy(); - }); - }); - - it("constructor with touch enabled", function () { - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - options.setCustomTouchInterface(true); - return minerva.create(options).then(function (result) { - assert.ok(result); - return result.destroy(); - }); - }); - }); - - - it('create Export', function () { - var options = null; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - - return minerva.createExport(options); - }).then(function (result) { - assert.ok(result); - assert.equal(logger.getWarnings().length, 0); - }); - }); - - it('create Admin', function () { - var options = null; - return ServerConnectorMock.getProject().then(function (project) { - options = helper.createCustomMapOptions(project); - - return minerva.createAdmin(options); - }).then(function (result) { - assert.ok(result); - assert.equal(logger.getWarnings().length, 0); - result.destroy(); - }); - }); - it('getProject', function () { - return ServerConnectorMock.getProject().then(function (project) { - var options = helper.createCustomMapOptions(project); - return minerva.create(options); - }).then(function (result) { - assert.equal(result.getProject().getProjectId(), "sample"); - return result.destroy(); - }); - }); - -}); +"use strict"; + +require("./mocha-config"); + +var Alias = require('../../main/js/map/data/Alias'); +var minerva = require('../../main/js/minerva'); +var Project = require('../../main/js/map/data/Project'); +var GuiConnectorMock = require('./GuiConnector-mock'); +var SecurityError = require('../../main/js/SecurityError'); +var ServerConnectorMock = require('./ServerConnector-mock'); +var ProxyAccessPlugin = require('./plugin/ProxyAccessPlugin'); + +var chai = require('chai'); +var assert = chai.assert; +var logger = require('./logger'); + +describe('minerva global', function () { + beforeEach(function () { + global.ServerConnector = undefined; + }); + + afterEach(function () { + global.ServerConnector = ServerConnectorMock; + }); + + describe('create', function() { + it('default', function() { + var options = null; + return ServerConnectorMock.getProject().then(function(project) { + options = helper.createCustomMapOptions(project); + + return minerva.create(options); + }).then(function(result) { + assert.ok(result); + assert.equal(logger.getWarnings().length, 0); + return result.destroy(); + }); + }); + it('invalid projectId', function() { + var options = { + projectId: "unknownId", + element: testDiv + }; + return minerva.create(options).then(function () { + assert.ok(false); + }, function (error) { + assert.ok(error.message.indexOf("Project with given id doesn't exist") >= 0); + }); + }); + it('with overview', function () { + helper.setUrl("http://test/?id=complex_model_with_images"); + var customMap; + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createOptions(project); + + return minerva.create(options); + }).then(function (result) { + customMap = result; + assert.ok(result); + assert.equal(logger.getWarnings().length, 0); + var showOverviewButton = document.getElementsByName("showOverviewButton")[0]; + return showOverviewButton.onclick(); + }).then(function () { + return customMap.destroy(); + }); + }); + }); + + + it("showComments", function() { + var options = null; + var map ; + return ServerConnectorMock.getProject().then(function (project) { + options = helper.createCustomMapOptions(project); + return minerva.create(options); + }).then(function (result) { + map = result; + var commentCheckbox = document.getElementsByName("commentCheckbox")[0]; + commentCheckbox.checked = true; + return commentCheckbox.onclick(); + }).then(function() { + assert.ok(ServerConnectorMock.getSessionData(options.getProject()).getShowComments()); + return map.destroy(); + }); + }); + + describe("constructor", function () { + + it("with GET zoom param", function () { + helper.setUrl("http://test/?zoom=5"); + var options; + return ServerConnectorMock.getProject().then(function (project) { + options = helper.createCustomMapOptions(project); + return minerva.create(options); + }).then(function (result) { + var sessionData = ServerConnectorMock.getSessionData(options.getProject()); + assert.equal(sessionData.getZoomLevel(options.getProject().getModel()), 5); + return result.destroy(); + }); + }); + + it("with GET coordinates param", function () { + helper.setUrl("http://test/?x=5&y=6"); + var options; + return ServerConnectorMock.getProject().then(function (project) { + options = helper.createCustomMapOptions(project); + return minerva.create(options); + }).then(function (result) { + var center = ServerConnectorMock.getSessionData(options.getProject()).getCenter(options.getProject().getModel()); + assert.ok(center instanceof google.maps.Point); + assert.equal(center.x, 5); + assert.equal(center.y, 6); + return result.destroy(); + }); + }); + + it("simple", function () { + var options = { + projectId: "sample", + element: testDiv + }; + return minerva.create(options).then(function (result) { + assert.ok(result); + result.destroy(); + }); + }); + }); + + it('create with layout', function () { + var layout, project, plugin, map; + return ServerConnectorMock.getProject().then(function (result) { + project = result; + var options = helper.createCustomMapOptions(project); + + plugin = new ProxyAccessPlugin({}); + options.getPlugins().push(plugin); + + layout = project.getModel().getLayouts()[1]; + + helper.setUrl("http://test/?layout=" + layout.getName()); + + return minerva.create(options); + }).then(function (result) { + map = result; + assert.ok(result); + // input file is not available so it's the background + return plugin.getMinervaPluginProxy().project.map.getVisibleDataOverlays(); + }).then(function (visibleDataOverlays) { + // input file is available so it's not the background file but overlay + assert.equal(visibleDataOverlays.length, 0); + assert.equal(ServerConnectorMock.getSessionData(project).getSelectedBackgroundOverlay(), layout.getId()); + assert.equal(logger.getWarnings().length, 0); + return map.destroy(); + }); + }); + + it('create restricted map', function () { + var originalFunction = ServerConnectorMock.getProject; + ServerConnectorMock.getProject=function(){ + return Promise.reject(new SecurityError("Access denied.")); + }; + helper.setUrl("http://test/?id=restricted_sample"); + var options = { + element: testDiv, + mapDiv: testDiv, + configuration: helper.getConfiguration() + }; + + return minerva.create(options).then(function (map) { + assert.equal(null, map); + }).catch(function (e) { + assert.ok(e.message.indexOf("Access denied") >= 0); + }).finally(function(){ + ServerConnectorMock.getProject = originalFunction; + }); + }); + + it('create with layout from session data', function() { + var layout; + return ServerConnectorMock.getProject().then(function(project) { + var options = helper.createCustomMapOptions(project); + + layout = project.getModel().getLayouts()[1]; + + ServerConnectorMock.getSessionData(project).setSelectedBackgroundOverlay(layout.getId()); + + return minerva.create(options); + }).then(function (result) { + assert.equal(ServerConnectorMock.getSessionData().getSelectedBackgroundOverlay(), layout.getId()); + return result.destroy(); + }); + }); + + it('create with layout 2', function () { + helper.setUrl("http://test/?layout=xxx"); + var globalObject, plugin; + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createCustomMapOptions(project); + plugin = new ProxyAccessPlugin(); + options.getPlugins().push(plugin); + return minerva.create(options); + }).then(function (result) { + globalObject = result; + assert.ok(result); + return plugin.getMinervaPluginProxy().project.map.getVisibleDataOverlays(); + }).then(function (visibleDataOverlays) { + // input file is available so it's not the background file but overlay + assert.equal(visibleDataOverlays.length, 1); + assert.equal(logger.getWarnings().length, 0); + return globalObject.destroy(); + }); + }); + + it('create with search overlay and GET search param', function () { + helper.setUrl("http://test/?search=s1"); + + var globalObject, plugin; + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createCustomMapOptions(project); + plugin = new ProxyAccessPlugin(); + options.getPlugins().push(plugin); + return minerva.create(options); + }).then(function (result) { + globalObject = result; + return plugin.getMinervaPluginProxy().project.map.getHighlightedBioEntities("search"); + }).then(function (elements) { + assert.ok(elements.length > 0); + return globalObject.destroy(); + }); + }); + + it('create with show submodel GET param', function () { + helper.setUrl("http://test/?submap=15781"); + + var project = helper.createProject(); + project.getModel().setId(15781); + + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createCustomMapOptions(project); + + return minerva.create(options); + }).then(function (result) { + return result.destroy(); + }); + }); + + it("constructor with touch enabled", function () { + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createCustomMapOptions(project); + options.setCustomTouchInterface(true); + return minerva.create(options).then(function(result) { + assert.ok(result); + return result.destroy(); + }); + }); + }); + + + it('create Export', function () { + var options = null; + return ServerConnectorMock.getProject().then(function (project) { + options = helper.createCustomMapOptions(project); + + return minerva.createExport(options); + }).then(function (result) { + assert.ok(result); + assert.equal(logger.getWarnings().length, 0); + }); + }); + + it('create Admin', function () { + var options = null; + return ServerConnectorMock.getProject().then(function (project) { + options = helper.createCustomMapOptions(project); + + return minerva.createAdmin(options); + }).then(function (result) { + assert.ok(result); + assert.equal(logger.getWarnings().length, 0); + result.destroy(); + }); + }); + it('getProject', function () { + return ServerConnectorMock.getProject().then(function (project) { + var options = helper.createCustomMapOptions(project); + return minerva.create(options); + }).then(function (result) { + assert.equal(result.getProject().getProjectId(), "sample"); + return result.destroy(); + }); + }); + +}); diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/Layout.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/Layout.java index 672b1feca43b0fdcc3d2ceae6e0fd1cf974e6614..acb3b4612a6dce1f24b2671530cd8ec2e95ea777 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/layout/Layout.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/Layout.java @@ -34,7 +34,7 @@ import lcsb.mapviewer.model.user.User; @Entity public class Layout implements Serializable { /** - * + * */ private static final long serialVersionUID = 1L; @@ -143,7 +143,7 @@ public class Layout implements Serializable { /** * Constructor that initializes object with basic parameters. - * + * * @param title * title of the layout * @param directory @@ -159,7 +159,7 @@ public class Layout implements Serializable { /** * Constructor that initializes object with the copy of the data from parameter. - * + * * @param layout * from this object the data will be initialized */ @@ -180,7 +180,7 @@ public class Layout implements Serializable { /** * Prepares a copy of layout. - * + * * @return copy of layout */ public Layout copy() { @@ -398,7 +398,7 @@ public class Layout implements Serializable { /** * When this layout is connected to the top model in complex models then this * method adds layout of a submodel. - * + * * @param layout * layout of a submodel */ @@ -409,7 +409,7 @@ public class Layout implements Serializable { /** * Sets {@link #model}. - * + * * @param model * new {@link #model} value */ diff --git a/persist/src/db/11.0.7/fix_db_20180118.sql b/persist/src/db/11.0.7/fix_db_20180118.sql new file mode 100644 index 0000000000000000000000000000000000000000..a33b6ad89d4881c84fb355b8c56d309760e66b70 --- /dev/null +++ b/persist/src/db/11.0.7/fix_db_20180118.sql @@ -0,0 +1 @@ +-- empty file to force directory to be commited to git repo diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java index 02afc0199a9e39022bc90935372407560d5c4b3b..c6b2da557941c4337a9178d4a4da31b5c2177218 100644 --- a/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java +++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/BaseDao.java @@ -3,11 +3,13 @@ package lcsb.mapviewer.persist.dao; import java.util.List; import org.apache.log4j.Logger; +import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.springframework.beans.factory.annotation.Autowired; +import lcsb.mapviewer.common.Pair; import lcsb.mapviewer.persist.DbUtils; /** @@ -21,273 +23,302 @@ import lcsb.mapviewer.persist.DbUtils; */ public abstract class BaseDao<T> { - /** - * Default class logger. - */ - private static Logger logger = Logger.getLogger(BaseDao.class); + /** + * Default class logger. + */ + private static Logger logger = Logger.getLogger(BaseDao.class); - /** - * Sometimes objects have a flag that indicate that the object was removed - * from the system (but is still there because of foreign keys etc). This - * column determines the name of the column. If its set to null then such - * column doesn't exist. - */ - private String removableColumn = null; + /** + * Sometimes objects have a flag that indicate that the object was removed from + * the system (but is still there because of foreign keys etc). This column + * determines the name of the column. If its set to null then such column + * doesn't exist. + */ + private String removableColumn = null; - /** - * Class of the object that DAO works on. - */ - private Class<? extends T> clazz; + /** + * Class of the object that DAO works on. + */ + private Class<? extends T> clazz; - /** - * Default constructor. - * - * @param theClass - * class of the object that DAO will work on - */ - public BaseDao(Class<? extends T> theClass) { - this.clazz = theClass; - } + /** + * Default constructor. + * + * @param theClass + * class of the object that DAO will work on + */ + public BaseDao(Class<? extends T> theClass) { + this.clazz = theClass; + } - /** - * Default constructor. - * - * @param theClass - * class of the object that DAO will work on - * @param removableColumn - * determines the column in the object table that indicates if object - * should be considered as removed or not (see also: - * {@link #removableColumn}. - * - */ - public BaseDao(Class<? extends T> theClass, String removableColumn) { - this(theClass); - this.removableColumn = removableColumn; - } + /** + * Default constructor. + * + * @param theClass + * class of the object that DAO will work on + * @param removableColumn + * determines the column in the object table that indicates if object + * should be considered as removed or not (see also: + * {@link #removableColumn}. + * + */ + public BaseDao(Class<? extends T> theClass, String removableColumn) { + this(theClass); + this.removableColumn = removableColumn; + } - /** - * Utils that help to manage the sessions in custom multithreaded - * implementation. - */ - @Autowired - private DbUtils dbUtils; + /** + * Utils that help to manage the sessions in custom multithreaded + * implementation. + */ + @Autowired + private DbUtils dbUtils; - /** - * Adds object to the database. - * - * @param object - * object to add to database - */ - public void add(T object) { - getSession().save(object); - if (dbUtils.isAutoFlush()) { - getSession().flush(); - } - } + /** + * Adds object to the database. + * + * @param object + * object to add to database + */ + public void add(T object) { + getSession().save(object); + if (dbUtils.isAutoFlush()) { + getSession().flush(); + } + } - /** - * Flush connection with database. - */ - public void flush() { - getSession().flush(); - } + /** + * Flush connection with database. + */ + public void flush() { + getSession().flush(); + } - /** - * Commit current transaction. - */ - public void commit() { - if (!dbUtils.isCustomSessionForCurrentThread()) { - logger.warn("Manual commit with spring managed session!", new Exception()); - } + /** + * Commit current transaction. + */ + public void commit() { + if (!dbUtils.isCustomSessionForCurrentThread()) { + logger.warn("Manual commit with spring managed session!", new Exception()); + } - getSession().getTransaction().commit(); - getSession().beginTransaction(); - } + getSession().getTransaction().commit(); + getSession().beginTransaction(); + } - /** - * Returns current session. - * - * @return session for current thread - */ - protected Session getSession() { - return dbUtils.getSessionForCurrentThread(); - } + /** + * Returns current session. + * + * @return session for current thread + */ + protected Session getSession() { + return dbUtils.getSessionForCurrentThread(); + } - /** - * Update object in the database. - * - * @param object - * object to be updated - */ - public void update(T object) { - getSession().update(object); - if (dbUtils.isAutoFlush()) { - getSession().flush(); - } - } + /** + * Update object in the database. + * + * @param object + * object to be updated + */ + public void update(T object) { + getSession().update(object); + if (dbUtils.isAutoFlush()) { + getSession().flush(); + } + } - /** - * Removes object from the database. - * - * @param object - * object to be removed from database - */ - public void delete(T object) { - getSession().delete(object); - if (dbUtils.isAutoFlush()) { - getSession().flush(); - } - } + /** + * Removes object from the database. + * + * @param object + * object to be removed from database + */ + public void delete(T object) { + getSession().delete(object); + if (dbUtils.isAutoFlush()) { + getSession().flush(); + } + } - /** - * "Disconnects" object with the element in database. From this point on we - * cannot update/delete it in the database. - * - * @param object - * object that should be evicted - */ - public void evict(T object) { - getSession().evict(object); - if (dbUtils.isAutoFlush()) { - getSession().flush(); - } - } + /** + * "Disconnects" object with the element in database. From this point on we + * cannot update/delete it in the database. + * + * @param object + * object that should be evicted + */ + public void evict(T object) { + getSession().evict(object); + if (dbUtils.isAutoFlush()) { + getSession().flush(); + } + } - /** - * Returns number of elements in the table for this object. - * - * @return number of all elements in database - */ - public long getCount() { - if (removableColumn == null) { - return (Long) getSession().createCriteria(this.clazz).setProjection(Projections.rowCount()).uniqueResult(); - } else { - return (Long) getSession().createCriteria(this.clazz).add(Restrictions.eq(removableColumn, false)).setProjection(Projections.rowCount()).uniqueResult(); - } - } + /** + * Returns number of elements in the table for this object. + * + * @return number of all elements in database + */ + public long getCount() { + if (removableColumn == null) { + return (Long) getSession().createCriteria(this.clazz).setProjection(Projections.rowCount()).uniqueResult(); + } else { + return (Long) getSession().createCriteria(this.clazz).add(Restrictions.eq(removableColumn, false)) + .setProjection(Projections.rowCount()).uniqueResult(); + } + } - /** - * Returns an element that has a key parameter equal to value. If there is - * more than one element than one of them will be returned. If there is no - * such element then <code>null</code> is returned. - * - * @param key - * which parameter will filter the data - * @param value - * what must be the value of parameter key - * @return element that fulfill T.key=value criteria - */ - @SuppressWarnings("unchecked") - protected T getByParameter(String key, Object value) { - List<?> list = getSession() - .createQuery(" from " + this.clazz.getSimpleName() + " where " + key + " = :param_val " + removableAndStatemant()).setParameter("param_val", value) - .list(); - if (list.size() == 0) { - return null; - } else { - return (T) list.get(0); - } - } + /** + * Returns an element that has a key parameter equal to value. If there is more + * than one element than one of them will be returned. If there is no such + * element then <code>null</code> is returned. + * + * @param key + * which parameter will filter the data + * @param value + * what must be the value of parameter key + * @return element that fulfill T.key=value criteria + */ + @SuppressWarnings("unchecked") + protected T getByParameter(String key, Object value) { + List<?> list = getSession() + .createQuery( + " from " + this.clazz.getSimpleName() + " where " + key + " = :param_val " + removableAndStatemant()) + .setParameter("param_val", value).list(); + if (list.size() == 0) { + return null; + } else { + return (T) list.get(0); + } + } - /** - * Returns the list of elements that havae a key parameter equal to value. - * - * @param key - * which parameter will filter the data - * @param value - * what must be the value of parameter key - * @return list of elements that fulfill T.key=value criteria - */ - @SuppressWarnings("unchecked") - protected List<T> getElementsByParameter(String key, Object value) { - List<?> list = getSession() - .createQuery(" from " + this.clazz.getSimpleName() + " where " + key + " = :param_val " + removableAndStatemant()).setParameter("param_val", value) - .list(); - return (List<T>) list; - } + /** + * Returns the list of elements that have a key parameter equal to value. + * + * @param key + * which parameter will filter the data + * @param value + * what must be the value of parameter key + * @return list of elements that fulfill T.key=value criteria + */ + @SuppressWarnings("unchecked") + protected List<T> getElementsByParameter(String key, Object value) { + List<?> list = getSession() + .createQuery( + " from " + this.clazz.getSimpleName() + " where " + key + " = :param_val " + removableAndStatemant()) + .setParameter("param_val", value).list(); + return (List<T>) list; + } - /** - * Returns element with the id given as parameter. - * - * @param id - * database identifier - * @return object width identifier given as parameter - */ - @SuppressWarnings("unchecked") - public T getById(int id) { - List<?> list = getSession().createQuery(" from " + this.clazz.getSimpleName() + " where id=? " + removableAndStatemant()).setParameter(0, id).list(); - if (list.size() == 0) { - return null; - } else { - return (T) list.get(0); - } - } + @SuppressWarnings("unchecked") + protected List<T> getElementsByParameters(List<Pair<String, Object>> params) { + String queryString = " from " + this.clazz.getSimpleName() + " where "; + boolean firstParam = true; + for (Pair<String, Object> param : params) { + String key = param.getLeft(); + if (!firstParam) { + queryString += " AND "; + } + queryString += key + " = :param_val_" + key + " "; - /** - * Returns list of all object in db. - * - * @return list of all object in db - */ - @SuppressWarnings("unchecked") - public List<T> getAll() { - List<?> list = getSession().createQuery(" from " + this.clazz.getSimpleName() + " " + removableStatemant()).list(); - return (List<T>) list; - } + firstParam = false; + } + queryString += removableAndStatemant(); + Query query = getSession().createQuery(queryString); + for (Pair<String, Object> param : params) { + String key = param.getLeft(); + Object value = param.getRight(); + query = query.setParameter("param_val_" + key, value); + } + List<?> list = query.list(); + return (List<T>) list; + } - /** - * Removes all elements from the database. - */ - public void clearTable() { - String stringQuery = "DELETE FROM " + this.clazz.getSimpleName(); - getSession().createQuery(stringQuery).executeUpdate(); - if (dbUtils.isAutoFlush()) { - getSession().flush(); - } - } + /** + * Returns element with the id given as parameter. + * + * @param id + * database identifier + * @return object width identifier given as parameter + */ + @SuppressWarnings("unchecked") + public T getById(int id) { + List<?> list = getSession() + .createQuery(" from " + this.clazz.getSimpleName() + " where id=? " + removableAndStatemant()) + .setParameter(0, id).list(); + if (list.size() == 0) { + return null; + } else { + return (T) list.get(0); + } + } - /** - * Refresh object with the new data taken from database. - * - * @param object - * object to be refreshed - */ - public void refresh(Object object) { - getSession().refresh(object); - } + /** + * Returns list of all object in db. + * + * @return list of all object in db + */ + @SuppressWarnings("unchecked") + public List<T> getAll() { + List<?> list = getSession().createQuery(" from " + this.clazz.getSimpleName() + " " + removableStatemant()).list(); + return (List<T>) list; + } - /** - * @return the clazz - */ - protected Class<? extends T> getClazz() { - return clazz; - } + /** + * Removes all elements from the database. + */ + public void clearTable() { + String stringQuery = "DELETE FROM " + this.clazz.getSimpleName(); + getSession().createQuery(stringQuery).executeUpdate(); + if (dbUtils.isAutoFlush()) { + getSession().flush(); + } + } - /** - * Returns part of HQL statement responsible for {@link #removableColumn}. - * - * @return part of HQL statement responsible for {@link #removableColumn}. - */ - protected String removableAndStatemant() { - if (removableColumn == null) { - return ""; - } else { - return " AND " + removableColumn + " = false "; - } - } + /** + * Refresh object with the new data taken from database. + * + * @param object + * object to be refreshed + */ + public void refresh(Object object) { + getSession().refresh(object); + } - /** - * Returns part of HQL statement responsible for {@link #removableColumn} - * (without sql AND). - * - * @return part of HQL statement responsible for {@link #removableColumn} - * (without sql AND). - */ - protected String removableStatemant() { - if (removableColumn == null) { - return ""; - } else { - return " WHERE " + removableColumn + " = false "; - } - } + /** + * @return the clazz + */ + protected Class<? extends T> getClazz() { + return clazz; + } + + /** + * Returns part of HQL statement responsible for {@link #removableColumn}. + * + * @return part of HQL statement responsible for {@link #removableColumn}. + */ + protected String removableAndStatemant() { + if (removableColumn == null) { + return ""; + } else { + return " AND " + removableColumn + " = false "; + } + } + + /** + * Returns part of HQL statement responsible for {@link #removableColumn} + * (without sql AND). + * + * @return part of HQL statement responsible for {@link #removableColumn} + * (without sql AND). + */ + protected String removableStatemant() { + if (removableColumn == null) { + return ""; + } else { + return " WHERE " + removableColumn + " = false "; + } + } } diff --git a/persist/src/main/java/lcsb/mapviewer/persist/dao/map/LayoutDao.java b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/LayoutDao.java index 11fb912fdff420b04c871a2f3979c9c9a3742a6a..e464248cdda8d07df887438b05d64d76336474f2 100644 --- a/persist/src/main/java/lcsb/mapviewer/persist/dao/map/LayoutDao.java +++ b/persist/src/main/java/lcsb/mapviewer/persist/dao/map/LayoutDao.java @@ -1,86 +1,101 @@ -package lcsb.mapviewer.persist.dao.map; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.hibernate.Criteria; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; - -import lcsb.mapviewer.model.map.layout.Layout; -import lcsb.mapviewer.model.map.model.Model; -import lcsb.mapviewer.model.user.User; -import lcsb.mapviewer.persist.dao.BaseDao; - -/** - * Data access object for {@link Layout} class. - * - * @author Piotr Gawron - * - */ -public class LayoutDao extends BaseDao<Layout> { - - /** - * Default class logger. - */ - @SuppressWarnings("unused") - private static Logger logger = Logger.getLogger(LayoutDao.class); - - /** - * Default constructor. - */ - public LayoutDao() { - super(Layout.class); - } - - /** - * Lists layouts for the model. - * - * @param model - * for this model layouts will be listed - * @return list of layouts for the model - */ - public List<Layout> getLayoutsByModel(Model model) { - List<Layout> layouts = getElementsByParameter("model_iddb", model.getId()); - for (Layout layout : layouts) { - refresh(layout); - } - return layouts; - } - - /** - * Return number of layouts created by the user. - * - * @param user - * the user - * @return number of layouts created by the user - */ - public long getCountByUser(User user) { - Criteria crit = getSession().createCriteria(this.getClazz()); - crit.setProjection(Projections.rowCount()); - crit.add(Restrictions.eq("creator", user)); - crit.createAlias("model", "m"); - crit.add(Restrictions.sizeLe("m.parentModels", 0)); - return (Long) crit.uniqueResult(); - } - - /** - * Returns layout identified by name and model. - * - * @param model - * model where the layouts lay on - * @param name - * name of the layout - * @return layout - */ - public Layout getLayoutByName(Model model, String name) { - List<Layout> layouts = getElementsByParameter("model_iddb", model.getId()); - for (Layout layout : layouts) { - refresh(layout); - if (layout.getTitle().equals(name)) { - return layout; - } - } - return null; - } -} +package lcsb.mapviewer.persist.dao.map; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.Criteria; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Restrictions; + +import lcsb.mapviewer.common.Pair; +import lcsb.mapviewer.model.map.layout.Layout; +import lcsb.mapviewer.model.map.model.Model; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.persist.dao.BaseDao; + +/** + * Data access object for {@link Layout} class. + * + * @author Piotr Gawron + * + */ +public class LayoutDao extends BaseDao<Layout> { + + /** + * Default class logger. + */ + @SuppressWarnings("unused") + private static Logger logger = Logger.getLogger(LayoutDao.class); + + /** + * Default constructor. + */ + public LayoutDao() { + super(Layout.class); + } + + /** + * Lists layouts for the model. + * + * @param model + * for this model layouts will be listed + * @return list of layouts for the model + */ + public List<Layout> getLayoutsByModel(Model model) { + List<Layout> layouts = getElementsByParameter("model_iddb", model.getId()); + for (Layout layout : layouts) { + refresh(layout); + } + return layouts; + } + + public List<Layout> getLayoutsByModel(Model model, User creator, Boolean isPublic) { + List<Pair<String, Object>> params = new ArrayList<>(); + params.add(new Pair<String, Object>("model_iddb", model.getId())); + if (isPublic != null) { + params.add(new Pair<String, Object>("publicLayout", isPublic)); + } + if (creator != null) { + params.add(new Pair<String, Object>("creator_iddb", creator.getId())); + } + List<Layout> layouts = getElementsByParameters(params); + return layouts; + } + + /** + * Return number of layouts created by the user. + * + * @param user + * the user + * @return number of layouts created by the user + */ + public long getCountByUser(User user) { + Criteria crit = getSession().createCriteria(this.getClazz()); + crit.setProjection(Projections.rowCount()); + crit.add(Restrictions.eq("creator", user)); + crit.createAlias("model", "m"); + crit.add(Restrictions.sizeLe("m.parentModels", 0)); + return (Long) crit.uniqueResult(); + } + + /** + * Returns layout identified by name and model. + * + * @param model + * model where the layouts lay on + * @param name + * name of the layout + * @return layout + */ + public Layout getLayoutByName(Model model, String name) { + List<Layout> layouts = getElementsByParameter("model_iddb", model.getId()); + for (Layout layout : layouts) { + refresh(layout); + if (layout.getTitle().equals(name)) { + return layout; + } + } + return null; + } +} diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java index ddc1e5f3bcd551a012a6e360d367029ab974f488..53762ae79f0123483f6d6c1eaa8ba46052fb9de8 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/LayoutService.java @@ -107,7 +107,7 @@ public class LayoutService implements ILayoutService { /** * Service used to access logs. - * + * * @see ILogService */ @Autowired @@ -171,31 +171,14 @@ public class LayoutService implements ILayoutService { } @Override - public List<LayoutView> getCustomLayouts(Model model, User user, Boolean publicOverlay, User creator) { + public List<LayoutView> getCustomLayouts(Model model, User user) { List<LayoutView> result = new ArrayList<>(); if (model == null || user == null) { return result; } - List<Layout> layouts = layoutDao.getLayoutsByModel(model); + List<Layout> layouts = layoutDao.getLayoutsByModel(model, user, false); for (Layout layout : layouts) { - boolean toAdd = true; - if (creator != null) { - if (layout.getCreator() == null) { - toAdd = false; - } else if (!layout.getCreator().getId().equals(creator.getId())) { - toAdd = false; - } - } - if (publicOverlay != null) { - if (!publicOverlay.equals(layout.isPublicLayout())) { - toAdd = false; - } - } - if (toAdd) { - if (userCanViewOverlay(layout, user)) { - result.add(layoutViewFactory.create(layout)); - } - } + result.add(layoutViewFactory.create(layout)); } Collections.sort(result, LayoutView.ID_COMPARATOR); return result; @@ -648,7 +631,7 @@ public class LayoutService implements ILayoutService { /** * Sends notification email that layout was removed. - * + * * @param projectId * identifier of the project * @param layoutName @@ -667,7 +650,7 @@ public class LayoutService implements ILayoutService { /** * Sends notification email that layout was generated. - * + * * @param params * list of {@link CreateLayoutParams params} used for layout creation * @param schemas @@ -706,7 +689,7 @@ public class LayoutService implements ILayoutService { /** * Prepares table with statistics about coloring. - * + * * @param schemas * schemas that were used for coloring * @param scr @@ -738,7 +721,7 @@ public class LayoutService implements ILayoutService { * {@link ColorSchema} sometimes contains merged value from few rows. This * method split single {@link ColorSchema} object to simple flat objects that * can be serialiazed in a simple tab separated file. - * + * * @param originalSchema * original {@link ColorSchema} objcet that we want to spli into flat * objects @@ -763,7 +746,7 @@ public class LayoutService implements ILayoutService { /** * Prepares tab separated {@link String} represenation of {@link ColorSchema}. - * + * * @param columns * columns that should be outputed in the result String * @param schema @@ -791,7 +774,7 @@ public class LayoutService implements ILayoutService { /** * Returns String representing data of {@link GenericColorSchema} that should * appear in a given {@link ColorSchemaColumn}. - * + * * @param schema * object for which data will be returned * @param column @@ -846,7 +829,7 @@ public class LayoutService implements ILayoutService { /** * Returns String representing data of {@link GeneVariationColorSchema} that * should appear in a given {@link ColorSchemaColumn}. - * + * * @param schema * object for which data will be returned * @param column @@ -921,7 +904,7 @@ public class LayoutService implements ILayoutService { /** * Returns byte array containing data from original input file that was used to * generate the layout. - * + * * @param layoutId * identifier of layout for which we want to retrieve original file * data diff --git a/web/src/main/webapp/index.xhtml b/web/src/main/webapp/index.xhtml index 7dd60ad0c641af31c616d06de5529e70948704bd..4173a0d9b725208930f7bba7f48de251ed0d5583 100644 --- a/web/src/main/webapp/index.xhtml +++ b/web/src/main/webapp/index.xhtml @@ -38,7 +38,7 @@ function initMap(){ customMap = result; document.title = result.getProject().getName(); }).catch(function(rejectReason){ - minerva.GuiConnector.alert(rejectReason); + minerva.GuiConnector.alert(rejectReason, true); }); }