diff --git a/.aspell-api-exceptions.pws b/.aspell-api-exceptions.pws new file mode 100644 index 0000000000000000000000000000000000000000..2f5c04dda5012ffb8eea710c86fc5a2bf661a38e --- /dev/null +++ b/.aspell-api-exceptions.pws @@ -0,0 +1,703 @@ +personal_ws-1.1 en 0 utf-8 +acetylated +aceview +adw +affy +aftol +Agitans +al +aliasId +allergome +amoebadb +analyte +Analytics +annotatorClass +annotatorClassName +antibodyregistry +antweb +apd +aphidbase +april +arachnoserver +ardb +arrayexpress +arxiv +aspgd +assoiated +atc +atcc +atcvet +atfdb +autdb +avogadro +backgroundId +backgroundOverlayId +bacmap +bdgp +beetlebase +bgee +bieEntity +bigg +bindingDB +biocarta +biocatalogue +biocyc +bioEntites +bioEntity +Bioentity +bioEntityFields +biogrid +Biomedicine +biomodels +BioModels +BIOMODELS +bionumbers +bioportal +bioproject +biosample +biosystems +bitterdb +bloodBrainBarrier +Bname +boundaryCondition +boxSize +brainstem +brandNames +brenda +briefView +Broot +bto +Btype +bugbase +buildDate +bvar +bykdb +candela +cas +CAS +cath +cattleqtldb +cazy +ccd +CCD +ccds +CCDS +cco +cdd +CDMT +cdpd +cef +cellimage +CENRAL +centerPoint +cgd +cgsc +charprot +chebi +Chebi +ChEMBL +chemdb +chemidplus +chemspider +ChemSpider +CHEMSPIDER +chickenqtldb +ci +citationCount +className +cldb +clinicaltrials +clinvar +clo +coeruleus +commentId +commonName +compartmentId +complexId +compulyeast +connectedToLdap +conoserver +coord +coriell +corum +coulumb +cpc +CPC +creationDate +cryptodb +csa +cst +ctd +cubedb +cutdb +dailymed +darc +datatable +datetime +datf +dbd +dbest +dbg +dbprobe +dbsnp +defaultOverlay +defaultPrivileges +degradome +depod +desc +dictybase +disprot +dmet +DN +dna +doi +doid +dommino +DONT +doqcs +downloadImage +downloadModel +downloadProgress +downloadSource +dpv +dragondb +drsc +drugbank +drugbankv +ebimetagenomics +ec +echobase +eco +ecogene +ecoliwiki +edam +efo +ega +elementAnnotations +elementClassNames +elementId +elementIds +elementTypes +embl +ena +ensembl +entrez +environ +epd +et +euclinicaltrials +exac +excludedCompartmentIds +expt +fb +ffccffcc +fff +FFFFFF +fileId +filteredSize +flybase +fma +Fmapping +foodb +formerSymbols +Fs +fsnp +fullName +funcbase +functionId +functionIds +fungidb +gabi +gcms +genatlas +genecards +genedb +genefarm +geneMapping +genetree +geneVariations +genewiki +genomeId +genomeType +genomeTypes +genomeVersion +genpept +genprop +geo +getAvailableRemoteUrls +giardiadb +gitHash +glida +glycan +glycoepitope +glycomedb +glycosylated +gmd +goa +googleLicenseConsent +gpcr +gpcrdb +gpml +gramene +grantPrivileges +greengenes +grp +grsdb +gsta +gui +gwascentral +gxa +hamap +handlerClass +hcvdb +hdr +henry +hg +hgmd +hgnc +hierarchyVisibilityLevel +hinv +HIPAA +hla +hmdb +HMDB +hogenom +homd +homologene +hovergen +hpa +hpm +hprd +href +hs +hssp +hydroxylated +icd +idObject +idot +ie +imageFormats +imageLinkId +IMAP +imex +img +IMG +imgt +inchi +InChi +inchikey +initialAmount +initialConcentration +innerPosition +inputFormat +inputType +insdc +interpro +InterPro +INTERPRO +introns +ird +irefweb +isbn +isDefault +isfinder +isoform +Isoform +ISOFORM +isPublic +isServerSide +issn +iuphar +jaxmice +jcggdb +jcm +jcsd +jstor +june +jws +katal +kegg +kineticLaw +kineticrecord +kisao +KnapSack +lastActive +lcsb +ldapAccountAvailable +lepra +Lewy +LEWY +lgic +ligandbox +ligandexpo +ligm +lincs +linkedSubmodel +lipidbank +lipidmaps +listOfAntisenseRNAs +listOfBlockDiagrams +listOfCompartmentAliases +listOfCompartments +listOfComplexSpeciesAliases +listOfGenes +listOfGroups +listOfLayers +listOfProteins +listOfRNAs +listOfSpecies +listOfSpeciesAliases +listOfUnitDefinitions +listOfUnits +localUrl +logEntries +lrg +lsid +macie +maizegdb +mamo +mapCanvasType +mapCanvasTypes +mapName +mappingName +mapTypes +masklike +massbank +mathMl +mathMlPresentation +matrixdb +maxColor +maxZoom +MCS +medlineplus +merops +MeSH +meshId +metabolights +metagenome +metaid +metazoa +methylated +metlin +mgd +MGD +MGnify +MGNIFY +microsporidia +mimodb +minColor +MINERVANET +minZoom +mipmod +mirbase +miRBase +mirex +MiriamType +miriamTypes +miRnas +mirnest +miRTarBase +mmdb +mmrrc +modeldb +modelDisplay +modelFormats +modelId +modelLinkId +modelPoint +modelVersion +modificationDates +modificationStateTypes +molbase +mpid +mrow +myco +mycobank +myristoylated +namebank +napp +narcis +nasc +nbn +nbrc +ncbi +ncbigene +ncbiprotein +ncim +ncit +ndc +neurolex +neurologic +neuromorpho +neurondb +neutralColor +nextdb +nextprot +nI +niaest +nigra +nKind +noncode +noncodev +norine +notifyEmail +NPJ +nuclearbd +oai +objectClass +objectId +objectIdentifier +objectType +obo +Ok +oma +omia +omim +OMIM +opb +opm +orcid +ordb +ordo +organismId +oridb +orphanet +orthodb +Orthologous +orthology +Orthology +ORTHOLOGY +oryzabase +otl +outputFormat +overlayContent +overlayId +overlayIds +overlayTypes +OverviewImage +OverviewImageLink +overviewImageViews +OverviewModelLink +OverviewSearchLink +paleodb +palmytoylated +parameterId +parameterIds +parentClass +parkinsonism +participantId +Pathologic +pathwaycommons +pato +paxdb +pazar +pdb +PDB +peptideatlas +perfectMatch +peroxibase +pfam +PFAM +PHARM +pharmgkb +phenolexplorer +phosphopoint +phosphorylated +PHOSPHORYLATED +phosphosite +phylomedb +phytozome +pid +pigqtldb +pina +piroplasma +pirsf +plasmodb +pmap +pmc +pmdb +po +pocketome +polbase +polygonString +pombase +positionToCompartment +postive +prenylated +privilegeType +privilegeTypes +probeset +prodom +proglyc +proj +projectBackground +prosite +protclustdb +proteincard +proteinReference +proteomicsdb +protist +protonated +protonet +pscdb +pseudomonas +psimi +psimod +psipar +pthcmp +pubchem +publicOverlay +PubMed +pubmedId +pw +qtl +reactionAnnotations +reactionIds +reactionTypes +rebase +refseq +RefSeq +REFSEQ +registryIdentifier +removeReason +requestResetPassword +resid +retropulsion +revokePrivileges +rfam +rgd +ricegap +rna +rnai +rnamods +ro +sa +sabiork +sacch +samp +sbgn +sbo +scop +scretf +sdbs +sgd +SGD +sgn +sharedInMinervaNet +sheepqtldb +sider +siemens +sievert +simpleColor +singleLine +sitex +sizeX +sizeY +smeg +smpdb +snomedct +sortColumn +sortOrder +sourceUrl +soybase +speciesAlias +speciesIdentity +sra +stap +steradian +structuralState +submapConnections +substantia +substratedb +subtilist +subtiwiki +suggestedQueryList +sulfated +supfam +swiss +tair +tarbase +targetElements +targetParticipants +taxonomyId +tcdb +termsOfUseConsent +tesla +tgd +th +tigrfam +tileSize +tissuelist +tol +topdb +topfind +topOverviewImage +totalSize +Toxicogenomic +TOXICOGENOMIC +toxoplasma +transparencyLevel +treebase +treefam +trichdb +tritrypdb +ttd +Ub +uberon +ubio +ubiquitinated +udl +umbbd +unigene +UniGene +UNIGENE +unii +unimod +uniparc +uniprot +Uniprot +uniqueId +unists +unitDefinition +unitId +unitsId +unitTypeFactors +unitTypes +updatePreferences +updatePrivileges +uploadedDataLength +uris +uspto +usualView +validConnection +valueType +vario +vbase +vbrc +vfdb +viralzone +virsirna +vmhmetabolite +vmhreaction +weber +wikidata +Wikidata +WIKIDATA +wikigenes +wikipathways +WikiPathways +WIKIPATHWAYS +wikipedia +worfdb +wormbase +wormpep +xenbase +xhtml +xmlns +xxxxxxxx +ydpm +yeastintron +yetfasco +yrcpdr +zfin +zoomLevel diff --git a/.aspell.en.pws b/.aspell.en.pws new file mode 100644 index 0000000000000000000000000000000000000000..d55156159364099eba8cb9d180d7bd8b5a01dd1c --- /dev/null +++ b/.aspell.en.pws @@ -0,0 +1,568 @@ +personal_ws-1.1 en 0 utf-8 +Acetosalic +ACETYLOXY +ACETYLSALIC +Acetylsalicylic +ACETYLSALICYLIC +ACETYLSALICYLICUM +Aceview +ACIDUM +actomyosin +Affymetrix +AFTOL +ALKA +allel +Allergome +AmoebaDB +ANADIN +Analyte +ANGETTES +antisense +AntWeb +APD +AphidBase +api +Arabidopsis +ArachnoServer +ARITOX +ArrayExpress +arXiv +asc +AspGD +ASPRO +ATCC +ATH +AutDB +AUTH +autocomplete +autofill +BackgroundColor +BacMap +BBD +bcrypt +BDGP +BeetleBase +BENZOIC +BEVASIRANIB +Bgee +BiGG +BindingDB +bioassay +BioCarta +BioCatalogue +BioCompendium +BioCyc +bioEntities +BioEntity +BioGRID +BioNumbers +biopax +BioPortal +BioProject +BioSample +BioSystems +Biotransformation +BitterDB +BOM +boolean +BorderColor +bqbiol +bqmodel +BugBase +BYKdb +capslock +cardinality +CATH +CAZy +celldesigner +CellDesigner +CGSC +CharProt +charset +CHEBI +checkboxes +chembl +ChemDB +ChemIDplus +Chuderland +CLDB +ClinicalTrials +ClinVar +CLR +compartmentRef +Compulyeast +Concurent +config +Conoserver +contect +contentType +coords +COPASI +Coriell +CORS +CORUM +cron +CryptoDB +CSA +css +CTD +ctdbase +curation +CutDB +CVE +cyclooxygenase +DailyMed +DANAMEP +DAPI +DARC +DataBase +dataset +datasets +DATF +dbconfig +DBD +dbEST +DBG +dbProbe +dbSNP +debian +defaultCenterX +defaultCenterY +defaultZoomLevel +Degradome +Denda +DEPOD +dialogs +Dictybase +DISPRIN +DisProt +DMET +DOI +DOMMINO +DORLIMOMAB +DPV +DragonDB +DRSC +DrugBank +ds +DURLAZA +eboVir +EchoBASE +EcoGene +EcoliWiki +Ecotrin +eggNOG +elementIdentifier +ENA +ENPRIN +Ensembl +Entrez +enviPath +Environ +EPD +Equi +ExAC +Expt +Feng +FlyBase +FMA +FooDB +frontend +FuncBase +FungiDB +Fyn +GABI +Gawron +GC +Gebel +Genatlas +GENCARDIA +GeneCards +GeneDB +GeneFarm +geneMappingId +GeneTree +genomeId +genomic +GenPept +getWriter +GiardiaDB +GLIDA +Glycan +Glycoconjugate +GlycoEpitope +GlycomeDB +glyphs +glypican +Golm +GPC +GPCR +GPCRDB +GPML +Gramene +graphicalObject +GreenGenes +Grossman +GRSDB +GWAS +GXA +HAMAP +Harada +hasInstance +hasProperty +hasTaxon +Hatanaka +HCVDB +heterodimer +HGMD +HGNC +Hikari +Hiramoto +HLA +HOGENOM +HOMD +Homeodomain +HomoloGene +homomultimer +HOVERGEN +HPA +HPRD +hsa +HSSP +html +http +https +hungs +ICD +ICEberg +IMEx +IMGT +InChI +InChIKey +includedCompartmentIds +InfoWindow +IntAct +Intron +Introns +InvDb +IRD +iRefWeb +isDerivedFrom +ISFinder +isInstanceOf +isPropertyOf +ISSN +IUPHAR +javascript +JAX +JCGGDB +Jiang +jpg +JS +json +JSTOR +JWS +KA +Kawakubo +Kawamura +Kegg +KEGG +KiSAO +KNApSAcK +Kuzma +LayerText +layouted +LDAP +leprae +LEVIUS +ligand +LigandBox +LIGM +LINCS +lineWidth +LipidBank +logrotate +lu +Luo +MACiE +MaizeGDB +mapId +marinum +MassBank +MatrixDB +Matsumoto +Mazein +md +MEASURIN +MedlinePlus +MEROPS +MetaboLights +Metabolome +Metagenome +Metainformation +MetaNetX +Metazoa +METLIN +MGED +MICROPIRIN +microRNA +MicrosporidiaDB +MimoDB +minerva +MINERVA’s +MIPModDB +miR +mirEX +miriam +miRNA +miRNAs +miRNEST +mirtarbase +misalign +misaligning +MMRRC +ModelDB +MolArt +Molbase +multimer +multimers +MycoBank +MycoBrowser +NADH +Nakano +NameBank +namespace +NAPP +NARCIS +NASC +NCBI +NCI +NCIm +NCIt +NeuroLex +NeuroMorpho +NeuronDB +NEXTDB +nextProt +NIAEST +Ninio +NITE +NONCODE +NORINE +Noshiro +NucleaRDB +occursIn +OMA +OMIA +openjdk +OpenLayers +OPM +ORCID +OriDB +Orphanet +OrthoDB +Oryza +Oryzabase +Ostaszewski +Otjacques +overlayed +PaleoDB +parseable +PATO +PaxDb +PAYNOCIL +Pazar +pdf +pdmap +PDR +PeptideAtlas +Peroxibase +PharmGKB +phenome +phenotypes +phentoype +PhosphoPoint +Phosphoprotein +PhosphoSite +PhylomeDB +Phytozome +PINA +Piotr +PiroplasmaDB +PIRSF +PlasmoDB +PLATET +PMC +pmceurope +PMP +png +Pocketome +PolBase +PomBase +postgres +postgresql +POSTMI +posttranslational +PredictProtein +Prin +Probeset +ProDom +ProGlycProt +projectId +PROSITE +ProtClustDB +ProteinCard +Proteome +ProteomicsDB +Protists +ProtoNet +PSCDB +Pseudomonas +PTGS +PubChem +pubmed +px +Qiu +qTL +QTL +QuickStart +RDF +reactionId +reactionIdentifier +reactome +REBASE +removeAllListeners +reportable +repositioned +RESID +resizeable +reupload +revalidated +reverseReaction +RFAM +RGD +RhoA +RHOA +RK +RNAi +RNAs +RoundedRectangle +Ruan +SABIO +Saccharomyces +SALICYLATE +Salicylic +Satagopam +Sato +SBGN +SBGNML +sbml +SBML +SBO +ScerTF +Schizosaccharomyces +SCOP +scrollbar +scrollbars +SearchListener +selectable +SemanticZoomLevelTransparency +Shalgi +ShapeType +Shomron +SIDER +SitEx +smegmatis +SMTP +SNOMED +SNP +sortable +SoyBase +speciesReference +specific +SSL +STAP +stoichiometry +STRGH +subfolders +submap +submaps +submodel +submodels +substanceUnits +SubstrateDB +SubtiList +SubtiWiki +superfamily +SUPFAM +svg +SwissLipids +symlink +Tair +TAIR +TarBase +targetting +Taxnomy +Tetrahymena +TFDB +Thaliana +TIGRFAMS +timeouted +TOPDB +TopFind +ToS +ToxoDB +TransparencyZoomLevelVisibility +TreeBASE +TreeFam +TrichDB +TriTrypDB +TTD +txt +UBERON +uBio +ubuntu +UCSC +uid +un +unhandled +unicode +UNII +Unimod +UniParc +UniPathway +UniProt +UniSTS +uri +url +urlencoded +urls +USPTO +UTF +VariO +VAZALORE +Vbase +VBRC +Vetinary +VFDB +viewBox +ViralZone +VIRsiRNA +vmh +webpage +whitespace +WikiGenes +Worfdb +WormBase +Wormpep +www +Xenbase +xml +xsd +xss +YDPM +YeTFasCo +YRC +ZFIN +Zhang +Zorzan diff --git a/.gitignore b/.gitignore index 086453b02d6c62843ccb976bbeac9ebf476e8ff1..3193dd9a22fbecf20f4ef209c5a3739c68d03a2d 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ service/minerva-big/ #eclipse files .classpath .settings +.externalToolBuilders #maven build files target/ @@ -28,3 +29,6 @@ debian/src/*.sql #rpm build files rpm/rpmbuildtemp/ + +#local test +web/src/test/java/lcsb/mapviewer/web/TestXXX.java diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9cc9e8425e1690a6ca7b625230ebcc513ce1a7f6..2d6c98f81d2b348d7e8238bd651b45b144ab543f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -589,3 +589,11 @@ test_postgres_14_compatibility: <<: *test_database_definition services: - postgres:14 + +changelog_spelling: + image: debian + stage: test + script: + - apt-get update + - apt-get install -y aspell aspell-en + - ./test_spelling.sh diff --git a/CHANGELOG b/CHANGELOG index 2c038263d1ed5a2c3c77cc77a7a0bb1004847d3c..0bc4cdd6dc60aa246c827d3616879d2e1b259cd0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -13,9 +13,91 @@ minerva (16.3.0) unstable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 27 Jun 2022 15:00:00 +0200 +minerva (16.2.10) stable; urgency=medium + * Bug fix (API documentation): typos in API documentation corrected (#1806) + * Bug fix (API documentation): header in logout method change to keep + consistency with other methods (#1806) + * Bug fix (API documentation): missing information about genomeId added when + adding gene mapping (#1807) + * Bug fix: exporting map with data overlay coloring did not work (#1817) + * Bug fix: non-numeric character in pubmed id prevent publications from + being downloaded (#1802) + * Bug fix: line width was ignored when fetching information about advanced + data overlay (#1742) + * Bug fix: global xml namespace definition caused MINERVA to fail on + processing model notes (#1804) + * Bug fix: genetic data overlays from zip input did not contain proper info + about genome (#1815) + * Bug fix: overlay genetic data that contained multiple matches (for example + two different uniprot ID for the same gene) caused problem when visualizing + genome browser (#1815) + * Bug fix: when exporting elements the list of selected excluded/included + compartments was too long then the error was raised (#1798) + * Bug fix: when merged results in left panel contained different submap link + minerva crashed (#1764) + + -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 25 Jan 2023 12:00:00 +0200 + +minerva (16.2.9) stable; urgency=medium + * Bug fix (API documentation): authentication token is not needed (and + misleading) when accessing list of projects from guest account (#1775) + * Bug fix (API documentation): missing authentication token in logout + sample (#1775) + * Bug fix (API documentation): when starting downloading genome data the + response fields is empty and unnecessary (#1775) + * Bug fix (API documentation): information where genomeId can be found + added (#1775) + * Bug fix (API documentation): information where geneMappingId can be + found added (#1775) + * Bug fix (API documentation): when creating user use better user password + example (#1775) + * Bug fix (API documentation): when creating user list of parameters was + wrong (#1775) + * Bug fix (API documentation): remove unnecessary "-i" option in curl + examples (#1775) + * Bug fix: parsing GPML file with unknown ShapeType caused errors during + parsing (#1776) + * Bug fix: information about layers was not merged in merge API call (#1771) + * Bug fix: downloading model with limited list of reactions and elements + downloaded also text areas (#1770) + * Bug fix: when CellDesigner species contained notes in both Species and Gene + tags the notes were improperly parsed and could cause issues on export + (#1772, #1772) + * Bug fix: when the last cell in the last column of overlay data entered in + the upload dialog is empty there was an unexpected (#1743) + * Bug fix: disable delete plugin button when removing plugin (#1766) + * Bug fix: removing non existing overlay caused an error (#1791) + + -- Piotr Gawron <piotr.gawron@uni.lu> Sat, 22 Oct 2022 11:00:00 +0200 + +minerva (16.2.8) stable; urgency=medium + * Bug fix: missing content-type header in REST API documentation caused + issues with converter API (#1745, #1754, #1759, #1755) + * Bug fix: MINERVA_AUTH token in REST API documentation was sometimes + missing and sometimes it was unnecessary (#1744) + * Bug fix: deprecated "semantic-zoom" changed to + "semantic-zoom-contains-multiple-layouts" in REST API documentation for + project upload (#1754) + * Bug fix: export to SBML did not work with empty complexes containing the + same structural state (#1757, #1756) + * Bug fix: updating user plugin data did not work (#1739) + * Bug fix: legend was not visualized properly for mix of defined and + undefined colors in overlay (#1749) + * Bug fix: misleading "undefined maps" removed from submaps tab (#1703) + + -- Piotr Gawron <piotr.gawron@uni.lu> Fri, 09 Sep 2022 10:00:00 +0200 + +minerva (16.2.7) stable; urgency=medium + * Bug fix: when providing problematic input file in REST API converter the + status code should be 400 (BAD REQUEST) instead of 500 + * Bug fix: default curl content type (application/x-www-form-urlencoded) + caused issues when using converter API (#1734) + + -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 21 Jul 2022 11:00:00 +0200 + minerva (16.2.6) stable; urgency=medium - * Bug fix: partial update on defaultCenterX and defaultCenterY and defaultZoomLevel - did not work + * Bug fix: partial update on defaultCenterX and defaultCenterY and + defaultZoomLevel did not work -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 7 Jul 2022 11:00:00 +0200 @@ -26,7 +108,7 @@ minerva (16.2.5) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 6 Jul 2022 16:00:00 +0200 minerva (16.2.4) stable; urgency=medium - * Bug fix: rest api of uniprot.org changed + * Bug fix: rest API of UniProt changed -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 5 Jul 2022 14:00:00 +0200 @@ -35,7 +117,7 @@ minerva (16.2.3) stable; urgency=medium annotators (#1722) * Bug fix: modification residue id must start with a letter when exporting to CellDesigner - * Bug fix: expot to SBML did not work for cmaps that had two or more complexes + * Bug fix: export to SBML did not work for maps that had two or more complexes with the same children that had modification residues (#1720) * Bug fix: when providing invalid url in gene mapping proper error message is shown (#1723) @@ -54,7 +136,7 @@ minerva (16.2.2) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 20 Jun 2022 12:00:00 +0200 minerva (16.2.1) stable; urgency=medium - * Bug fix: Kegg annotator stopped working after kegg moved to https + * Bug fix: Kegg annotator stopped working after Kegg moved to https * Bug fix: General overlays were marked as editable even though they should not be (#1706, #1702) * Bug fix: searching for non existing chemical caused an error to be thrown @@ -240,7 +322,7 @@ minerva (16.1.0) stable; urgency=medium * Bug fix: help dialog is closed automatically after Add Project dialog is closed (#1099) * Bug fix: root url must be valid url pointing to minerva instance (#1689) - * Bug fix: there were missing lines when exporting truncation/dissotiation + * Bug fix: there were missing lines when exporting truncation/dissociation reaction to GPML (#1676) * Bug fix: some SBML files were recognized as CellDesigner files (#1677) * Bug fix: reaction middle was not highlighted (#1637) @@ -390,8 +472,8 @@ minerva (16.0.0) stable; urgency=medium * Small improvement: homomultimer information is provided in API (#1468) * Small improvement: missing info about species for SBML parsing warning (#1472) - * Small improvement: information about dimer in sbgn is provided only once - if the information is duplicated in sbgn data (#1358) + * Small improvement: information about dimer in SBGN is provided only once + if the information is duplicated in SBGN data (#1358) * Small improvement: glyph quality is improved (#1458) * Small improvement: search results are group by diagram (#1451) * Small improvement: "Failed to fetch" errors are reported in a way that @@ -421,7 +503,7 @@ minerva (16.0.0) stable; urgency=medium caused issue (#1546) * Bug fix: search results were limited to 10 elements * Bug fix: Chrome autofill is disabled for "Search: " in admin panel tables - * Bug fix: search tab becomes active when drug/chemical/mirna result are + * Bug fix: search tab becomes active when drug/chemical/MiRNA result are available (#1491) * Bug fix: arrows without a "process" box had an irregular empty space in their lines (#1471) @@ -434,7 +516,7 @@ minerva (16.0.0) stable; urgency=medium * Bug fix: removing plugin that does not exist anymore does not raise an error (#1289) * Bug fix: md5 hash function of plugin was not computed properly - * Bug fix: exported gpml for every compartment contained list of species name + * Bug fix: exported GPML for every compartment contained list of species name in the comment section -- Piotr Gawron <piotr.gawron@uni.lu> Fri, 29 Oct 2021 13:00:00 +0200 @@ -479,14 +561,14 @@ minerva (15.1.1) stable; urgency=medium * Bug fix: zoom level change was not reflected in the url when submap was opened (#1338) * Bug fix: API call returning list of overlays returned for non existing - project returned access denied status insted Not Found (#1370) - * Bug fix: results for chembl targetting uniprot without gene name (for + project returned access denied status instead Not Found (#1370) + * Bug fix: results for chembl targetting UniProt without gene name (for example P0C2L1) could crash caching (#1377) * Bug fix: removing non-existing project results in warning not an error message (#1367) * Bug fix: opening map in google maps without background resulted in unexpected error (#1416) - * Bug fix: normal user could not update tos information (#1419) + * Bug fix: normal user could not update ToS information (#1419) * Bug fix: and operator in SBGN-like view was not drawn (#1408) * Bug fix: export of overlayed map as an image did not respect overlay colors (#1417) @@ -558,15 +640,15 @@ minerva (15.0.3) stable; urgency=medium * Bug fix: when there is a problem with minerva deployment on tomcat proper warning message is presented in admin panel (#1332) * Bug fix: API call updating user preferences did not handle properly - conflicts on new gui properties (#1326) - * Bug fix: "bqbiol:hasTaxon" relation type is not supported by CellDedigner + conflicts on new GUI properties (#1326) + * Bug fix: "bqbiol:hasTaxon" relation type is not supported by CellDesigner and is now transformed during export into something readable by CellDesigner (#1281) * Bug fix: concurrency issue that could happen rarely on first search of the map and put the project into "unsearchable" state is fixed (#1333) - * Bug fix: when edit project buton was clicked on project that was removed in + * Bug fix: when edit project button was clicked on project that was removed in another tab there was an error thrown (#1343) - * Bug fix: chebi and entrez annotations were incorrectly exported to GPML + * Bug fix: CHEBI and Entrez annotations were incorrectly exported to GPML (#1349) * Bug fix: exporting to GPML sometimes resulted in invalid modification point end for catalysis (#1350) @@ -597,11 +679,11 @@ minerva (15.0.2) stable; urgency=medium not handled properly (#1281) * Bug fix: "bqmodel:isInstanceOf", "bqmodel:hasInstance", "bqbiol:hasProperty", "bqbiol:isPropertyOf" relation types are not - supported by CellDedigner and are now transformed during export into + supported by CellDesigner and are now transformed during export into something readable by CellDesigner (#1281) * Bug fix: at random time points there was an issue with cached data (#1323) * Bug fix: connection to DAPI timeouted sometimes which resulted in error - when checking for all chemicals for specfific protein (#1324) + when checking for all chemicals for specific protein (#1324) * Bug fix: complex/compartment with empty name was incorrectly exported to CellDesigner (#1310) @@ -680,7 +762,7 @@ minerva (15.0.0) stable; urgency=medium * Small improvement: simple molecules in SBGN compliant view are drawn as ellipses not circles (#796) * Small improvement: uploaded map is automatically cached (#983) - * Small improvement: molart updated to version 1.5.0: Ability to show + * Small improvement: MolArt updated to version 1.5.0: Ability to show unobserved structure regions in the sequence view. * Small improvement: list of genomes is automatically refreshed during genome upload (#820) @@ -717,7 +799,7 @@ minerva (15.0.0) stable; urgency=medium * Bug fix: newt use incorrect attributes when exporting render information that could not be parsed by minerva (#1127) * Bug fix: catalysis to protein was not parsed from SBGN file (#1116) - * Bug fix: antisenseRNA shape is inferred from SBGN when antisenseRNA text is + * Bug fix: antisense RNA shape is inferred from SBGN when antisense RNA text is present in glyph label (#1114) * Bug fix: export to SBGN sometimes crashed due to concurrency issues (#1126) * Bug fix: CellDesigner models where start and end point of reaction was the @@ -766,9 +848,9 @@ minerva (14.0.13) stable; urgency=medium minerva (14.0.12) stable; urgency=medium * Bug fix: comments on submaps were not visible (#1230) * Bug fix: removing comment from submap did not work - * Bug fix: reaction name containing "<" character was exported inproperly to + * Bug fix: reaction name containing "<" character was exported improperly to CellDesigner (#1227) - * Bug fix: doi annotation was inproperly parsed from CellDesigner file and + * Bug fix: DOI annotation was improperly parsed from CellDesigner file and resulted in not clickable link (#1231) * Bug fix: when plugin data was too big 500 error was returned (#1232) * Bug fix: removing plugin in admin panel removes it from server permanently @@ -777,7 +859,7 @@ minerva (14.0.12) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 11 May 2020 17:00:00 +0200 minerva (14.0.11) stable; urgency=medium - * Bug fix: complex with no border was inproperly imported from CellDesigner + * Bug fix: complex with no border was improperly imported from CellDesigner (#1198) * Bug fix: export to CellDesigner deal with CellDesigner issue that does not allow compartment species alias to be shorter than 2 characters (#1204) @@ -785,7 +867,7 @@ minerva (14.0.11) stable; urgency=medium minerva (#1202) * Bug fix: infinity value in kinetic parameter could not be parsed from CellDesigner file minerva (#1203) - * Bug fix: author list inproperly presented author data when some fields were + * Bug fix: author list improperly presented author data when some fields were missing (#1201) * Bug fix: refreshing minerva page with more than one plugin opened might led to an error due to race condition (#1197) @@ -801,7 +883,7 @@ minerva (14.0.10) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 16 Mar 2020 14:00:00 +0200 minerva (14.0.9) stable; urgency=medium - * Bug fix: simultanous export to SBML of more than one file could result in + * Bug fix: simultaneous export to SBML of more than one file could result in 500 Internal Server Error (#1110) * Bug fix: refresh data overlay did not hide data overlays that were removed and selected (#1097) @@ -832,7 +914,7 @@ minerva (14.0.9) stable; urgency=medium minerva (14.0.8) stable; urgency=medium * Bug fix: API didn't allow to upload plugins with local url (#1084, regression 14.0.7) - * Bug fix: upload of data overlay with two entries having different uniprot + * Bug fix: upload of data overlay with two entries having different UniProt identifier but pointing to the same gene crashed (#1083) * Bug fix: don't allow to remove plugin twice (#1081) * Bug fix: upload of SBML file with very short reaction length could produce @@ -866,13 +948,13 @@ minerva (14.0.6) stable; urgency=medium * Bug fix: search by identifier didn't consider identifiers added by annotators (#1047) * Bug fix: if map has SHOW OVERVIEW, the legend/comment/clear were not - displayed at all (regresion 14.0.5, #1045) + displayed at all (regression 14.0.5, #1045) * Bug fix: when there is a problem with database during removing project, project removal doesn't hang (#1058) * Bug fix: coloring of the reaction wasn't applied to center of reaction (regression 14.0.0, #1057) * Bug fix: genetic variant overlay improperly processed elements identified - by miriam identifiers, like uniprot (#1059) + by miriam identifiers, like UniProt (#1059) * Bug fix: invalid information was provided for genetic variants overlay when map organism was defined (#1060) @@ -881,7 +963,7 @@ minerva (14.0.6) stable; urgency=medium minerva (14.0.5) stable; urgency=medium * Bug fix: copy-paste of genetic-variant data overlay into Add overlay content dialog could crash upload (#1040) - * Bug fix: some annotators (like Cazy) were crashing on old installations + * Bug fix: some annotators (like CAZy) were crashing on old installations (#1029) * Bug fix: uploading a map that breaks postgres constraints hung upload of the project (#1028) @@ -891,7 +973,7 @@ minerva (14.0.5) stable; urgency=medium * Bug fix: search for NADH drug resulted in drug with empty name (#1018) * Bug fix: export to SBML didn't handle properly arrows (#1015) * Bug fix: Font colour of text area was preserved in Empty view (#1014) - * Bug fix: exported sbml file always contain model identifier (#1013) + * Bug fix: exported SBML file always contain model identifier (#1013) * Bug fix: typo allel reverted to allele in overlay data (regression 14.0.0, #1012) * Bug fix: after loading/removing too many plugins it was impossible to load @@ -906,7 +988,7 @@ minerva (14.0.4) stable; urgency=high due to problems with identifiers used by SBGN (#1006) * Bug fix: upload of data overlay with conflicting overlay types caused error (#998) - * Bug fix: upload of sbml file with protein modifications inside complex + * Bug fix: upload of SBML file with protein modifications inside complex crashed visualization (#966) * Bug fix: list of overlays for admin and curator included also other people overlays (regression 14.0.3, #1008) @@ -918,7 +1000,7 @@ minerva (14.0.4) stable; urgency=high minerva (14.0.3) stable; urgency=medium * Bug fix: default zoom level on main map works even when x or y are undefined (#993) - * Bug fix: sbml parser had sometimes problems with combining layout and multi + * Bug fix: SBML parser had sometimes problems with combining layout and multi packages (#966) * Bug fix: parsing of CellDesigner files that contained substanceUnits could crash the upload (#985) @@ -954,7 +1036,7 @@ minerva (14.0.2) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 15 Oct 2019 11:00:00 +0200 minerva (14.0.1) stable; urgency=medium - * Bug fix: maps that were annotated using old Biocompendium annotator could + * Bug fix: maps that were annotated using old BioCompendium annotator could not load properly (#986) -- Piotr Gawron <piotr.gawron@uni.lu> Wed, 15 Oct 2019 9:00:00 +0200 @@ -1018,7 +1100,7 @@ minerva (14.0.0) stable; urgency=medium (#936) * Bug fix: work on FF Private Window mode could cause logout or raise an error on when opening new tab with minerva (#892) - * Bug fix: fetching list of miRnas resulted sometimes in "Internal Server + * Bug fix: fetching list of MiRNAs resulted sometimes in "Internal Server Error" (#889) * Bug fix: edit project dialog verifies organism id (#914) * Bug fix: all colors in boolean reaction (from CellDesigner) are processed @@ -1092,7 +1174,7 @@ minerva (13.1.1) stable; urgency=medium inside compartment (#856) * Bug fix: searching for some drugs in chembl didn't provide any results even though that data exists, for instance 'DORLIMOMAB ARITOX' (#842) - * Bug fix: user wasn't logged out in all tabs when the log out event appeard + * Bug fix: user wasn't logged out in all tabs when the log out event appeared in only one of them (#847) -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 2 Jul 2019 19:00:00 +0200 @@ -1133,7 +1215,7 @@ minerva (13.1.0) stable; urgency=medium (#666) * Small improvement: list of projects is auto refreshed every 5 seconds if at least one of the project is uploading/removing (#610) - * Small improvement: passwords to email account and ldap are not sent over + * Small improvement: passwords to email account and LDAP are not sent over API (#732) * Small improvement: reactant/product/modifier specific colors are parsed properly from CellDesigner file (#597) @@ -1142,7 +1224,7 @@ minerva (13.1.0) stable; urgency=medium * Small improvement: Info tab provides information about model annotations and submap tabs provide information about submaps annotations if applicable (#591) - * Small improvement: uploading sbml file should automatically discover a file + * Small improvement: uploading SBML file should automatically discover a file type (#784) * Small improvement: when plugin listeners crash the system notifies user about problem with a plugin (#767) @@ -1157,19 +1239,19 @@ minerva (13.1.0) stable; urgency=medium SemanticZoomLevelTransparency (#801) * Small improvement: export/import from SBML support z-index in LAYOUT extension - * Bug fix: due to blocking of our requests from ctdbase the autocomplete for + * Bug fix: due to blocking of our requests from CTD base the autocomplete for this database is disabled * Bug fix: deprecated columns in data overlay are not visible to the end user (#827) * Bug fix: invalid color in data overlay provides proper feedback to the user (#822) * Bug fix: genetic variant overlay without name caused problems (#832) - * Bug fix: tair locus identifiers were used improperly - instead of id the + * Bug fix: Tair locus identifiers were used improperly - instead of id the name was used * Bug fix: plugin tab header wasn't properly resized after adding plugins that introduced second line for tab selection (#758) * Bug fix: invisible layer shouldn't be shown on the map (#813) - * Bug fix: list of availbale annotators is sorted alphabetically (#815) + * Bug fix: list of available annotators is sorted alphabetically (#815) * Bug fix: redirect url from export panel is fixed (#819) * Bug fix: allow to reupload the same file without closing add overlay dialog (#833) @@ -1193,8 +1275,8 @@ minerva (13.1.0) stable; urgency=medium slightly separated from target phenotype (#664) * Bug fix: order of genomes in admin panel doesn't change after refreshing list of genomes (#761) - * Bug fix: fixing situation when Molart started with variation overlay not - having the aa change information + * Bug fix: fixing situation when MolArt started with variation overlay not + having the a change information * Bug fix: plugin contect element width is adjusted when link to tabs are wrapped in more than one line (#758) * Bug fix: export to CellDesigner preserve font size (#798) @@ -1246,7 +1328,7 @@ minerva (12.2.2) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Tue, 9 Apr 2019 17:00:00 +0200 minerva (12.2.1) stable; urgency=medium - * Bug fix: export of reaction colorsi in SBML is properly encoded (COPASI can + * Bug fix: export of reaction colors in SBML is properly encoded (COPASI can read colors properly) (#744) * Bug fix: removing active plugin didn't switch plugin tab to the next loaded plugin (#757) @@ -1317,7 +1399,7 @@ minerva (12.2.0) stable; urgency=medium email account is provided * Small improvement: Plugin API allows to show/hide data overlays * Bug fix: Icons were sometimes not properly loaded on Safari (#661) - * Bug fix: migration scripts are compatibile with postgres 9.3 version that + * Bug fix: migration scripts are compatible with postgres 9.3 version that is default on Ubuntu 14 (#762) * Bug fix: update/remove button is disabled when user has no privileges for managing overlays (#742) @@ -1403,7 +1485,7 @@ minerva (12.1.6) stable; urgency=medium -- Piotr Gawron <piotr.gawron@uni.lu> Mon, 28 Jan 2019 16:00:00 +0200 minerva (12.1.5) stable; urgency=medium - * Bug fix: Drugbank changed output format which crashed drug connector + * Bug fix: DrugBank changed output format which crashed drug connector * Bug fix: word wrapping fixed in overlay table for long overlay names in Firefox browser @@ -1435,8 +1517,8 @@ minerva (12.1.3) stable; urgency=medium minerva (12.1.2) stable; urgency=medium * Bug fix: vmh annotations should be properly matching id entered in the input - * Bug fix: opacity was not working when highliting objects in plugins - * Bug fix: integer configurtion options (like SMTP_PORT) are properly + * Bug fix: opacity was not working when highlighting objects in plugins + * Bug fix: integer configuration options (like SMTP_PORT) are properly validated before saving * Bug fix: inside of reaction box wasn't properly aligned * Bug fix: too long data overlay name disturbed size of the map div and @@ -1470,7 +1552,7 @@ minerva (12.1.0) stable; urgency=medium * Small improvement: plugins have to access information about active submap * Feature: genome browser with gene variants * Feature: support of all CellDesigner element modifications - * Feature: ldap authentication + * Feature: LDAP authentication * Feature: multicolored anchors for data overlays * Feature: minerva is distributed using rpm packages * Small improvement: annotations from RHEA are handled @@ -1482,7 +1564,7 @@ minerva (12.1.0) stable; urgency=medium weren't provided properly * Bug fix: passwords in the configuration tab are hidden with '*' * Bug fix: user has access to transparency level when creating custom semantic - view (without this parametere functionality was very difficult to use) + view (without this parameter functionality was very difficult to use) * Bug fix: loading invalid plugin doesn't render empty div anymore * Bug fix: sorting of custom overlays was broken when description of overlay was present @@ -1495,7 +1577,7 @@ minerva (12.1.0) stable; urgency=medium * Bug fix: double click on user add button disabled * Bug fix: privileges are mirrored correctly across different popups * Bug fix: plugin tab css fixed - * Bug fix: uploading sbml file with no ids in glyphs returned error that + * Bug fix: uploading SBML file with no ids in glyphs returned error that could not be easily understand * Bug fix: ds_store files in subfolders crashed zip upload * Bug fix: when creating new user default privileges were not filled @@ -1564,7 +1646,7 @@ minerva (12.0.0) stable; urgency=medium * Feature: plugin API * Feature: all functionalities are provided via REST API * Feature: visualization of two (or more) overlaying results (like drug - target, mirna target) is highlighted with different icon + target, MiRNA target) is highlighted with different icon * Small improvement: email for account request contain configurable text * Small improvement: transparency level for data overlays is configurable * Small improvement: CellDesigner reactions of Modifier type are acceptable @@ -1585,7 +1667,7 @@ minerva (12.0.0) stable; urgency=medium * Small improvement: Data overlays can submap column to differentiate between maps * Small improvement: search by chemical names is possible - * Small improvement: auto complete functionality for drugs, mirnas and + * Small improvement: auto complete functionality for drugs, MiRNAs and chemicals * Small improvement: columns value and type are not mutually exclusive in data overlays @@ -1601,7 +1683,7 @@ minerva (12.0.0) stable; urgency=medium * Small improvement: submap reference in publication list * Small improvement: size of connection to database reduced to 90 (so default connection pool to postgres is not completely filled with minerva) - * Small improvement: visualization of sbml function improved (lambda + * Small improvement: visualization of SBML function improved (lambda expression removed from the definition) * Small improvement: handling of additional miriam types from BiGG ontology * Small improvement: configuration options are grouped in categories @@ -1681,17 +1763,17 @@ minerva (11.0.7) stable; urgency=medium * 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 + (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 + * Bug fix: fix a bug when entering invalid MiRNA id -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 14 Dec 2017 16:00:00 +0200 minerva (11.0.5) stable; urgency=medium - * Bug fix: fix on connection to drugbank database + * Bug fix: fix on connection to DrugBank database * Bug fix: posttranslational modification data was sometimes unavailable in search results panel @@ -1710,7 +1792,7 @@ minerva (11.0.3) stable; urgency=medium * Bug fix: links to invalid annotations were opening invalid web page * Bug fix: service resolving miriam resources doesn't work over http anymore - * Bug fix: chebi annotator doesn't work over http anymore + * Bug fix: CHEBI annotator doesn't work over http anymore -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 19 Oct 2017 13:50:00 +0200 @@ -1728,7 +1810,7 @@ minerva (11.0.0) stable; urgency=medium * Bug fix: security issue - access to specific map can be restricted by the user login - * Bug fix: sbgn import + * Bug fix: SBGN import * Bug fix: mesh connector * Rest API (documentation can be found here: https://git-r3lab.uni.lu/piotr.gawron/minerva/blob/master/README.md) @@ -1746,7 +1828,7 @@ minerva (10.0.5) stable; urgency=medium * Bug fix: interacting drugs can be found for RNAs * Bug fix: error handling improved on map upload - * Bug fix: taxonomy ncbi server switched to https + * Bug fix: taxonomy NCBI server switched to https * Overlay presents description field if possible @@ -1774,7 +1856,7 @@ minerva (10.0.3) stable; urgency=medium minerva (10.0.2) stable; urgency=medium - * Bug fix: markers for mirna targets visibility + * Bug fix: markers for MiRNA targets visibility -- Piotr Gawron <piotr.gawron@uni.lu> Thu, 29 Sep 2016 10:01:16 +0200 @@ -1843,15 +1925,15 @@ minerva (6) stable; urgency=low * Galaxy connector * Miriam types report * Advanced annotation options - * Uniprot annotation module + * UniProt annotation module * Customized validation of miriam annotations * Recon annotation service * Bug fix: Data autofill problem in user management * Bug fix: User privileges for adding project * Bug fix: Problem with some miriam entries in RDF format * Bug fix: Reporting of drawing problems - * Bug fix: Visualization of posttranslationa modification - * Bug fix: Drugbank problem after update of Drugbank interface + * Bug fix: Visualization of posttranslational modification + * Bug fix: DrugBank problem after update of DrugBank interface * Bug fix: Session scope fixed (browsing many maps at the same time) * Bug fix: Asynchronous removing/adding maps * Bug fix: Export to CellDesigner rarely produced corrupted CellDesigner file @@ -1879,12 +1961,12 @@ minerva (5) stable; urgency=low minerva (4) stable; urgency=low * Export of the part of the map into CellDesigner file - * Logo files managable via config webpage + * Logo files manageable via config webpage * Import data from GO * Custom overlay upload * Additional structural information imported from annotation service * Bug fix: Fonts and lines in hierarchical view - * Bug fix: Visualization of residues in rna, antisense rna, proteins + * Bug fix: Visualization of residues in RNA, antisense RNA, proteins * Bug fix: Problem with touching bubbles on touch interface * Bug fix: Problem with special UTF-8 characters in CellDesigner file * Bug fix: Problem with users and session expire diff --git a/CellDesigner-plugin/.project b/CellDesigner-plugin/.project index 7644e74c95ccb96514302b8fac71b10af8d5df71..5a8593cc67bc0f4a56843ed5043137b7b68fdcec 100644 --- a/CellDesigner-plugin/.project +++ b/CellDesigner-plugin/.project @@ -11,8 +11,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (12).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/annotation/.project b/annotation/.project index 5dd65eed5eb071becf35fe19a7e9aaab629db307..cc8da93dfb1360118ff0a1e84298e27f0072081e 100644 --- a/annotation/.project +++ b/annotation/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (3).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParserImpl.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParserImpl.java index 6ae3a6ba0480131109c5bb701b2e6811cdd68a0c..69012b6163542ff096c10681f0e6c47b2eabbcb7 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParserImpl.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/PubmedParserImpl.java @@ -212,7 +212,7 @@ public class PubmedParserImpl extends CachableInterface implements PubmedParser if (id == null) { return null; } - return getPubmedArticleById(Integer.valueOf(id.trim())); + return getPubmedArticleById(Integer.valueOf(id.replaceAll("[^0-9.]", "").trim())); } /** diff --git a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorImpl.java b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorImpl.java index 07b20b8a17d985153ed42120207f2d9ad39382ff..f7e7a33ac97e4fa897f31e7e1244e17a5385de41 100644 --- a/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorImpl.java +++ b/annotation/src/main/java/lcsb/mapviewer/annotation/services/annotators/EnsemblAnnotatorImpl.java @@ -46,7 +46,7 @@ public class EnsemblAnnotatorImpl extends ElementAnnotator implements EnsemblAnn /** * Version of the rest API that is supported by this annotator. */ - static final String SUPPORTED_VERSION = "15.1"; + static final String SUPPORTED_VERSION = "15.3"; /** * Url address of ensembl restful service. @@ -128,7 +128,8 @@ public class EnsemblAnnotatorImpl extends ElementAnnotator implements EnsemblAnn } @Override - public boolean annotateElement(final BioEntityProxy element, final MiriamData identifier, final AnnotatorData parameters) + public boolean annotateElement(final BioEntityProxy element, final MiriamData identifier, + final AnnotatorData parameters) throws AnnotatorException { if (identifier.getDataType().equals(MiriamType.ENSEMBL)) { String query = REST_SERVICE_URL + identifier.getResource() + URL_SUFFIX; diff --git a/commons/.project b/commons/.project index 2d0eff72f8eac2b33561e093d44e9ff86b84e90d..a26883597d46ac49b74ce855ae9b1c945e26ee8d 100644 --- a/commons/.project +++ b/commons/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (1).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java index 30436f65e06122abcb38aed21043928fb5df813f..1a5b7a15675b5f829073b668362ee3c2882f499e 100644 --- a/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java +++ b/commons/src/main/java/lcsb/mapviewer/common/XmlParser.java @@ -101,18 +101,27 @@ public final class XmlParser { * @return node from nodes list with the tagName name, <b>null</b> if such node * doesn't exist */ - public static Node getNode(final String tagName, final NodeList nodes) { + public static Node getNode(final String tagName, final NodeList nodes, final boolean ignoreNamespace) { for (int x = 0; x < nodes.getLength(); x++) { Node node = nodes.item(x); if (node.getNodeType() == Node.ELEMENT_NODE) { if (node.getNodeName().equalsIgnoreCase(tagName)) { return node; } + if (ignoreNamespace) { + if (node.getNodeName().toLowerCase().endsWith(":" + tagName.toLowerCase())) { + return node; + } + } } } return null; } + public static Node getNode(final String tagName, final NodeList nodes) { + return getNode(tagName, nodes, false); + } + /** * Method returns the child node of xml 'parentNode' with 'tagName' name. If * node could not be found then null is returned. @@ -301,8 +310,8 @@ public final class XmlParser { } /** - * This method transform color encoded in string (final CellDesigner format) into - * Color. + * This method transform color encoded in string (final CellDesigner format) + * into Color. * * @param color * string representing color diff --git a/converter-CellDesigner/.project b/converter-CellDesigner/.project index cf03151587cdb2953630e7b185b372732c08243e..bf1a13a878d0387dab56dd985e09c455750a7820 100644 --- a/converter-CellDesigner/.project +++ b/converter-CellDesigner/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (5).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/annotation/RestAnnotationParser.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/annotation/RestAnnotationParser.java index c831e934e97a6e0224a3a118bafbf24162e431bd..e732d65f57e509eb6e3cf272a47bd67704691fe7 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/annotation/RestAnnotationParser.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/annotation/RestAnnotationParser.java @@ -445,11 +445,11 @@ public class RestAnnotationParser { throw new InvalidArgumentException("Invalid notes node"); } - Node htmlNode = XmlParser.getNode("html", node.getChildNodes()); + Node htmlNode = XmlParser.getNode("html", node.getChildNodes(), true); if (htmlNode == null) { notes = XmlParser.nodeToString(node).trim(); } else { - Node bodyNode = XmlParser.getNode("body", htmlNode.getChildNodes()); + Node bodyNode = XmlParser.getNode("body", htmlNode.getChildNodes(), true); if (bodyNode != null) { notes = XmlParser.nodeToString(bodyNode).trim(); } diff --git a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/CellDesignerSpecies.java b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/CellDesignerSpecies.java index cd1ec4aa44ea0f957c3430fee38600c30953cafc..f2343a619a997e887aebf3648ae7294657e5789f 100644 --- a/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/CellDesignerSpecies.java +++ b/converter-CellDesigner/src/main/java/lcsb/mapviewer/converter/model/celldesigner/structure/CellDesignerSpecies.java @@ -187,7 +187,7 @@ public class CellDesignerSpecies<T extends Species> extends CellDesignerElement< setNotes(species.getNotes()); } else if (!string1.toLowerCase().contains(string2.toLowerCase())) { // insert new information - setNotes(string2 + getNotes()); + setNotes(string2 + "\n" + getNotes()); } } @@ -597,7 +597,8 @@ public class CellDesignerSpecies<T extends Species> extends CellDesignerElement< public void updateModelElementAfterLayoutAdded(final Species element) { } - protected StructuralState createStructuralState(final Species species, final String structuralState, final Double sourceAngle) { + protected StructuralState createStructuralState(final Species species, final String structuralState, + final Double sourceAngle) { if (structuralState == null) { return null; } diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java index 40c94d91091354b33823f42e657c518a859c6b4d..91b9da293c501fa15498ff2961906258824156d4 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/CellDesignerXmlParserTest.java @@ -1044,4 +1044,13 @@ public class CellDesignerXmlParserTest extends CellDesignerTestFunctions { assertNull(((Species) model2.getElementByElementId(protein2.getElementId())).getSubstanceUnits()); } + @Test + public void testNamespace() throws Exception { + CellDesignerXmlParser parser = new CellDesignerXmlParser(); + Model model = parser + .createModel(new ConverterParams().filename("testFiles/problematic/namespace.xml") + .sizeAutoAdjust(false)); + assertEquals("", model.getNotes()); + } + } diff --git a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/structure/SpeciesTest.java b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/structure/SpeciesTest.java index 959f74e50413a9aedf2d1f997fed50ad8bf4738a..6bbe527a54a7d16888ed0cc31ea5d57499d563d3 100644 --- a/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/structure/SpeciesTest.java +++ b/converter-CellDesigner/src/test/java/lcsb/mapviewer/converter/model/celldesigner/structure/SpeciesTest.java @@ -2,6 +2,7 @@ package lcsb.mapviewer.converter.model.celldesigner.structure; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -182,6 +183,20 @@ public class SpeciesTest extends CellDesignerTestFunctions { assertEquals(0, warningsCount); } + @Test + public void testUpdateNotes() { + String notes1 = "XXX A"; + String notes2 = "Notes B"; + CellDesignerSpecies<?> species = new CellDesignerSpecies<GenericProtein>(); + species.setNotes(notes1); + CellDesignerSpecies<?> species2 = new CellDesignerSpecies<GenericProtein>(); + species2.setNotes(notes2); + species.update(species2); + assertEquals(0, getWarnings().size()); + assertNotEquals(notes1 + notes2, species.getNotes()); + assertNotEquals(notes2 + notes1, species.getNotes()); + } + @Test(expected = InvalidArgumentException.class) public void testSetInvalidAmount() { CellDesignerSpecies<?> species = new CellDesignerSpecies<GenericProtein>(); diff --git a/converter-CellDesigner/testFiles/problematic/namespace.xml b/converter-CellDesigner/testFiles/problematic/namespace.xml new file mode 100644 index 0000000000000000000000000000000000000000..fe6a7035d60451dbea093c7281e93e46867af10a --- /dev/null +++ b/converter-CellDesigner/testFiles/problematic/namespace.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sbml xmlns="http://www.sbml.org/sbml/level2/version4" xmlns:bqbiol="http://biomodels.net/biology-qualifiers/" xmlns:bqmodel="http://biomodels.net/model-qualifiers/" xmlns:celldesigner="http://www.sbml.org/2001/ns/celldesigner" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" level="2" version="4"> + <model> + <notes> + <html:html> + <html:head> + <html:title /> + </html:head> + <html:body /> + </html:html> + </notes> + <annotation> + <celldesigner:extension> + <celldesigner:modelVersion>4.0</celldesigner:modelVersion> + <celldesigner:modelDisplay sizeX="600" sizeY="400" /> + <celldesigner:listOfCompartmentAliases /> + <celldesigner:listOfComplexSpeciesAliases /> + <celldesigner:listOfSpeciesAliases /> + <celldesigner:listOfGroups /> + <celldesigner:listOfProteins /> + <celldesigner:listOfGenes /> + <celldesigner:listOfRNAs /> + <celldesigner:listOfAntisenseRNAs /> + <celldesigner:listOfLayers /> + <celldesigner:listOfBlockDiagrams /> + </celldesigner:extension> + </annotation> + <listOfUnitDefinitions> + <unitDefinition metaid="substance" id="substance" name="substance"> + <listOfUnits> + <unit metaid="CDMT00001" kind="mole" /> + </listOfUnits> + </unitDefinition> + <unitDefinition metaid="volume" id="volume" name="volume"> + <listOfUnits> + <unit metaid="CDMT00002" kind="litre" /> + </listOfUnits> + </unitDefinition> + <unitDefinition metaid="area" id="area" name="area"> + <listOfUnits> + <unit metaid="CDMT00003" kind="metre" exponent="2" /> + </listOfUnits> + </unitDefinition> + <unitDefinition metaid="length" id="length" name="length"> + <listOfUnits> + <unit metaid="CDMT00004" kind="metre" /> + </listOfUnits> + </unitDefinition> + <unitDefinition metaid="time" id="time" name="time"> + <listOfUnits> + <unit metaid="CDMT00005" kind="second" /> + </listOfUnits> + </unitDefinition> + </listOfUnitDefinitions> + <listOfCompartments> + <compartment metaid="default" id="default" size="1" units="volume" /> + </listOfCompartments> + </model> +</sbml> \ No newline at end of file diff --git a/converter-SBGNML/.project b/converter-SBGNML/.project index cee08a22554f452159725e87277b35fcc4639be8..339d4b3234ce97f358d444c1376d2ff74e3a74dd 100644 --- a/converter-SBGNML/.project +++ b/converter-SBGNML/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (7).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/converter-graphics/.project b/converter-graphics/.project index a0ccbe6c1b2791d99338688883a6465b946a257b..98b2440a4a066452a6a62999018c06507ebf7ccc 100644 --- a/converter-graphics/.project +++ b/converter-graphics/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (6).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/LegendGenerator.java b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/LegendGenerator.java index a8a566c09f89bd3e3b4003ada52d9cd6634936e4..8cb9369e1c61bcef2ef92a171bec4e6b95c39ac0 100644 --- a/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/LegendGenerator.java +++ b/converter-graphics/src/main/java/lcsb/mapviewer/converter/graphics/LegendGenerator.java @@ -172,7 +172,11 @@ public class LegendGenerator { Font oldFont = graphics.getFont(); Set<Color> colorSet = new HashSet<>(); for (DataOverlayEntry entry : overlay.getEntries()) { - colorSet.add(((GenericDataOverlayEntry) entry).getColor()); + Color color = ((GenericDataOverlayEntry) entry).getColor(); + if (color == null) { + color = colorExtractor.getSimpleColor(); + } + colorSet.add(color); } List<Color> colors = new ArrayList<>(colorSet); colors.sort(new Comparator<Color>() { diff --git a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/LegendGeneratorTest.java b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/LegendGeneratorTest.java index 297cf345cb743d30d5ecebdc449bd169ae6f93b1..a866896e3033649db32bb5e939bdf61d0806b130 100644 --- a/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/LegendGeneratorTest.java +++ b/converter-graphics/src/test/java/lcsb/mapviewer/converter/graphics/LegendGeneratorTest.java @@ -69,6 +69,24 @@ public class LegendGeneratorTest extends GraphicsTestFunctions { file.delete(); } + @Test + public void testGenericWithNullColor() throws IOException { + DataOverlay overlay = new DataOverlay(); + GenericDataOverlayEntry entry = new GenericDataOverlayEntry(); + entry.setColor(Color.YELLOW); + overlay.addEntry(entry); + entry = new GenericDataOverlayEntry(); + entry.setColor(null); + entry.setElementId("re1"); + overlay.addEntry(entry); + generator.savetToPng(overlay, extractor, "tmp.png"); + File file = new File("tmp.png"); + assertTrue(file.exists()); + Mockito.verify(generator, times(1)).generateGenericLegendByColor(any(), any(), any()); + // Desktop.getDesktop().open(file); + file.delete(); + } + @Test public void testGenetic() throws IOException { DataOverlay overlay = new DataOverlay(); diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/extension/multi/MultiPackageNamingUtils.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/extension/multi/MultiPackageNamingUtils.java index 51873300ec19d791e123d2ea60757839c9f24513..1f10d6b1ec3840613b0ea585ccc4ef327d47cf7d 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/extension/multi/MultiPackageNamingUtils.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/extension/multi/MultiPackageNamingUtils.java @@ -66,10 +66,6 @@ public final class MultiPackageNamingUtils { return feature.getIdPrefix() + getSpeciesTypeId(element).replace("minerva_species_type_", ""); } - public static String getFeatureId(final Species element, final BioEntityFeature feature) { - return getFeatureId(element, feature); - } - public static boolean isFeatureId(final String featureTypeId, final BioEntityFeature feature) { return featureTypeId.startsWith(feature.getIdPrefix()); } diff --git a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java index 1ce0aecbe8b37f665cf6c0af8792148828265c70..dfca779a628a04ce66925f6427769e58745f53de 100644 --- a/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java +++ b/converter-sbml/src/main/java/lcsb/mapviewer/converter/model/sbml/species/SbmlSpeciesExporter.java @@ -488,6 +488,9 @@ public class SbmlSpeciesExporter extends SbmlElementExporter<Species, org.sbml.j multiDistinguisher += "\n" + element.getActivity(); multiDistinguisher += "\n" + element.getCharge(); multiDistinguisher += "\n" + element.getHomodimer(); + if (element instanceof Complex) { + multiDistinguisher += "\n" + element.getElementId(); + } } String result = element.getClass().getSimpleName() + "\n" + annotationNames + "\n" + element.getName() + "\n" + compartmentName + "\n" diff --git a/converter-sbml/testFiles/cd_for_multi/equal_complexes_with_structural_state.xml b/converter-sbml/testFiles/cd_for_multi/equal_complexes_with_structural_state.xml new file mode 100644 index 0000000000000000000000000000000000000000..4bb3a99c2282847c176786a1a224d92acd518be4 --- /dev/null +++ b/converter-sbml/testFiles/cd_for_multi/equal_complexes_with_structural_state.xml @@ -0,0 +1,113 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sbml xmlns="http://www.sbml.org/sbml/level2/version4" xmlns:celldesigner="http://www.sbml.org/2001/ns/celldesigner" level="2" version="4"> +<model metaid="Axonal_remodelling" id="Axonal_remodelling"> +<annotation> +<celldesigner:extension> +<celldesigner:modelVersion>4.0</celldesigner:modelVersion> +<celldesigner:modelDisplay sizeX="6000" sizeY="2000"/> +<celldesigner:listOfCompartmentAliases/> +<celldesigner:listOfComplexSpeciesAliases> +<celldesigner:complexSpeciesAlias id="csa18" species="s12096"> +<celldesigner:activity>inactive</celldesigner:activity> +<celldesigner:bounds x="3391.3334686147173" y="453.18641774891717" w="130.0" h="50.0"/> +<celldesigner:font size="12"/> +<celldesigner:view state="usual"/> +<celldesigner:backupSize w="0.0" h="0.0"/> +<celldesigner:backupView state="none"/> +<celldesigner:structuralState angle="1.5707963267948966"/> +<celldesigner:usualView> +<celldesigner:boxSize width="130.0" height="50.0"/> +<celldesigner:singleLine width="2.0"/> +<celldesigner:paint color="fff7f7f7" scheme="Color"/> +</celldesigner:usualView> +<celldesigner:briefView> +<celldesigner:innerPosition x="0.0" y="0.0"/> +<celldesigner:boxSize width="80.0" height="60.0"/> +<celldesigner:singleLine width="2.0"/> +<celldesigner:paint color="fff7f7f7" scheme="Color"/> +</celldesigner:briefView> +<celldesigner:info state="empty" angle="-1.5707963267948966"/> +</celldesigner:complexSpeciesAlias> +<celldesigner:complexSpeciesAlias id="csa24" species="s12096"> +<celldesigner:activity>inactive</celldesigner:activity> +<celldesigner:bounds x="4074.6971049783497" y="615.6409632034627" w="130.0" h="50.0"/> +<celldesigner:font size="12"/> +<celldesigner:view state="usual"/> +<celldesigner:backupSize w="0.0" h="0.0"/> +<celldesigner:backupView state="none"/> +<celldesigner:structuralState angle="1.5707963267948966"/> +<celldesigner:usualView> +<celldesigner:boxSize width="130.0" height="50.0"/> +<celldesigner:singleLine width="2.0"/> +<celldesigner:paint color="fff7f7f7" scheme="Color"/> +</celldesigner:usualView> +<celldesigner:briefView> +<celldesigner:innerPosition x="0.0" y="0.0"/> +<celldesigner:boxSize width="80.0" height="60.0"/> +<celldesigner:singleLine width="2.0"/> +<celldesigner:paint color="fff7f7f7" scheme="Color"/> +</celldesigner:briefView> +<celldesigner:info state="empty" angle="-1.5707963267948966"/> +</celldesigner:complexSpeciesAlias> +</celldesigner:listOfComplexSpeciesAliases> +<celldesigner:listOfSpeciesAliases/> +<celldesigner:listOfGroups/> +<celldesigner:listOfProteins/> +<celldesigner:listOfGenes/> +<celldesigner:listOfRNAs/> +<celldesigner:listOfAntisenseRNAs/> +<celldesigner:listOfLayers/> +<celldesigner:listOfBlockDiagrams/> +</celldesigner:extension> +</annotation> +<listOfUnitDefinitions> +<unitDefinition metaid="substance" id="substance" name="substance"> +<listOfUnits> +<unit metaid="CDMT00180" kind="mole"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="volume" id="volume" name="volume"> +<listOfUnits> +<unit metaid="CDMT00181" kind="litre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="area" id="area" name="area"> +<listOfUnits> +<unit metaid="CDMT00182" kind="metre" exponent="2"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="length" id="length" name="length"> +<listOfUnits> +<unit metaid="CDMT00183" kind="metre"/> +</listOfUnits> +</unitDefinition> +<unitDefinition metaid="time" id="time" name="time"> +<listOfUnits> +<unit metaid="CDMT00184" kind="second"/> +</listOfUnits> +</unitDefinition> +</listOfUnitDefinitions> +<listOfCompartments> +<compartment metaid="default" id="default" size="1" units="volume"/> +</listOfCompartments> +<listOfSpecies> +<species metaid="s12096" id="s12096" name="filamentous actin" compartment="default" initialAmount="0"> +<annotation> +<celldesigner:extension> +<celldesigner:positionToCompartment>inside</celldesigner:positionToCompartment> +<celldesigner:speciesIdentity> +<celldesigner:class>COMPLEX</celldesigner:class> +<celldesigner:hypothetical>true</celldesigner:hypothetical> +<celldesigner:name>filamentous actin</celldesigner:name> +<celldesigner:state> +<celldesigner:listOfStructuralStates> +<celldesigner:structuralState structuralState="ADP"/> +</celldesigner:listOfStructuralStates> +</celldesigner:state> +</celldesigner:speciesIdentity> +</celldesigner:extension> +</annotation> +</species> +</listOfSpecies> +</model> +</sbml> diff --git a/converter/.project b/converter/.project index 129ec9da5c64d938f92db650d7a107e1ecfb58fc..305714127019af79159400ec54675e21ef291964 100644 --- a/converter/.project +++ b/converter/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (4).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java index d45ef7e7a449fbfce1fa1ed92c60f44585db84f5..b32fd50e3cba1e864ad7dab3708b26c6cb86907c 100644 --- a/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java +++ b/converter/src/main/java/lcsb/mapviewer/converter/ComplexZipConverter.java @@ -31,6 +31,7 @@ import lcsb.mapviewer.converter.zip.ModelZipEntryFile; import lcsb.mapviewer.converter.zip.ZipEntryFile; import lcsb.mapviewer.converter.zip.ZipEntryFileFactory; import lcsb.mapviewer.model.cache.UploadedFileEntry; +import lcsb.mapviewer.model.map.layout.ReferenceGenomeType; import lcsb.mapviewer.model.map.model.ElementSubmodelConnection; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelSubmodelConnection; @@ -56,8 +57,7 @@ import lcsb.mapviewer.model.overlay.InvalidDataOverlayException; public class ComplexZipConverter { /** - * Size of the buffer used for accessing single chunk of data from input - * stream. + * Size of the buffer used for accessing single chunk of data from input stream. */ private static final int BUFFER_SIZE = 1024; @@ -94,8 +94,8 @@ public class ComplexZipConverter { * Creates complex {@link Model} that contains submaps. * * @param params - * {@link ComplexZipConverterParams object} with information about - * data from which result is going to be created + * {@link ComplexZipConverterParams object} with information about data + * from which result is going to be created * @return complex {@link Model} created from input data * @throws InvalidInputDataExecption * thrown when there is a problem with accessing input data @@ -258,8 +258,8 @@ public class ComplexZipConverter { } /** - * This method validates if information about model and submodels in the - * params are sufficient. If not then appropriate exception will be thrown. + * This method validates if information about model and submodels in the params + * are sufficient. If not then appropriate exception will be thrown. * * @param params * parameters to validate @@ -356,6 +356,18 @@ public class ComplexZipConverter { ByteArrayInputStream baos = new ByteArrayInputStream(fileEntry.getFileContent()); try { layout.addEntries(reader.readColorSchema(baos, parameters)); + + if (colorSchemaType == DataOverlayType.GENETIC_VARIANT) { + String genomeVersion = parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_GENOME_VERSION); + ReferenceGenomeType genomeType = ReferenceGenomeType.UCSC; + if (parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_GENOME_TYPE) != null) { + genomeType = ReferenceGenomeType + .valueOf(parameters.get(ZipEntryFileFactory.LAYOUT_HEADER_PARAM_GENOME_TYPE)); + } + layout.setGenomeType(genomeType); + layout.setGenomeVersion(genomeVersion); + } + } catch (final InvalidDataOverlayException e) { throw new InvalidInputDataExecption("Data overlay is invalid", e); } diff --git a/frontend-js/src/main/js/ServerConnector.js b/frontend-js/src/main/js/ServerConnector.js index 9998423f73d13a2197ed4fdcfe58f88e5569c6d3..cf3e453212c83a87884d05544b8b2986b4cf621e 100644 --- a/frontend-js/src/main/js/ServerConnector.js +++ b/frontend-js/src/main/js/ServerConnector.js @@ -2126,6 +2126,17 @@ ServerConnector.getReactions = function (params) { }); }; +/** + * + * @param {number} [params.modelId] + * @param {number[]} [params.ids] + * @param {number[]} [params.includedCompartmentIds] + * @param {number[]} [params.excludedCompartmentIds] + * @param {string[]} [params.columns] + * @param {string} [params.projectId] + * @param {string} [params.type] + * @returns {*} + */ ServerConnector.getAliases = function (params) { var self = this; var queryParams = { @@ -2150,7 +2161,10 @@ ServerConnector.getAliases = function (params) { }; return self.getProjectId(params.projectId).then(function (result) { queryParams.projectId = result; - if (filterParams.id.length > self.MAX_NUMBER_OF_IDS_IN_GET_QUERY) { + if (filterParams.id.length > self.MAX_NUMBER_OF_IDS_IN_GET_QUERY + || filterParams.excludedCompartmentIds.length > self.MAX_NUMBER_OF_IDS_IN_GET_QUERY + || filterParams.includedCompartmentIds.length > self.MAX_NUMBER_OF_IDS_IN_GET_QUERY + ) { return self.sendPostRequest(self.getAliasesUrl(queryParams), filterParams); } else { return self.sendGetRequest(self.getAliasesUrl(queryParams, filterParams)); diff --git a/frontend-js/src/main/js/gui/AddOverlayDialog.js b/frontend-js/src/main/js/gui/AddOverlayDialog.js index ba42107154a7879db4ca909f674df77269c367c4..a827253a285ae1be316c0a5798f2bd6a3467dd15 100644 --- a/frontend-js/src/main/js/gui/AddOverlayDialog.js +++ b/frontend-js/src/main/js/gui/AddOverlayDialog.js @@ -225,8 +225,7 @@ AddOverlayDialog.prototype.getFileContent = function () { var contentInput = $("[name='overlay-content']", self.getElement())[0]; if (contentInput.value !== undefined && contentInput.value !== null) { - contentInput.value = contentInput.value.trim(); - if (contentInput.value !== "") { + if (contentInput.value.trim() !== "") { self.setFileContent(contentInput.value); } } diff --git a/frontend-js/src/main/js/gui/admin/PluginAdminPanel.js b/frontend-js/src/main/js/gui/admin/PluginAdminPanel.js index d9a9f8c53fa8206358aa11373d99e93e85e4b64e..c813ae5c8fa8496c0f593af9fc7ab792284d920b 100644 --- a/frontend-js/src/main/js/gui/admin/PluginAdminPanel.js +++ b/frontend-js/src/main/js/gui/admin/PluginAdminPanel.js @@ -89,6 +89,7 @@ PluginAdminPanel.prototype._createGui = function () { input: false }).then(function (param) { if (param.status) { + $(button).prop('disabled', true); return self.getServerConnector().removePlugin({hash: $(button).attr("data")}).catch(function (error) { if (error instanceof NetworkError && error.statusCode === HttpStatus.NOT_FOUND) { GuiConnector.warn("Plugin does not exist anymore"); @@ -96,6 +97,7 @@ PluginAdminPanel.prototype._createGui = function () { throw error; } }).finally(function () { + $(button).prop('disabled', false); return self.onRefreshClicked(); }); } diff --git a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js index 36bcad174e7394b7946e326e54f97833251616b9..454a86cbb4ba16be13ae9d397723c37d222fa1f4 100644 --- a/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js +++ b/frontend-js/src/main/js/gui/leftPanel/GuiUtils.js @@ -601,14 +601,17 @@ GuiUtils.prototype.createSubMapLink = function (params) { var result = Functions.createElement({type: "div", className: params.className}); if (params.mapId !== undefined) { var button = document.createElement("button"); - var model = self.getMap().getSubmapById(params.mapId).getModel(); - - button.innerHTML = model.getName(); - button.onclick = function () { - return self.getMap().openSubmap(params.mapId); - }; - result.appendChild(this.createLabel(params.label)); - result.appendChild(button); + var submap = self.getMap().getSubmapById(params.mapId); + if (submap !== null) { + var model = submap.getModel(); + + button.innerHTML = model.getName(); + button.onclick = function () { + return self.getMap().openSubmap(params.mapId); + }; + result.appendChild(this.createLabel(params.label)); + result.appendChild(button); + } } return result; }; diff --git a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js index a18c3f54815f1da5354eaf603c46204271391c78..7d7d028d03bd4c126a9c7f7683e9297de32cfc5c 100644 --- a/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js +++ b/frontend-js/src/main/js/gui/leftPanel/OverlayPanel.js @@ -9,6 +9,7 @@ var AddOverlayDialog = require('../AddOverlayDialog'); var Panel = require('../Panel'); var PanelControlElementType = require('../PanelControlElementType'); var ValidationError = require('../../ValidationError'); +var NetworkError = require('../../NetworkError'); var GuiConnector = require('../../GuiConnector'); // noinspection JSUnusedLocalSymbols @@ -526,7 +527,15 @@ OverlayPanel.prototype.openEditOverlayDialog = function (overlay) { GuiConnector.showProcessing("Removing"); return self.removeOverlay(overlay).then(function () { $(windowSelf).dialog("close"); - }).catch(GuiConnector.alert).finally(function () { + }).catch(function (error) { + if (error instanceof NetworkError && error.statusCode === 404) { + GuiConnector.warn("Overlay has been already removed."); + $(windowSelf).dialog("close"); + return self.refresh(); + } else { + GuiConnector.alert(error); + } + }).finally(function () { GuiConnector.hideProcessing(); }); } diff --git a/frontend-js/src/main/js/gui/leftPanel/SubmapPanel.js b/frontend-js/src/main/js/gui/leftPanel/SubmapPanel.js index 0888efa83975f935482f9401c16a57a17c0558b0..496c5d7e78f87d2ab4f3f3b316e4d6cc94926971 100644 --- a/frontend-js/src/main/js/gui/leftPanel/SubmapPanel.js +++ b/frontend-js/src/main/js/gui/leftPanel/SubmapPanel.js @@ -184,7 +184,7 @@ SubmapPanel.prototype.init = function () { for (i = 0; i < types.length; i++) { var type = types[i]; var tableName = type + " submaps"; - if (type === "UNKNOWN") { + if (type === "UNKNOWN" || type === undefined || type === null) { tableName = "" } modelsByType[type].sort(function (modelA, modelB) { diff --git a/frontend-js/src/main/js/map/data/GeneVariant.js b/frontend-js/src/main/js/map/data/GeneVariant.js index b38277db7aea575b970ac4deac261623c04bdd86..d052b9894134767b61e39360a8b1e38793270241 100644 --- a/frontend-js/src/main/js/map/data/GeneVariant.js +++ b/frontend-js/src/main/js/map/data/GeneVariant.js @@ -1,30 +1,45 @@ "use strict"; +/** + * @typedef GeneVariantOptions + * @property {number} position + * @property {string} originalDna + * @property {string} modifiedDna + * @property {string} referenceGenomeType + * @property {string} referenceGenomeVersion + * @property {string} contig + * @property {string} [aminoAcidChange] + * @property {null|string} [allelFrequency] + * @property {null|string} [variantIdentifier] + */ + /** * - * @param {Object} javaObject - * @param {number} javaObject.position - * @param {string} javaObject.originalDna - * @param {string} javaObject.modifiedDna - * @param {string} javaObject.referenceGenomeType - * @param {string} javaObject.referenceGenomeVersion - * @param {string} javaObject.contig - * @param {string} [javaObject.aminoAcidChange] - * @param {null|string} [javaObject.allelFrequency] - * @param {null|string} [javaObject.variantIdentifier] - * + * @param {GeneVariantOptions|GeneVariant} javaObject * @constructor - */ + * */ function GeneVariant(javaObject) { - this.setPosition(javaObject.position); - this.setOriginalDna(javaObject.originalDna); - this.setModifiedDna(javaObject.modifiedDna); - this.setReferenceGenomeType(javaObject.referenceGenomeType); - this.setReferenceGenomeVersion(javaObject.referenceGenomeVersion); - this.setContig(javaObject.contig); - this.setAllelFrequency(javaObject.allelFrequency); - this.setVariantIdentifier(javaObject.variantIdentifier); - this.setAminoAcidChange(javaObject.aminoAcidChange); + if (javaObject instanceof GeneVariant) { + this.setPosition(javaObject.getPosition()); + this.setOriginalDna(javaObject.getOriginalDna()); + this.setModifiedDna(javaObject.getModifiedDna()); + this.setReferenceGenomeType(javaObject.getReferenceGenomeType()); + this.setReferenceGenomeVersion(javaObject.getReferenceGenomeVersion()); + this.setContig(javaObject.getContig()); + this.setAllelFrequency(javaObject.getAllelFrequency()); + this.setVariantIdentifier(javaObject.getVariantIdentifier()); + this.setAminoAcidChange(javaObject.getAminoAcidChange()); + } else { + this.setPosition(javaObject.position); + this.setOriginalDna(javaObject.originalDna); + this.setModifiedDna(javaObject.modifiedDna); + this.setReferenceGenomeType(javaObject.referenceGenomeType); + this.setReferenceGenomeVersion(javaObject.referenceGenomeVersion); + this.setContig(javaObject.contig); + this.setAllelFrequency(javaObject.allelFrequency); + this.setVariantIdentifier(javaObject.variantIdentifier); + this.setAminoAcidChange(javaObject.aminoAcidChange); + } } /** @@ -109,7 +124,7 @@ GeneVariant.prototype.getContig = function () { /** * - * @param {string} allelFrequency + * @param {string|number} allelFrequency */ GeneVariant.prototype.setAllelFrequency = function (allelFrequency) { if (allelFrequency === null) { diff --git a/frontend-js/src/main/js/map/data/LayoutAlias.js b/frontend-js/src/main/js/map/data/LayoutAlias.js index f313a307967cec55f930fed581b16d10049f7a43..ea6b0fc4780dd888407b85797968933bd45b2e29 100644 --- a/frontend-js/src/main/js/map/data/LayoutAlias.js +++ b/frontend-js/src/main/js/map/data/LayoutAlias.js @@ -2,43 +2,63 @@ var GeneVariant = require('./GeneVariant'); +/** + * @typedef LayoutAliasOptions + * @property {number} idObject + * @property {number} [value] + * @property {{rgb:number}} [color] + * @property {number} modelId + * @property {string} [description] + * @property {number} [uniqueId] + * @property {string} [type=LayoutAlias.LIGHT] + * @property {Array} [geneVariations] */ + /** * Class representing alias visualized in a overlay. * - * @param {number} javaObject.idObject - * @param {number} [javaObject.value] - * @param {{rgb:number}} [javaObject.color] - * @param {number} javaObject.modelId - * @param {string} [javaObject.description] - * @param {number} [javaObject.uniqueId] - * @param {string} [javaObject.type=LayoutAlias.LIGHT] - * @param {Array} [javaObject.geneVariations] - */ + * @param {LayoutAliasOptions|LayoutAlias} javaObject + * @constructor + * */ function LayoutAlias(javaObject) { - this.setId(javaObject.idObject); - this.setValue(javaObject.value); - this.setColor(javaObject.color); - this.setModelId(javaObject.modelId); - this.setDescription(javaObject.description); - this.setDataOverlayEntryId(javaObject.uniqueId); - if (javaObject.type === undefined) { - this.setType(LayoutAlias.LIGHT); - } else if (javaObject.type === LayoutAlias.GENETIC_VARIANT) { - if (javaObject.geneVariations !== undefined) { - this.setType(LayoutAlias.GENETIC_VARIANT); - } else { - this.setType(LayoutAlias.LIGHT); + if (javaObject instanceof LayoutAlias) { + this.setId(javaObject.getId()); + this.setValue(javaObject.getValue()); + this.setColor(javaObject.getColor()); + this.setModelId(javaObject.getModelId()); + this.setDescription(javaObject.getDescription()); + this.setDataOverlayEntryId(javaObject.getDataOverlayEntryId()); + this.setType(javaObject.getType()); + + this.setGeneVariants([]); + for (var i = 0; i < javaObject.getGeneVariants().length; i++) { + this.addGeneVariant(new GeneVariant(javaObject.getGeneVariants()[i])); } - } else if (javaObject.type === LayoutAlias.GENERIC) { - this.setType(LayoutAlias.GENERIC); } else { - throw new Error("Unknown type: " + javaObject.type); - } + this.setId(javaObject.idObject); + this.setValue(javaObject.value); + this.setColor(javaObject.color); + this.setModelId(javaObject.modelId); + this.setDescription(javaObject.description); + this.setDataOverlayEntryId(javaObject.uniqueId); + if (javaObject.type === undefined) { + this.setType(LayoutAlias.LIGHT); + } else if (javaObject.type === LayoutAlias.GENETIC_VARIANT) { + if (javaObject.geneVariations !== undefined) { + this.setType(LayoutAlias.GENETIC_VARIANT); + } else { + this.setType(LayoutAlias.LIGHT); + } + } else if (javaObject.type === LayoutAlias.GENERIC) { + this.setType(LayoutAlias.GENERIC); + } else { + throw new Error("Unknown type: " + javaObject.type); + } - this.setGeneVariants([]); - if (javaObject.geneVariations !== undefined) { - for (var i = 0; i < javaObject.geneVariations.length; i++) { - this.addGeneVariant(new GeneVariant(javaObject.geneVariations[i])); + this.setGeneVariants([]); + if (javaObject.geneVariations !== undefined) { + for (var j = 0; j < javaObject.geneVariations.length; j++) { + this.addGeneVariant(new GeneVariant(javaObject.geneVariations[j])); + } } } } diff --git a/frontend-js/src/main/js/map/window/AliasInfoWindow.js b/frontend-js/src/main/js/map/window/AliasInfoWindow.js index d14c5ac9a24ad4ff259eeb1f20c091f414f7490e..e4c874f0e8afbbabe90df5fab507cea46adeded9 100644 --- a/frontend-js/src/main/js/map/window/AliasInfoWindow.js +++ b/frontend-js/src/main/js/map/window/AliasInfoWindow.js @@ -450,7 +450,16 @@ AliasInfoWindow.prototype.createGenomicDiv = function (params) { promises = []; result.forEach(function (overlayEntries) { if (overlayEntries !== undefined) { - overlaysData = overlaysData.concat(overlayEntries); + //check if we have gene variants split into multiple groups + if (overlayEntries.length > 1 && overlayEntries[0].getType() === LayoutAlias.GENETIC_VARIANT) { + var tmpAlias = new LayoutAlias(overlayEntries[0]); + for (var i = 1; i < overlayEntries.length; i++) { + tmpAlias.setGeneVariants(tmpAlias.getGeneVariants().concat(overlayEntries[i].getGeneVariants())); + overlaysData.push(tmpAlias); + } + } else { + overlaysData = overlaysData.concat(overlayEntries); + } } }); return Promise.all(promises); diff --git a/model-command/.project b/model-command/.project index 9dbb4bccdca54896776ec561b100cd19e5790deb..76db27f2b567de901675394f1adc139045b9abdf 100644 --- a/model-command/.project +++ b/model-command/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (8).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/AddElementPrefixCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/AddElementPrefixCommand.java index 752aa47d3532df9135ef1432d24381f69a0a8460..8184b8a700d4837f6579ec85cbe123899f4c00b5 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/AddElementPrefixCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/AddElementPrefixCommand.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.commands; import lcsb.mapviewer.common.exception.NotImplementedException; +import lcsb.mapviewer.model.map.layout.graphics.Layer; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.reaction.Reaction; import lcsb.mapviewer.model.map.species.Element; @@ -37,6 +38,9 @@ public class AddElementPrefixCommand extends ModelCommand { reaction.setIdReaction(prefix + reaction.getElementId()); model.addReaction(reaction); } + for (Layer layer : model.getLayers()) { + layer.setLayerId(prefix + layer.getLayerId()); + } } } diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/MergeCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/MergeCommand.java index e7a1e84e71672aa0e5f1dfc4aaa9eef385c5e11c..d40aaa69e4e148cee4879ed4b3cf1c6ad4bcb76e 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/MergeCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/MergeCommand.java @@ -40,6 +40,7 @@ public class MergeCommand extends NewModelCommand { result.addElements(model.getElements()); result.addReactions(new ArrayList<>(model.getReactions())); + result.addLayers(model.getLayers()); mapHeight = Math.max(mapHeight, offsetY + model.getHeight() + MARGIN); mapWidth = Math.max(mapWidth, offsetX + model.getWidth() + MARGIN); diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/MoveCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/MoveCommand.java index 96508b571b460834547b7758713085f34d499d27..e1755ce3db6240587209fff1558c03bdc4d1c764 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/MoveCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/MoveCommand.java @@ -3,6 +3,11 @@ package lcsb.mapviewer.commands; import java.awt.geom.Line2D; import lcsb.mapviewer.common.exception.NotImplementedException; +import lcsb.mapviewer.model.graphics.PolylineData; +import lcsb.mapviewer.model.map.layout.graphics.Layer; +import lcsb.mapviewer.model.map.layout.graphics.LayerOval; +import lcsb.mapviewer.model.map.layout.graphics.LayerRect; +import lcsb.mapviewer.model.map.layout.graphics.LayerText; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.reaction.AbstractNode; import lcsb.mapviewer.model.map.reaction.Reaction; @@ -24,6 +29,7 @@ public class MoveCommand extends ModelCommand { * Delta x. */ private double dx; + /** * Delta y. */ @@ -93,6 +99,27 @@ public class MoveCommand extends ModelCommand { reaction.getLine().setLine(i, line.getX1() + dx, line.getY1() + dy, line.getX2() + dx, line.getY2() + dy); } } + + for (Layer layer : model.getLayers()) { + for (LayerText text : layer.getTexts()) { + text.setX(text.getX() + dx); + text.setY(text.getY() + dy); + } + for (LayerRect rect : layer.getRectangles()) { + rect.setX(rect.getX() + dx); + rect.setY(rect.getY() + dy); + } + for (LayerOval oval : layer.getOvals()) { + oval.setX(oval.getX() + dx); + oval.setY(oval.getY() + dy); + } + for (PolylineData line : layer.getLines()) { + for (int i = 0; i < line.getLines().size(); i++) { + Line2D l = line.getLines().get(i); + line.setLine(i, l.getX1() + dx, l.getY1() + dy, l.getX2() + dx, l.getY2() + dy); + } + } + } } } diff --git a/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java b/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java index 5c8dba38badd517a8ecac322cf6ddf441faa6f86..d70b50c701fba73ee93b5da8e1721aa7672c7fc6 100644 --- a/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java +++ b/model-command/src/main/java/lcsb/mapviewer/commands/SubModelCommand.java @@ -54,7 +54,8 @@ public class SubModelCommand extends NewModelCommand { * @param polygon * #polygon that limits the area for the new model */ - public SubModelCommand(final Model model, final Path2D polygon, final Set<Integer> elementIds, final Set<Integer> reactionIds) { + public SubModelCommand(final Model model, final Path2D polygon, final Set<Integer> elementIds, + final Set<Integer> reactionIds) { super(model); this.polygon = polygon; this.elementIds = elementIds; @@ -165,7 +166,7 @@ public class SubModelCommand extends NewModelCommand { for (final Layer layer : result.getLayers()) { List<LayerText> textToRemove = new ArrayList<>(); for (final LayerText text : layer.getTexts()) { - if (!(polygon.intersects(text.getBorder()))) { + if (!(polygon.intersects(text.getBorder())) || elementIds.size() > 0 || reactionIds.size() > 0) { textToRemove.add(text); } } diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/AddElementPrefixCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/AddElementPrefixCommandTest.java index 9433ffaaaa1a5e7469cd7df18af12e12e2296a7d..e77efee4da9403c1f9826e585ebc7a85dd31de3d 100644 --- a/model-command/src/test/java/lcsb/mapviewer/commands/AddElementPrefixCommandTest.java +++ b/model-command/src/test/java/lcsb/mapviewer/commands/AddElementPrefixCommandTest.java @@ -1,9 +1,11 @@ package lcsb.mapviewer.commands; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import org.junit.Test; +import lcsb.mapviewer.model.map.layout.graphics.Layer; import lcsb.mapviewer.model.map.model.Model; public class AddElementPrefixCommandTest extends CommandTestFunctions { @@ -16,4 +18,14 @@ public class AddElementPrefixCommandTest extends CommandTestFunctions { assertNotNull(model.getElementByElementId("pre" + id)); } + @Test + public void testPrefixLayer() throws CommandExecutionException { + Model model = super.createSimpleModel(); + Layer layer = new Layer(); + layer.setLayerId("x"); + model.addLayer(layer); + new AddElementPrefixCommand(model, "pre").execute(); + assertNotEquals("x", layer.getLayerId()); + } + } diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/MoveCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/MoveCommandTest.java index 309846d2bf93f1cd319b2003e2e769b00c83a9de..fa83087774b268ddeb184a9f4718fbe6425857ee 100644 --- a/model-command/src/test/java/lcsb/mapviewer/commands/MoveCommandTest.java +++ b/model-command/src/test/java/lcsb/mapviewer/commands/MoveCommandTest.java @@ -5,11 +5,16 @@ import static org.junit.Assert.assertTrue; import java.awt.geom.Line2D; import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; import org.junit.Test; import lcsb.mapviewer.common.Configuration; import lcsb.mapviewer.model.graphics.PolylineData; +import lcsb.mapviewer.model.map.layout.graphics.Layer; +import lcsb.mapviewer.model.map.layout.graphics.LayerOval; +import lcsb.mapviewer.model.map.layout.graphics.LayerRect; +import lcsb.mapviewer.model.map.layout.graphics.LayerText; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.reaction.Product; import lcsb.mapviewer.model.map.reaction.Reactant; @@ -72,4 +77,66 @@ public class MoveCommandTest extends CommandTestFunctions { assertEquals(new Point2D.Double(50, 40), state.getPosition()); } + @Test + public void testMoveLayerText() throws CommandExecutionException { + Model model = super.createSimpleModel(); + + Layer layer = new Layer(); + LayerText text = new LayerText(new Rectangle2D.Double(10, 20, 30, 40), "xyz"); + layer.addLayerText(text); + model.addLayer(layer); + + new MoveCommand(model, 10, 20).execute(); + + assertEquals(20, text.getX(), Configuration.EPSILON); + assertEquals(40, text.getY(), Configuration.EPSILON); + } + + @Test + public void testMoveLayerRect() throws CommandExecutionException { + Model model = super.createSimpleModel(); + + Layer layer = new Layer(); + LayerRect rect = new LayerRect(new Rectangle2D.Double(10, 20, 30, 40)); + layer.addLayerRect(rect); + model.addLayer(layer); + + new MoveCommand(model, 10, 20).execute(); + + assertEquals(20, rect.getX(), Configuration.EPSILON); + assertEquals(40, rect.getY(), Configuration.EPSILON); + } + + @Test + public void testMoveLayerOval() throws CommandExecutionException { + Model model = super.createSimpleModel(); + + Layer layer = new Layer(); + LayerOval oval = new LayerOval(); + oval.setX(10.0); + oval.setY(20.0); + layer.addLayerOval(oval); + model.addLayer(layer); + + new MoveCommand(model, 10, 20).execute(); + + assertEquals(20, oval.getX(), Configuration.EPSILON); + assertEquals(40, oval.getY(), Configuration.EPSILON); + } + + @Test + public void testMoveLayerLine() throws CommandExecutionException { + Model model = super.createSimpleModel(); + + Layer layer = new Layer(); + PolylineData line = new PolylineData(new Point2D.Double(10, 20), new Point2D.Double(30, 40)); + layer.addLayerLine(line); + model.addLayer(layer); + + new MoveCommand(model, 10, 20).execute(); + + assertEquals(0, new Point2D.Double(20, 40).distance(line.getStartPoint()), Configuration.EPSILON); + assertEquals(0, new Point2D.Double(40, 60).distance(line.getEndPoint()), Configuration.EPSILON); + } + } diff --git a/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java b/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java index b96f428a94b66a7a1525cbf00a3b6d0fc056cb6f..4150cb89665bd91763b6489f68ed1b3ce1580e9b 100644 --- a/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java +++ b/model-command/src/test/java/lcsb/mapviewer/commands/SubModelCommandTest.java @@ -4,6 +4,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import java.awt.geom.Path2D; +import java.awt.geom.Rectangle2D; import java.util.Arrays; import java.util.HashSet; @@ -11,6 +12,8 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import lcsb.mapviewer.model.map.layout.graphics.Layer; +import lcsb.mapviewer.model.map.layout.graphics.LayerText; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelComparator; @@ -148,6 +151,31 @@ public class SubModelCommandTest extends CommandTestFunctions { assertEquals(0, copy.getReactions().size()); } + @Test + public void testGetSubmodelWithElementIdsAndTextArea() throws Exception { + Model model = getModelForFile("testFiles/spliting_test_Case.xml", false); + + Path2D polygon = new Path2D.Double(); + polygon.moveTo(0, 0); + polygon.lineTo(0, 1000); + polygon.lineTo(1000, 1000); + polygon.lineTo(1000, 0); + polygon.closePath(); + model.getElementByElementId("sa2").setId(-2); + + Layer layer = new Layer(); + LayerText text = new LayerText(new Rectangle2D.Double(10, 10, 20, 20), "xy"); + layer.addLayerText(text); + model.addLayer(layer); + + Model copy = new SubModelCommand(model, polygon, new HashSet<>(Arrays.asList(-2)), new HashSet<>()).execute(); + + assertEquals(1, copy.getElements().size()); + assertEquals(0, copy.getReactions().size()); + assertEquals(1, copy.getLayers().size()); + assertEquals(0, copy.getLayers().iterator().next().getTexts().size()); + } + @Test public void testGetSubmodelWithEmptyElementIds() throws Exception { Model model = getModelForFile("testFiles/spliting_test_Case.xml", true); diff --git a/model/.project b/model/.project index aaaa0fce06cdb04fcc7a38db966e3d7a802e568f..44a99170d5a1d8c098ee5fc1f26b3028de600c4c 100644 --- a/model/.project +++ b/model/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (2).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java index 934187f82a623151ad14f9cb85a89152405f5b39..7690ea3d5d77a176034128ff729f8939a2e409e6 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/MiriamType.java @@ -3463,7 +3463,7 @@ public enum MiriamType { }, new Class<?>[] {}, "MIR:00000273", new Class<?>[] {}, "massbank", - "PB000166"), + "MSBNK-IPB_Halle-PB000166"), MATHEMATICAL_MODELLING_ONTOLOGY("Mathematical Modelling Ontology", "http://bioportal.bioontology.org/ontologies/MAMO", @@ -6670,8 +6670,8 @@ public enum MiriamType { private List<Class<? extends BioEntity>> validClass = new ArrayList<>(); /** - * When class from this list is marked as "require at least one annotation" - * then annotation of this type is valid. + * When class from this list is marked as "require at least one annotation" then + * annotation of this type is valid. */ private List<Class<? extends BioEntity>> requiredClass = new ArrayList<>(); @@ -6775,8 +6775,8 @@ public enum MiriamType { * identifier in the format NAME:IDENTIFIER. Where NAME is the name * from {@link MiriamType#commonName} and IDENTIFIER is resource * identifier. - * @return {@link MiriamData} representing generalIdentifier, when identifier - * is invalid InvalidArgumentException is thrown + * @return {@link MiriamData} representing generalIdentifier, when identifier is + * invalid InvalidArgumentException is thrown */ public static MiriamData getMiriamDataFromIdentifier(final String generalIdentifier) { int index = generalIdentifier.indexOf(":"); diff --git a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerRect.java b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerRect.java index 03619c01582a599651288c0933dd296fd9c9a545..0eeff2c1ee6062c55f2f075b384d4ca0138efc32 100644 --- a/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerRect.java +++ b/model/src/main/java/lcsb/mapviewer/model/map/layout/graphics/LayerRect.java @@ -1,6 +1,7 @@ package lcsb.mapviewer.model.map.layout.graphics; import java.awt.Color; +import java.awt.geom.Rectangle2D; import java.io.Serializable; import javax.persistence.Column; @@ -103,6 +104,13 @@ public class LayerRect implements Serializable, Drawable { height = layerRect.getHeight(); } + public LayerRect(final Rectangle2D rect) { + x = rect.getX(); + y = rect.getY(); + width = rect.getWidth(); + height = rect.getHeight(); + } + /** * Prepares a copy of the object. * @@ -260,10 +268,12 @@ public class LayerRect implements Serializable, Drawable { return width * height; } + @Override public Color getBorderColor() { return borderColor; } + @Override public void setBorderColor(final Color borderColor) { this.borderColor = borderColor; } diff --git a/pathvisio/.project b/pathvisio/.project index 03de699bdd6e159ef0855b7312363a55bc669abf..d68188f8af21a94b27220f3577020e3b37604f87 100644 --- a/pathvisio/.project +++ b/pathvisio/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder.launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/xml/ModelContructor.java b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/xml/ModelContructor.java index be478b490aeed102e684fc2345a12ab06c8fdca0..c3262b837b30ab0a5bf13625e6d23103b9af4650 100644 --- a/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/xml/ModelContructor.java +++ b/pathvisio/src/main/java/lcsb/mapviewer/wikipathway/xml/ModelContructor.java @@ -249,8 +249,8 @@ public class ModelContructor { } /** - * This function adds {@link Complex} to model from graph. ComplexName is set - * as groupId from GPML + * This function adds {@link Complex} to model from graph. ComplexName is set as + * groupId from GPML * * @param groups * list of groups @@ -303,6 +303,7 @@ public class ModelContructor { * ... */ protected void addElement(final Model model, final Graph graph, final Data data) { + for (final DataNode dataNode : graph.getDataNodes()) { Species species = createSpecies(dataNode); species.addMiriamData(biopaxFactory.getMiriamData(graph.getBiopaxData(), dataNode.getBiopaxReferences())); @@ -338,7 +339,7 @@ public class ModelContructor { } else { if (!shape.isCompartment()) { - if (shape.getShape().equals(GpmlShape.OVAL)) { + if (Objects.equals(shape.getShape(), GpmlShape.OVAL)) { LayerOval oval = createOval(shape); data.layer.addLayerOval(oval); } else if (shape.getComments().size() > 0 || shape.getTextLabel() != null) { @@ -1242,8 +1243,7 @@ public class ModelContructor { } /** - * Tries to find a name to assign to complexes if complexes don't contain - * them. + * Tries to find a name to assign to complexes if complexes don't contain them. * * @param model * model where complexes are placed @@ -1314,8 +1314,8 @@ public class ModelContructor { } /** - * Tries to find a name to assign to compartments if compartments don't - * contain them. + * Tries to find a name to assign to compartments if compartments don't contain + * them. * * @param model * model where compartments are placed @@ -1365,8 +1365,8 @@ public class ModelContructor { } /** - * By default gpml doesn't offer information about compartments structure. - * This function fixes assignments to compartment and compartment aliases. + * By default gpml doesn't offer information about compartments structure. This + * function fixes assignments to compartment and compartment aliases. * * @param model * model where assignments are fixed. diff --git a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/GPMLToModelTest.java b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/GPMLToModelTest.java index 0bfed93e4100eece5dabb7ff96db13fdced30858..43314e18d3ba4dafcac70bbc99238b5f269a5a60 100644 --- a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/GPMLToModelTest.java +++ b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/GPMLToModelTest.java @@ -262,6 +262,13 @@ public class GPMLToModelTest extends WikipathwaysTestFunctions { assertEquals(0, getWarnings().size()); } + @Test + public void testUnknownElementType() throws Exception { + String fileName = "testFiles/complex/unknown_element.gpml"; + new GPMLToModel().getModel(fileName); + assertEquals(1, getWarnings().size()); + } + @Test public void testComplexName() throws Exception { String fileName = "testFiles/complex/complex_with_name.gpml"; diff --git a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/xml/ShapeParserTest.java b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/xml/ShapeParserTest.java index 071e64f9b365872437751f3f23f2672f1260835c..10fb112f723a1497705d4bb7a5542e4b24aa255e 100644 --- a/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/xml/ShapeParserTest.java +++ b/pathvisio/src/test/java/lcsb/mapviewer/wikipathway/xml/ShapeParserTest.java @@ -118,6 +118,15 @@ public class ShapeParserTest extends WikipathwaysTestFunctions { assertEquals(0, getWarnings().size()); } + @Test + public void testParseUnknown() throws Exception { + Element node = fileToNode("testFiles/elements/unknown.xml"); + Shape shape = parser.parse(node); + assertNotNull(shape); + + assertEquals(1, getWarnings().size()); + } + @Test public void testParsePent() throws Exception { Element node = fileToNode("testFiles/elements/pent.xml"); diff --git a/pathvisio/testFiles/complex/unknown_element.gpml b/pathvisio/testFiles/complex/unknown_element.gpml new file mode 100644 index 0000000000000000000000000000000000000000..57ea5983c95db00e73a9f2d565bc7d517f813177 --- /dev/null +++ b/pathvisio/testFiles/complex/unknown_element.gpml @@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Pathway xmlns="http://pathvisio.org/GPML/2013a" Name="Insulin Signaling" Last-Modified="10/17/2013" Organism="Homo sapiens"> + <Graphics BoardWidth="769.3333333333334" BoardHeight="710.0" /> + <Shape TextLabel="eee" GraphId="c42d9"> + <Comment>oval</Comment> + <BiopaxRef>d35</BiopaxRef> + <Graphics CenterX="668.25" CenterY="636.25" Width="353.5" Height="123.5" ZOrder="16384" FontSize="10" Valign="Middle" ShapeType="unknown-type" Rotation="0.0" /> + </Shape> + <Biopax> + </Biopax> +</Pathway> + diff --git a/pathvisio/testFiles/elements/unknown.xml b/pathvisio/testFiles/elements/unknown.xml new file mode 100644 index 0000000000000000000000000000000000000000..04dfe4a9ec14beb3e9f424109943f3587d63630e --- /dev/null +++ b/pathvisio/testFiles/elements/unknown.xml @@ -0,0 +1,5 @@ + <Shape TextLabel="eee" GraphId="c42d9"> + <Comment>oval</Comment> + <BiopaxRef>d35</BiopaxRef> + <Graphics CenterX="668.25" CenterY="636.25" Width="353.5" Height="123.5" ZOrder="16384" FontSize="10" Valign="Middle" ShapeType="unknown-type" Rotation="0.0" /> + </Shape> diff --git a/persist/.project b/persist/.project index c76dcb2aefa82b83fd6ecb778b2001f2f790c783..6988b02d15c133024d99338879f5734516594fb0 100644 --- a/persist/.project +++ b/persist/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (9).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/rest-api/.project b/rest-api/.project index a4d854734795cb0c96fbba9960acd8b0cc90d759..fc78f7be58cd8140b065e18ab8de6a529224fa10 100644 --- a/rest-api/.project +++ b/rest-api/.project @@ -21,8 +21,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (10).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertController.java b/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertController.java index 15b6edf1280b61f156199492d5f25378f1247c4d..606fd8ab2c38a3a7f200bb6b4359934893cb881c 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/convert/ConvertController.java @@ -60,13 +60,19 @@ public class ConvertController extends BaseController { this.modelConverters = modelConverters; } - @PostMapping(value = "/{fromFormat}:{toFormat:.+}", produces = MediaType.APPLICATION_XML_VALUE) + @PostMapping(value = "/{fromFormat}:{toFormat:.+}", + consumes = { + MediaType.APPLICATION_XML_VALUE, + MediaType.APPLICATION_OCTET_STREAM_VALUE, + MediaType.TEXT_PLAIN_VALUE + }, + produces = MediaType.APPLICATION_XML_VALUE) public byte[] convertInput(final @PathVariable(value = "fromFormat") String fromFormat, final @PathVariable(value = "toFormat") String toFormat, - final @RequestBody byte[] body) - throws IOException, QueryException, SBMLException, + final @RequestBody byte[] body) throws IOException, QueryException, SBMLException, InvalidInputDataExecption, InconsistentModelException, ConverterException { - ConverterParams params = createConvertParams(body); + + ConverterParams params = new ConverterParams().inputStream(new ByteArrayInputStream(body)); MinervaLoggerAppender appender = MinervaLoggerAppender.createAppender(); Model original; try { @@ -78,6 +84,8 @@ public class ConvertController extends BaseController { } } original.setNotes(notes.toString()); + } catch (final InvalidInputDataExecption | ConverterException e) { + throw new QueryException("Problem with input file", e); } finally { MinervaLoggerAppender.unregisterLogEventStorage(appender); } @@ -101,14 +109,19 @@ public class ConvertController extends BaseController { return model; } - @PostMapping(value = "/image/{fromFormat}:{toFormat:.+}") + @PostMapping(value = "/image/{fromFormat}:{toFormat:.+}", + consumes = { + MediaType.APPLICATION_XML_VALUE, + MediaType.APPLICATION_OCTET_STREAM_VALUE, + MediaType.TEXT_PLAIN_VALUE + }) public @ResponseBody ResponseEntity<byte[]> convertInputToImage( final @PathVariable(value = "fromFormat") String fromFormat, final @PathVariable(value = "toFormat") String toFormat, final @RequestBody byte[] body) throws QueryException, IOException, DrawingException { Model original = null; try { - original = getModelParserByNameOrClass(fromFormat).createModel(createConvertParams(body)); + original = getModelParserByNameOrClass(fromFormat).createModel(new ConverterParams().inputStream(new ByteArrayInputStream(body))); } catch (final InvalidInputDataExecption | ConverterException e) { throw new QueryException("Problem with input file", e); } @@ -172,7 +185,11 @@ public class ConvertController extends BaseController { } - @PostMapping(value = "/merge/{fromFormat}:{toFormat}") + @PostMapping(value = "/merge/{fromFormat}:{toFormat}", + consumes = { + MediaType.APPLICATION_OCTET_STREAM_VALUE, + MediaType.TEXT_PLAIN_VALUE + }) public @ResponseBody ResponseEntity<byte[]> mergeFilesToFile( final @PathVariable(value = "fromFormat") String fromFormat, final @PathVariable(value = "toFormat") String toFormat, @@ -255,12 +272,6 @@ public class ConvertController extends BaseController { return result; } - private ConverterParams createConvertParams(final byte[] input) { - InputStream is = new ByteArrayInputStream(input); - - return new ConverterParams().inputStream(is); - } - private Converter getModelParserByNameOrClass(final String id) throws QueryException { try { return getModelParserByName(id); diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/files/FileController.java b/rest-api/src/main/java/lcsb/mapviewer/api/files/FileController.java index 2791e86191abc4a43f2f776da083c7de121d4329..78c0261ca8c8b711c89e3a2de4d565362d11fa1e 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/files/FileController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/files/FileController.java @@ -72,7 +72,7 @@ public class FileController extends BaseController { } @PreAuthorize("@fileService.getOwnerByFileId(#id)?.login == authentication.name") - @PostMapping(value = "/{id}:uploadContent") + @PostMapping(value = "/{id}:uploadContent", consumes = { MediaType.APPLICATION_OCTET_STREAM_VALUE }) public UploadedFileEntry uploadContent(final @PathVariable(value = "id") Integer id, final @RequestBody byte[] data) throws QueryException { UploadedFileEntry fileEntry = fileService.getById(id); diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/DirectoryNameGenerator.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/DirectoryNameGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..6945611975e77a3c3cceea97524720011fd012c0 --- /dev/null +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/DirectoryNameGenerator.java @@ -0,0 +1,25 @@ +package lcsb.mapviewer.api.projects; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import lcsb.mapviewer.common.Md5; +import lcsb.mapviewer.services.interfaces.IProjectService; + +@Service +public class DirectoryNameGenerator implements IDirectoryNameGenerator { + + private IProjectService projectService; + + @Autowired + public DirectoryNameGenerator(final IProjectService projectService) { + this.projectService = projectService; + } + + @Override + public String projectIdToDirectoryName(final String projectId) { + long id = projectService.getNextId(); + return Md5.compute(projectId + "-" + id); + } + +} diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/IDirectoryNameGenerator.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/IDirectoryNameGenerator.java new file mode 100644 index 0000000000000000000000000000000000000000..5c9ef3a36ba74112bb41e331c899ecf21d1f49f1 --- /dev/null +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/IDirectoryNameGenerator.java @@ -0,0 +1,6 @@ +package lcsb.mapviewer.api.projects; + +public interface IDirectoryNameGenerator { + String projectIdToDirectoryName(final String projectId); + +} diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java index 7070811b4698af462796af34be0f85649812f122..23fe21ddd8e4a9a100f32feeca2ea71db62437c3 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/ProjectController.java @@ -56,7 +56,6 @@ import lcsb.mapviewer.annotation.services.annotators.AnnotatorException; import lcsb.mapviewer.api.BaseController; import lcsb.mapviewer.api.OperationNotAllowedException; import lcsb.mapviewer.api.minervanet.MinervaNetController; -import lcsb.mapviewer.common.Md5; import lcsb.mapviewer.common.comparator.StringComparator; import lcsb.mapviewer.common.exception.InvalidArgumentException; import lcsb.mapviewer.converter.Converter; @@ -103,6 +102,7 @@ public class ProjectController extends BaseController { private ServletContext context; private MinervaNetController minervaNetController; private IProjectService projectService; + private IDirectoryNameGenerator directoryNameGenerator; private IConfigurationService configurationService; private IModelService modelService; private IElementService elementService; @@ -116,10 +116,14 @@ public class ProjectController extends BaseController { private List<Converter> modelConverters; @Autowired - public ProjectController(final ServletContext context, final IUserService userService, final IProjectService projectService, - final IMeshService meshService, final List<Converter> modelConverters, final IFileService fileService, final IElementService elementService, - final IReactionService reactionService, final IModelService modelService, final IConfigurationService configurationService, - final IProjectBackgroundService projectBackgroundService, final MinervaNetController minervaNetController) { + public ProjectController(final ServletContext context, final IUserService userService, + final IProjectService projectService, + final IMeshService meshService, final List<Converter> modelConverters, final IFileService fileService, + final IElementService elementService, + final IReactionService reactionService, final IModelService modelService, + final IConfigurationService configurationService, + final IProjectBackgroundService projectBackgroundService, final MinervaNetController minervaNetController, + final IDirectoryNameGenerator directoryNameGenerator) { this.context = context; this.userService = userService; this.projectService = projectService; @@ -132,6 +136,7 @@ public class ProjectController extends BaseController { this.configurationService = configurationService; this.projectBackgroundService = projectBackgroundService; this.minervaNetController = minervaNetController; + this.directoryNameGenerator = directoryNameGenerator; } @PreAuthorize("hasAnyAuthority('IS_ADMIN', 'READ_PROJECT:' + #projectId)") @@ -533,7 +538,8 @@ public class ProjectController extends BaseController { final Authentication authentication, final @RequestParam Map<String, Object> body, final @Size(max = 255) @Pattern(regexp = "^[a-z0-9A-Z\\-_]+$", - message = "projectId can contain only alphanumeric characters and -_") @PathVariable(value = "projectId") String projectId) + message = "projectId can contain only alphanumeric characters and -_") + @PathVariable(value = "projectId") String projectId) throws IOException, QueryException, SecurityException { fixFormUrlEncodedBody(body); if (Objects.equals(body.get("zip-entries"), "")) { @@ -642,8 +648,7 @@ public class ProjectController extends BaseController { } protected String computePathForProject(final String projectId, final String path) { - long id = projectService.getNextId(); - return path + "/../map_images/" + Md5.compute(projectId + "-" + id) + "/"; + return path + "/../map_images/" + directoryNameGenerator.projectIdToDirectoryName(projectId) + "/"; } @PreAuthorize("hasAuthority('IS_ADMIN')" diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java index 41c4aa8425ae438d297d08f8d7ea61c0c7a9a931..855237c155cb6fe578d49e75c2ef2eb8e2574046 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/models/ModelController.java @@ -75,7 +75,6 @@ import lcsb.mapviewer.model.map.InconsistentModelException; import lcsb.mapviewer.model.map.layout.ProjectBackground; import lcsb.mapviewer.model.map.model.Model; import lcsb.mapviewer.model.map.model.ModelData; -import lcsb.mapviewer.model.overlay.DataOverlay; import lcsb.mapviewer.model.overlay.DataOverlayEntry; import lcsb.mapviewer.model.overlay.InvalidDataOverlayException; import lcsb.mapviewer.model.user.User; @@ -440,9 +439,8 @@ public class ModelController extends BaseController { // Color with overlays for (final Integer overlayId : overlayIdsList) { - DataOverlay overlay = dataOverlayService.getDataOverlayById(projectId, overlayId); + Set<DataOverlayEntry> schemas = dataOverlayService.getDataOverlayEntriesById(projectId, overlayId); - Set<DataOverlayEntry> schemas = overlay.getEntries(); new ColorModelCommand(part, schemas, userService.getColorExtractorForUser(user)).execute(); } diff --git a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayEntryDTOSerializer.java b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayEntryDTOSerializer.java index 0be25c64e64a9763e0b3d5d390d69adec39e3771..289b2067995b215fad89145fd6de8c265a0142e3 100644 --- a/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayEntryDTOSerializer.java +++ b/rest-api/src/main/java/lcsb/mapviewer/api/projects/overlays/OverlayEntryDTOSerializer.java @@ -101,7 +101,8 @@ public class OverlayEntryDTOSerializer extends JsonSerializer<OverlayEntryDTO> { "description", "type", "geneVariations", - "uniqueId"); + "uniqueId", + "width"); } private void writeField(final JsonGenerator gen, final String field, final Object value, final PropertyFilter filter) throws IOException { diff --git a/service/.project b/service/.project index ec5afbcdc1c391a84415795af66de4941722f8d2..ba2b83aa611bce5c683cfb1ce886d97d3cf16200 100644 --- a/service/.project +++ b/service/.project @@ -16,8 +16,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (11).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/DataOverlayService.java b/service/src/main/java/lcsb/mapviewer/services/impl/DataOverlayService.java index a0e639c28e176c772d6885c63329c0bed4010d68..e4475473940695c92f458d01ed6a106e37ab5eaf 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/DataOverlayService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/DataOverlayService.java @@ -9,6 +9,7 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -261,13 +262,13 @@ public class DataOverlayService implements IDataOverlayService { } /** - * {@link DataOverlayEntry} sometimes contains merged value from few rows. - * This method split single {@link DataOverlayEntry} object to simple flat - * objects that can be serialized in a simple tab separated file. + * {@link DataOverlayEntry} sometimes contains merged value from few rows. This + * method split single {@link DataOverlayEntry} object to simple flat objects + * that can be serialized in a simple tab separated file. * * @param originalSchema - * original {@link DataOverlayEntry} object that we want to split - * into flat objects + * original {@link DataOverlayEntry} object that we want to split into + * flat objects * @return {@link List} of flat schema objects obtained from input */ private List<DataOverlayEntry> splitColorSchema(final DataOverlayEntry originalSchema) { @@ -372,8 +373,8 @@ public class DataOverlayService implements IDataOverlayService { } /** - * Returns String representing data of {@link GeneVariantDataOverlayEntry} - * that should appear in a given {@link ColorSchemaColumn}. + * Returns String representing data of {@link GeneVariantDataOverlayEntry} that + * should appear in a given {@link ColorSchemaColumn}. * * @param schema * object for which data will be returned @@ -592,4 +593,16 @@ public class DataOverlayService implements IDataOverlayService { } } + @Override + public Set<DataOverlayEntry> getDataOverlayEntriesById(final String projectId, final Integer overlayId) throws ObjectNotFoundException { + Set<DataOverlayEntry> result = getDataOverlayById(projectId, overlayId).getEntries(); + Hibernate.initialize(result); + for (DataOverlayEntry dataOverlayEntry : result) { + Hibernate.initialize(dataOverlayEntry.getTypes()); + Hibernate.initialize(dataOverlayEntry.getMiriamData()); + Hibernate.initialize(dataOverlayEntry.getCompartments()); + } + return result; + } + } diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/PluginService.java b/service/src/main/java/lcsb/mapviewer/services/impl/PluginService.java index 91a30a5943b49df9a93843be26af0c6898c8edd2..ae10e42858fd9265a2de7409d31396cbe5304fda 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/PluginService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/PluginService.java @@ -80,7 +80,7 @@ public class PluginService implements IPluginService { @Override public void update(final PluginDataEntry entry) { - pluginDataEntryDao.add(entry); + pluginDataEntryDao.update(entry); } @Override diff --git a/service/src/main/java/lcsb/mapviewer/services/impl/PublicationService.java b/service/src/main/java/lcsb/mapviewer/services/impl/PublicationService.java index a33c3b08f5ec40ae1f4c9be0b25781d6b41203ad..20d8f7a8938c0fe7c28ad99f8ee68a7bd29457ed 100644 --- a/service/src/main/java/lcsb/mapviewer/services/impl/PublicationService.java +++ b/service/src/main/java/lcsb/mapviewer/services/impl/PublicationService.java @@ -41,7 +41,7 @@ public class PublicationService implements IPublicationService { for (final String id : missingIds) { try { Article article = pubmedParser.getPubmedArticleById(id); - if (article != null) { + if (article != null && id.equals(article.getPubmedId())) { articleDao.add(article); } } catch (final PubmedSearchException e) { diff --git a/service/src/main/java/lcsb/mapviewer/services/interfaces/IDataOverlayService.java b/service/src/main/java/lcsb/mapviewer/services/interfaces/IDataOverlayService.java index e1d7490320316be2235074ce268acdde49f9a419..1160199429516bb02dd0b7b4e67bfe6d7c56a895 100644 --- a/service/src/main/java/lcsb/mapviewer/services/interfaces/IDataOverlayService.java +++ b/service/src/main/java/lcsb/mapviewer/services/interfaces/IDataOverlayService.java @@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.List; +import java.util.Set; import java.util.concurrent.ExecutionException; import lcsb.mapviewer.commands.ColorExtractor; @@ -38,11 +39,11 @@ public interface IDataOverlayService { private User user; /** - * Input stream with coloring information data in the stream should - * correspond to a file that can be parsed by - * {@link lcsb.mapviewer.services.utils.ColorSchemaXlsxReader - * ColorSchemaReader} . This is a copy of original input stream, so we can - * read this input stream multiple times. + * Input stream with coloring information data in the stream should correspond + * to a file that can be parsed by + * {@link lcsb.mapviewer.services.utils.ColorSchemaXlsxReader ColorSchemaReader} + * . This is a copy of original input stream, so we can read this input stream + * multiple times. */ private ByteArrayOutputStream colorInputStreamCopy; @@ -169,10 +170,11 @@ public interface IDataOverlayService { void waitForJobQueueToEmpty() throws InterruptedException, ExecutionException; - void add(final DataOverlay overlay); FileEntry getDataOverlayFileById(final String projectId, final Integer overlayId) throws ObjectNotFoundException; byte[] generateLegend(String projectId, Integer overlayId, ColorExtractor colorExtractor) throws ObjectNotFoundException, IOException; + + Set<DataOverlayEntry> getDataOverlayEntriesById(String projectId, Integer overlayId) throws ObjectNotFoundException; } diff --git a/test_spelling.sh b/test_spelling.sh new file mode 100755 index 0000000000000000000000000000000000000000..5ecbd2f27d8c91b53a0860fb04ec99cc815d88f8 --- /dev/null +++ b/test_spelling.sh @@ -0,0 +1,20 @@ +#!/bin/bash +result=0 + +while read filename +do + html='' + case $filename in *.html) + html=" --mode html ";; + esac + lines=`cat $filename | aspell $html --lang=en --encoding=utf-8 --add-extra-dicts=./.aspell.en.pws --add-extra-dicts=./.aspell-api-exceptions.pws list|wc -l` + if [ $lines -ne 0 ] + then + echo "[$filename] Unknown words:" + echo + cat $filename | aspell --lang=en $html --encoding=utf-8 --add-extra-dicts=./.aspell.en.pws --add-extra-dicts=./.aspell-api-exceptions.pws list |sort |uniq + result=1 + fi +done <<< "$(ls web/target/generated-docs/*.html CHANGELOG -c1)" + +exit $result diff --git a/web/.project b/web/.project index 0897627f36b8100d9a710728adbbec63f6411634..fc438eb8ab84b68d91263d67ef2b69ca18fed173 100644 --- a/web/.project +++ b/web/.project @@ -21,8 +21,13 @@ </arguments> </buildCommand> <buildCommand> - <name>net.sf.eclipsecs.core.CheckstyleBuilder</name> + <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name> + <triggers>full,incremental,</triggers> <arguments> + <dictionary> + <key>LaunchConfigHandle</key> + <value><project>/.externalToolBuilders/net.sf.eclipsecs.core.CheckstyleBuilder (13).launch</value> + </dictionary> </arguments> </buildCommand> <buildCommand> diff --git a/web/src/main/asciidoc/genomics.adoc b/web/src/main/asciidoc/genomics.adoc index a265d559e15ffd583cf0d22c6cb456f6d76cf510..881c63c77c0c34fe162250ba15f7eb628fe68925 100644 --- a/web/src/main/asciidoc/genomics.adoc +++ b/web/src/main/asciidoc/genomics.adoc @@ -64,9 +64,6 @@ include::{snippets}/genomics/download_genome/curl-request.adoc[] === Request Parameters include::{snippets}/genomics/download_genome/request-parameters.adoc[] -=== Response Fields -include::{snippets}/genomics/download_genome/response-fields.adoc[] - == Get information about specific downloaded genome === CURL sample @@ -105,9 +102,6 @@ include::{snippets}/genomics/delete_genome_information/path-parameters.adoc[] === Path Parameters include::{snippets}/genomics/add_gene_mapping/path-parameters.adoc[] -=== Response Fields -include::{snippets}/genomics/add_gene_mapping/response-fields.adoc[] - === CURL sample include::{snippets}/genomics/add_gene_mapping/curl-request.adoc[] diff --git a/web/src/main/asciidoc/index.adoc b/web/src/main/asciidoc/index.adoc index ee56886b186ef75271330782698c27730fdc48bb..b5eb4d5e4ed806a989e53d46b6d9c6a72781d830 100644 --- a/web/src/main/asciidoc/index.adoc +++ b/web/src/main/asciidoc/index.adoc @@ -17,7 +17,7 @@ For API calls that require authentication MINERVA_AUTH_TOKEN obtained during log == QuickStart guide Here is sample example that shows information about all projects accessible by guest account (anonymous user): -include::{snippets}/projects/project_data/list/curl-request.adoc[] +include::{snippets}/projects/project_data/list_guest/curl-request.adoc[] If we are interested in the API calls that require more privileges than anonymous user we need to login first: diff --git a/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java b/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java index dfbd94d4b23f3d1f3ce62107a145f40d0a98b734..b1f7095eddf13633e96c71d77e23f03a62169e54 100644 --- a/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java +++ b/web/src/test/java/lcsb/mapviewer/web/AllIntegrationTests.java @@ -9,6 +9,7 @@ import lcsb.mapviewer.web.bean.utils.StartupBeanTest; @RunWith(Suite.class) @SuiteClasses({ ConfigurationControllerIntegrationTest.class, ChemicalControllerIntegrationTest.class, + CommandFormatterTest.class, CommentControllerIntegrationTest.class, ConvertControllerIntegrationTest.class, DrugControllerIntegrationTest.class, @@ -24,6 +25,7 @@ import lcsb.mapviewer.web.bean.utils.StartupBeanTest; ParameterControllerIntegrationTest.class, PluginControllerIntegrationTest.class, ProjectControllerIntegrationTest.class, + ProjectControllerIntegrationForDocsTest.class, PublicationsControllerIntegrationTest.class, ReactionControllerIntegrationTest.class, SpringSecurityGeneralIntegrationTest.class, diff --git a/web/src/test/java/lcsb/mapviewer/web/CommandFormatterTest.java b/web/src/test/java/lcsb/mapviewer/web/CommandFormatterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c14fa665a8bc585d05401ac1903c7e859041ae0e --- /dev/null +++ b/web/src/test/java/lcsb/mapviewer/web/CommandFormatterTest.java @@ -0,0 +1,46 @@ +package lcsb.mapviewer.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import lcsb.mapviewer.web.utils.CommandFormatterWithReplacingPostFilenameHeader; + +@RunWith(SpringJUnit4ClassRunner.class) +public class CommandFormatterTest extends ControllerIntegrationTest { + + @Test + public void testExtractDefaultContentTypeContentType() throws Exception { + CommandFormatterWithReplacingPostFilenameHeader commandFormatter = new CommandFormatterWithReplacingPostFilenameHeader(" "); + String contentType = commandFormatter.getContentType(Arrays.asList(" ")); + assertEquals(MediaType.APPLICATION_OCTET_STREAM_VALUE, contentType); + } + + @Test + public void testExtractCustomContentType() throws Exception { + CommandFormatterWithReplacingPostFilenameHeader commandFormatter = new CommandFormatterWithReplacingPostFilenameHeader(" "); + String contentType = commandFormatter.getContentType(Arrays.asList(" ", "-H \"Content-Type: text/plain\"")); + assertEquals("text/plain", contentType); + } + + @Test + public void testExtractCustomContentTypeSingleQuote() throws Exception { + CommandFormatterWithReplacingPostFilenameHeader commandFormatter = new CommandFormatterWithReplacingPostFilenameHeader(" "); + String contentType = commandFormatter.getContentType(Arrays.asList(" ", "-H 'Content-Type: text/plain'")); + assertEquals("text/plain", contentType); + } + + @Test + public void testExtractCustomContentTypeWithCharset() throws Exception { + CommandFormatterWithReplacingPostFilenameHeader commandFormatter = new CommandFormatterWithReplacingPostFilenameHeader(" "); + String contentType = commandFormatter.getContentType(Arrays.asList(" ", "-H 'Content-Type: text/html; charset=utf-8'")); + assertTrue(contentType.contains("charset=utf-8")); + } + +} diff --git a/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java index 176d3c651664de0a825f5f33372714d07b69cf24..9d28d3f46ea35c993a93ccc96482bf9c5286ff30 100644 --- a/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/CommentControllerIntegrationTest.java @@ -672,7 +672,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -717,7 +717,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest public void testAddElementCommentAsAnonymous() throws Exception { String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -748,7 +748,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -789,7 +789,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -815,7 +815,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -844,7 +844,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -871,7 +871,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -892,7 +892,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -919,7 +919,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -941,7 +941,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("modelId", map.getId() + "")))); @@ -1024,7 +1024,7 @@ public class CommentControllerIntegrationTest extends ControllerIntegrationTest private String createContentBody(final String type, final String value) throws IOException, UnsupportedEncodingException { List<BasicNameValuePair> params = new ArrayList<>(Arrays.asList( new BasicNameValuePair("email", "a@a.lu"), - new BasicNameValuePair("content", "tes content"), + new BasicNameValuePair("content", "test content"), new BasicNameValuePair("pinned", "true"), new BasicNameValuePair("coordinates", "10,2"), new BasicNameValuePair("modelId", map.getId() + ""))); diff --git a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java index 101b715b8e6e12e0eedb43382de6551c7092b32d..80b5ad1d833ffac55b91fd7ed2d6d9a9ffb93962 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ControllerIntegrationTest.java @@ -194,12 +194,12 @@ public abstract class ControllerIntegrationTest extends TestUtils { } /** - * This method can be used to work around the fact that MockMvc cannot - * retrieve cookies from Spring Security. The Reason for that is that MockMvc - * calls the controller directly and (partially?) bypasses Spring. + * This method can be used to work around the fact that MockMvc cannot retrieve + * cookies from Spring Security. The Reason for that is that MockMvc calls the + * controller directly and (partially?) bypasses Spring. * <p> - * This method creates a mocked session that can be used in a request as - * opposed to the token. + * This method creates a mocked session that can be used in a request as opposed + * to the token. * </p> * <p> * FIXME: Find a better solution, that does not violate the spirit of @@ -366,13 +366,13 @@ public abstract class ControllerIntegrationTest extends TestUtils { + "</lambda></math>"); map.addFunction(sbmlFunction); - SbmlParameter sbmlParameter = new SbmlParameter("param1"); - sbmlParameter.setName("ppp"); + SbmlParameter sbmlParameter = new SbmlParameter("parameter1"); + sbmlParameter.setName("D coefficient"); sbmlParameter.setValue(1.2); map.addParameter(sbmlParameter); SbmlUnit sbmlUnit = new SbmlUnit("u1"); - sbmlUnit.setName("uuu"); + sbmlUnit.setName("Weight"); map.addUnit(sbmlUnit); Compartment comp = createCompartment(); @@ -382,6 +382,7 @@ public abstract class ControllerIntegrationTest extends TestUtils { reaction.setZ(2); reaction.setLine(new PolylineData(new Point2D.Double(0, 0), new Point2D.Double(10, 0))); reaction.addMiriamData(new MiriamData(MiriamType.PUBMED, "28725475")); + reaction.addMiriamData(new MiriamData(MiriamType.PUBMED, "123,")); SbmlKinetics kinetics = new SbmlKinetics(); kinetics.setDefinition("<math xmlns=\"http://www.w3.org/1998/Math/MathML\"><lambda>\n" + "<bvar>\n" @@ -444,7 +445,7 @@ public abstract class ControllerIntegrationTest extends TestUtils { ProjectBackground background = new ProjectBackground("Normal"); int id = 0; for (final ModelData model : project.getModels()) { - ProjectBackgroundImageLayer layer = new ProjectBackgroundImageLayer(model, "dir_" + (id++)); + ProjectBackgroundImageLayer layer = new ProjectBackgroundImageLayer(model, "directory_" + (id++)); background.addProjectBackgroundImageLayer(layer); } background.setDefaultOverlay(true); @@ -483,7 +484,8 @@ public abstract class ControllerIntegrationTest extends TestUtils { return element; } - private void assignCoordinates(final double x, final double y, final double width, final double height, final Element protein) { + private void assignCoordinates(final double x, final double y, final double width, final double height, + final Element protein) { protein.setX(x); protein.setY(y); protein.setZ(z++); @@ -585,7 +587,8 @@ public abstract class ControllerIntegrationTest extends TestUtils { return createOverlay(project, admin, content, DataOverlayType.GENERIC); } - protected DataOverlay createOverlay(final Project project, final User admin, final String content, final DataOverlayType type) + protected DataOverlay createOverlay(final Project project, final User admin, final String content, + final DataOverlayType type) throws Exception { UploadedFileEntry file = new UploadedFileEntry(); file.setFileContent(content.getBytes()); @@ -668,4 +671,9 @@ public abstract class ControllerIntegrationTest extends TestUtils { .description("target element that we are searching for in format TYPE:ID") .optional()); } + + protected PathParametersSnippet projectPathParameters() { + return pathParameters(parameterWithName("projectId").description("project identifier")); + } + } diff --git a/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java index 0a703d35f65b0cd616f71542ab61bbbc1d508bf1..54618a6497af371dce41dffbded9462a6ba12181 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ConvertControllerIntegrationTest.java @@ -11,17 +11,22 @@ import static org.springframework.restdocs.request.RequestDocumentation.paramete import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.awt.geom.Rectangle2D; import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; import org.apache.commons.io.FileUtils; import org.junit.Test; @@ -38,7 +43,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lcsb.mapviewer.converter.ConverterParams; import lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser; +import lcsb.mapviewer.model.map.layout.graphics.Layer; +import lcsb.mapviewer.model.map.layout.graphics.LayerText; import lcsb.mapviewer.model.map.model.Model; +import lcsb.mapviewer.model.map.model.ModelFullIndexed; import lcsb.mapviewer.model.map.species.Element; @RunWith(SpringJUnit4ClassRunner.class) @@ -51,7 +59,7 @@ public class ConvertControllerIntegrationTest extends ControllerIntegrationTest public void testConvertInvalidFile() throws Exception { String body = "invalid content"; RequestBuilder request = post("/api/convert/image/SBGN-ML:svg") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .contentType(MediaType.TEXT_PLAIN_VALUE) .content(body); mockMvc.perform(request) @@ -79,7 +87,7 @@ public class ConvertControllerIntegrationTest extends ControllerIntegrationTest public void testConvertInvalidMapFormat() throws Exception { String body = "invalid content"; RequestBuilder request = post("/api/convert/image/unknown:svg") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .contentType(MediaType.TEXT_PLAIN_VALUE) .content(body); mockMvc.perform(request) @@ -155,8 +163,8 @@ public class ConvertControllerIntegrationTest extends ControllerIntegrationTest String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); RequestBuilder request = post("/api/convert/{inputFormat}:{outputFormat}", "CellDesigner_SBML", "GPML") .header("post-filename", "input_file.xml") - .content(content.getBytes("UTF-8")) - .characterEncoding("UTF-8"); + .contentType(MediaType.TEXT_PLAIN_VALUE) + .content(content); mockMvc.perform(request) .andDo(document("converter/format_conversion", @@ -428,4 +436,89 @@ public class ConvertControllerIntegrationTest extends ControllerIntegrationTest assertTrue(inputs.size() > 0); } + @Test + public void testInvalidGpml2Sbml() throws Exception { + String content = "blah"; + + RequestBuilder request = post("/api/convert/{inputFormat}:{outputFormat}", "GPML", "SBML") + .header("post-filename", "input_file.xml") + .content(content.getBytes("UTF-8")) + .characterEncoding("UTF-8"); + mockMvc.perform(request) + .andExpect(status().isBadRequest()); + } + + @Test + public void testInvalidGpml2Svg() throws Exception { + String content = "blah"; + + RequestBuilder request = post("/api/convert/image/{inputFormat}:{outputFormat}", "GPML", "svg") + .header("post-filename", "input_file.xml") + .content(content.getBytes("UTF-8")) + .characterEncoding("UTF-8"); + mockMvc.perform(request) + .andExpect(status().isBadRequest()); + } + + @Test + public void convertCellDesignerToGpmlUsingUrlEncoded() throws Exception { + File file = new File("src/test/resources/convert/cd-sample.xml"); + String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8); + content = URLEncoder.encode(content, "UTF-8"); + RequestBuilder request = post("/api/convert/{inputFormat}:{outputFormat}", "CellDesigner_SBML", "GPML") + .header("post-filename", "input_file.xml") + .content(content.getBytes("UTF-8")) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .characterEncoding("UTF-8"); + + mockMvc.perform(request) + .andExpect(status().isUnsupportedMediaType()); + } + + @Test + public void testMergeCellDesignerWithTextArea() throws Exception { + Model model = new ModelFullIndexed(null); + Layer layer = new Layer(); + LayerText text = new LayerText(new Rectangle2D.Double(10, 20, 30, 40), "test text"); + model.addLayer(layer); + layer.addLayerText(text); + model.setWidth(300); + model.setHeight(400); + CellDesignerXmlParser parser = new CellDesignerXmlParser(); + String xml = parser.model2String(model); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (ZipOutputStream zos = new ZipOutputStream(baos)) { + ZipEntry entry = new ZipEntry("maps/map.xml"); + + zos.putNextEntry(entry); + zos.write(xml.getBytes()); + zos.closeEntry(); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + + byte[] body = baos.toByteArray(); + RequestBuilder request = post("/api/convert/merge/{inputFormat}:{outputFormat}", "CellDesigner_SBML", + "CellDesigner_SBML") + .header("post-filename", "maps.zip") + .content(body); + + byte[] content = mockMvc.perform(request) + .andDo(document("converter/merge_maps", + pathParameters( + parameterWithName("inputFormat") + .description("input format, available options: " + getModelInputConverters()), + parameterWithName("outputFormat") + .description("output format, available options: " + getModelOutputConverters())))) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsByteArray(); + + Model outputMap = parser.createModel(new ConverterParams().inputStream(new ByteArrayInputStream(content))); + + assertEquals(1, outputMap.getLayers().size()); + assertEquals(1, outputMap.getLayers().iterator().next().getTexts().size()); + + } + } diff --git a/web/src/test/java/lcsb/mapviewer/web/EndPointsInputValidationTests.java b/web/src/test/java/lcsb/mapviewer/web/EndPointsInputValidationTests.java index 984d0be04199d94527772cd05f9143fa79e6c0cd..8841c35648e60602da1304f4a7a178c8dbf8ebc2 100644 --- a/web/src/test/java/lcsb/mapviewer/web/EndPointsInputValidationTests.java +++ b/web/src/test/java/lcsb/mapviewer/web/EndPointsInputValidationTests.java @@ -43,7 +43,7 @@ public class EndPointsInputValidationTests extends ControllerIntegrationTest { private static String[] testValues = { " ", "-1", "0", "empty", "admin", "1.00,2.00", "17.00", "1" }; private static List<HttpStatus> validResponses = Arrays.asList(HttpStatus.OK, HttpStatus.BAD_REQUEST, - HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN, HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS); + HttpStatus.NOT_FOUND, HttpStatus.FORBIDDEN, HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS, HttpStatus.UNSUPPORTED_MEDIA_TYPE); @Autowired private RequestMappingHandlerMapping requestMappingHandlerMapping; diff --git a/web/src/test/java/lcsb/mapviewer/web/FileControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/FileControllerIntegrationTest.java index b139f65f101f4fc47f317fc078c8ab9bc22c87cf..fd8e1413177da84c515d7f0873db1ac123b611a2 100644 --- a/web/src/test/java/lcsb/mapviewer/web/FileControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/FileControllerIntegrationTest.java @@ -83,12 +83,11 @@ public class FileControllerIntegrationTest extends ControllerIntegrationTest { .get("id") .getAsString(); - body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - - new BasicNameValuePair("data", "test_content")))); + body = "test_content\nhello world"; request = post("/api/files/{fileId}:uploadContent", fileId) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE) + .header("post-filename", "input_file.txt") .content(body) .session(session); @@ -96,13 +95,13 @@ public class FileControllerIntegrationTest extends ControllerIntegrationTest { .andDo(document("file/upload_content", pathParameters(parameterWithName("fileId") .description("file id")), - requestParameters( - parameterWithName("data") - .description("content to append")), + requestParameters(), responseFields(fileResponseFields()))) .andExpect(status().is2xxSuccessful()); - assertNotNull(fileService.getById(Integer.valueOf(fileId))); + UploadedFileEntry file = fileService.getById(Integer.valueOf(fileId)); + assertNotNull(file); + assertEquals(body, new String(file.getFileContent())); } @Test diff --git a/web/src/test/java/lcsb/mapviewer/web/GenomicsControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/GenomicsControllerIntegrationTest.java index 43717a34696934599e98e81e7075d60dff0198ad..5d985272ab110d6f585e5538e513ad46ed0780e6 100644 --- a/web/src/test/java/lcsb/mapviewer/web/GenomicsControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/GenomicsControllerIntegrationTest.java @@ -75,7 +75,8 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest @After public void tearDown() throws Exception { referenceGenomeConnector.waitForDownloadsToFinish(); - ReferenceGenome referenceGenome = referenceGenomeService.getReferenceGenomeViewByParams(ebolaId, ReferenceGenomeType.UCSC, "eboVir3"); + ReferenceGenome referenceGenome = referenceGenomeService.getReferenceGenomeViewByParams(ebolaId, + ReferenceGenomeType.UCSC, "eboVir3"); if (referenceGenome != null) { referenceGenomeService.removeGenome(referenceGenome); } @@ -212,7 +213,8 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest .andDo(document("genomics/download_genome", requestParameters( parameterWithName("organismId").description("organism taxonomy id"), - parameterWithName("type").description("genome type, acceptable values: " + snippets.getOptionsAsString(ReferenceGenomeType.class)), + parameterWithName("type").description( + "genome type, acceptable values: " + snippets.getOptionsAsString(ReferenceGenomeType.class)), parameterWithName("version").description("genome version"), parameterWithName("url").description("url address from where the file should be downloaded")), responseFields())) @@ -243,7 +245,7 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest genome.setType(ReferenceGenomeType.UCSC); genome.setVersion("eboVir3"); ReferenceGenomeGeneMapping mapping = new ReferenceGenomeGeneMapping(); - mapping.setName("xy"); + mapping.setName("custom-gene-mapping"); mapping.setSourceUrl("https://minerva-dev.lcsb.uni.lu/tmp/refGene.bb"); genome.addReferenceGenomeGeneMapping(mapping); @@ -307,7 +309,8 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest .description("download progress") .type(JsonFieldType.NUMBER), fieldWithPath("geneMapping[].idObject") - .ignored(), + .description("id of the gene mapping") + .type(JsonFieldType.NUMBER), fieldWithPath("idObject") .description("unique id of genome in minerva") .type(JsonFieldType.NUMBER), @@ -352,7 +355,8 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest mockMvc.perform(request) .andDo(document("genomics/delete_genome_information", pathParameters( - parameterWithName("genomeId").description("genome id")), + parameterWithName("genomeId") + .description("genome id (genomeId is retrieved as idObject described above in 6.3)")), responseFields())) .andExpect(status().is2xxSuccessful()); @@ -398,7 +402,7 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest mockMvc.perform(request) .andDo(document("genomics/add_gene_mapping", pathParameters( - parameterWithName("genomeId").description("genome id")), + parameterWithName("genomeId").description("genome id (genomeId is retrieved as idObject described above in 6.3)")), requestParameters(parameterWithName("name").description("name of the gene-genome mapping"), parameterWithName("url").description("url where file with mapping is located")), responseFields())) @@ -425,8 +429,10 @@ public class GenomicsControllerIntegrationTest extends ControllerIntegrationTest mockMvc.perform(request) .andDo(document("genomics/delete_gene_mapping", pathParameters( - parameterWithName("genomeId").description("genome id"), - parameterWithName("geneMappingId").description("gene genome mapping id")))) + parameterWithName("genomeId") + .description("genome id (genomeId is retrieved as idObject described above in 6.3)"), + parameterWithName("geneMappingId") + .description("gene genome mapping id (geneMapping[].objectId described in 6.3)")))) .andExpect(status().is2xxSuccessful()); } diff --git a/web/src/test/java/lcsb/mapviewer/web/MapControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/MapControllerIntegrationTest.java index a6badf6ddfb46196510448c7aa38b164bf80e572..998f231085c328b53b77ca4b6358f50359313ed4 100644 --- a/web/src/test/java/lcsb/mapviewer/web/MapControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/MapControllerIntegrationTest.java @@ -218,7 +218,7 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { .type("int") .optional(), subsectionWithPath("[].other") - .description("list of oher properties") + .description("list of other properties") .type("object") .optional()); } @@ -282,7 +282,7 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { .type(JsonFieldType.OBJECT) .optional(), subsectionWithPath("[].other") - .description("list of oher properties") + .description("list of other properties") .type(JsonFieldType.OBJECT) .optional())); fields.addAll(reactionNodeFields("[].reactants[]")); @@ -636,7 +636,7 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { mapPathParameters(), responseFields( fieldWithPath("[]") - .description("list of all full search queries that could be used for quering the map") + .description("list of all full search queries that could be used for querying the map") .type("array<string>")))) .andExpect(status().is2xxSuccessful()); } @@ -655,7 +655,7 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { .type("number"), fieldWithPath("defaultZoomLevel").description("default zoom level used in frontend visualization") .type("number"), - fieldWithPath("minZoom").description("minimum zoom level availbale for the map").type("number"), + fieldWithPath("minZoom").description("minimum zoom level available for the map").type("number"), fieldWithPath("maxZoom").description("maximum zoom level available for the map").type("number"), fieldWithPath("authors").description("list of authors").type("array<Author>"), fieldWithPath("references").description("list of references").type("array<Reference>"), @@ -856,6 +856,25 @@ public class MapControllerIntegrationTest extends ControllerIntegrationTest { .andExpect(status().is2xxSuccessful()); } + @Test + public void testDownloadModelWithOverlay() throws Exception { + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + ModelData submap = getSubmap(); + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); + DataOverlay overlay = createOverlay(project, admin, "name\tvalue\nGSTA4\t1"); + + RequestBuilder request = get("/api/projects/{projectId}/models/{mapId}:downloadModel?" + + "handlerClass={handlerClass}" + + "&overlayIds={overlayId}", TEST_PROJECT, submap.getId(), + CellDesignerXmlParser.class.getCanonicalName(), + overlay.getId()) + .session(session); + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()); + } + @Test public void testDownloadSubmapModelWithPost() throws Exception { ModelData submap = getSubmap(); diff --git a/web/src/test/java/lcsb/mapviewer/web/MiRnaControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/MiRnaControllerIntegrationTest.java index fd595ba6dd62f5c3b742524407831e74888b33f9..18eed126aa33a26842516925e1325146926d57e0 100644 --- a/web/src/test/java/lcsb/mapviewer/web/MiRnaControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/MiRnaControllerIntegrationTest.java @@ -18,7 +18,6 @@ import org.springframework.test.web.servlet.RequestBuilder; @RunWith(SpringJUnit4ClassRunner.class) public class MiRnaControllerIntegrationTest extends ControllerIntegrationTest { - @Before public void setup() { } @@ -72,7 +71,7 @@ public class MiRnaControllerIntegrationTest extends ControllerIntegrationTest { getProjectPathParameters(), responseFields( fieldWithPath("[]") - .description("list of suggested mirna queries") + .description("list of suggested miRNA queries") .type("array<string>")))) .andExpect(status().is2xxSuccessful()) .andReturn().getResponse().getContentAsString(); @@ -92,7 +91,7 @@ public class MiRnaControllerIntegrationTest extends ControllerIntegrationTest { private ResponseFieldsSnippet listOfMiRnaFields() { return responseFields( subsectionWithPath("[].id") - .description("identifier of the mirna") + .description("identifier of the miRNA") .type("object"), fieldWithPath("[].name") .description("name") diff --git a/web/src/test/java/lcsb/mapviewer/web/NumericDirectoryNameGeneratorConfiguration.java b/web/src/test/java/lcsb/mapviewer/web/NumericDirectoryNameGeneratorConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..f4894f40e1c52c9dac01be122eae7b54dc8aa528 --- /dev/null +++ b/web/src/test/java/lcsb/mapviewer/web/NumericDirectoryNameGeneratorConfiguration.java @@ -0,0 +1,34 @@ +package lcsb.mapviewer.web; + +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.context.annotation.Profile; + +import lcsb.mapviewer.api.projects.IDirectoryNameGenerator; +import lcsb.mapviewer.common.Md5; +import lcsb.mapviewer.services.interfaces.IProjectService; + +@Profile("NumericDirectoryNameGeneratorProfile") +@Configuration +public class NumericDirectoryNameGeneratorConfiguration { + + @Autowired + private IProjectService projectService; + + @Bean + @Primary + public IDirectoryNameGenerator directoryNameGenerator() throws Exception { + IDirectoryNameGenerator mock = Mockito.mock(IDirectoryNameGenerator.class); + + Mockito.when(mock.projectIdToDirectoryName(Mockito.anyString())).thenAnswer(projectId -> { + long id = projectService.getNextId(); + return Md5.compute(projectId + "-" + id).replaceAll("[a-z]", "0"); + }); + + return mock; + } + +} diff --git a/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java index 1ee23b297ffd747577db30fe3b22729f8e200237..e261c654fea3ece0f237683ec215caef4efa13b9 100644 --- a/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/OverlayControllerIntegrationTest.java @@ -437,6 +437,28 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest .andReturn().getResponse().getContentAsString(); } + @Test + public void testGetReactionForOverlayWithWidth() throws Exception { + String reactionId = reaction.getElementId(); + DataOverlay overlay = createOverlay(project, user, "element_identifier\tvalue\tline_width\n" + reactionId + "\t1\t6"); + + MockHttpSession session = createSession(TEST_USER_LOGIN, TEST_USER_PASSWORD); + + RequestBuilder request = get( + "/api/projects/{projectId}/overlays/{overlayId}/models/{mapId}/bioEntities/reactions/{reactionId}/", + TEST_PROJECT, overlay.getId(), map.getId(), reaction.getId()) + .session(session); + + String json = mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + List<Map<String, Object>> objects = objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() { + }); + Map<?, ?> content = (Map<?, ?>) objects.get(0).get("overlayContent"); + assertTrue(content.containsKey("width")); + + } + private PathParametersSnippet getOverlayReactionPathParameters() { return getOverlayMapPathParameters().and(parameterWithName("reactionId").description("reaction identifier")); } @@ -578,10 +600,11 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("content", "element_identifier\tvalue\n\t-1"), new BasicNameValuePair("name", "overlay name"), - new BasicNameValuePair("description", "overlay name"), - new BasicNameValuePair("filename", "overlay name"), + new BasicNameValuePair("description", "overlay description"), + new BasicNameValuePair("filename", "source.txt"), new BasicNameValuePair("googleLicenseConsent", "false"), new BasicNameValuePair("type", "GENERIC")))); + logger.debug(body); RequestBuilder request = post("/api/projects/{projectId}/overlays/", TEST_PROJECT) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -1333,7 +1356,7 @@ public class OverlayControllerIntegrationTest extends ControllerIntegrationTest .description("identifier") .type(JsonFieldType.NUMBER), fieldWithPath("publicOverlay") - .description("is the data overlay publicaly available to all users") + .description("is the data overlay publicly available to all users") .type(JsonFieldType.BOOLEAN), fieldWithPath("googleLicenseConsent") .description("did creator accepted license required by Google Maps API") diff --git a/web/src/test/java/lcsb/mapviewer/web/PluginControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/PluginControllerIntegrationTest.java index b1f45c22adc1a7c46d839d32416498fa5cdf1dbc..1f5352d5813971b05bea3183aab1ed13115d8907 100644 --- a/web/src/test/java/lcsb/mapviewer/web/PluginControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/PluginControllerIntegrationTest.java @@ -132,7 +132,7 @@ public class PluginControllerIntegrationTest extends ControllerIntegrationTest { .description("version"), parameterWithName("isDefault") .optional() - .description("should be opened automatically whem map is browsed"), + .description("should be opened automatically when map is browsed"), parameterWithName("isPublic") .description("should the plugin be visible by all users"), parameterWithName("url") @@ -171,7 +171,7 @@ public class PluginControllerIntegrationTest extends ControllerIntegrationTest { .description("md5 checksum of the source file") .type("string"), fieldWithPath("isDefault") - .description("should be opened automatically whem map is browsed") + .description("should be opened automatically when map is browsed") .type("boolean"), fieldWithPath("isPublic") .description("should be visible on plugin list to all users") @@ -325,6 +325,46 @@ public class PluginControllerIntegrationTest extends ControllerIntegrationTest { assertEquals("xxx", result); } + @Test + public void updateUserPluginData() throws Exception { + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_LOGIN); + + String body = "value=xxx"; + Plugin plugin = createPlugin(); + + RequestBuilder request = post("/api/plugins/{hash}/data/users/{key}/", plugin.getHash(), "my_key") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .session(session) + .content(body); + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()); + + body = "value=xxx2"; + request = post("/api/plugins/{hash}/data/users/{key}/", plugin.getHash(), "my_key") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .session(session) + .content(body); + + mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()); + + request = get("/api/plugins/{hash}/data/users/{key}/", plugin.getHash(), "my_key") + .session(session); + + String response = mockMvc.perform(request) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + String result = new JsonParser() + .parse(response) + .getAsJsonObject() + .get("value") + .getAsString(); + + assertEquals("xxx2", result); + } + @Test public void removeGlobalPluginData() throws Exception { Plugin plugin = createPlugin(); diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationForDocsTest.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationForDocsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..ac5f1eeccedcb7efa59ca1776c7849e22e870922 --- /dev/null +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationForDocsTest.java @@ -0,0 +1,262 @@ +package lcsb.mapviewer.web; + +import static org.junit.Assert.assertEquals; +import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; +import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; +import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.restdocs.request.ParameterDescriptor; +import org.springframework.restdocs.request.RequestParametersSnippet; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.web.servlet.RequestBuilder; + +import lcsb.mapviewer.converter.zip.ZipEntryFileDeserializer; +import lcsb.mapviewer.model.Project; +import lcsb.mapviewer.model.ProjectStatus; +import lcsb.mapviewer.model.cache.UploadedFileEntry; +import lcsb.mapviewer.model.graphics.MapCanvasType; +import lcsb.mapviewer.model.map.model.SubmodelType; +import lcsb.mapviewer.model.user.ConfigurationElementType; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.services.interfaces.IConfigurationService; +import lcsb.mapviewer.services.interfaces.IProjectService; +import lcsb.mapviewer.services.interfaces.IUserService; + +@RunWith(SpringJUnit4ClassRunner.class) +@ActiveProfiles("NumericDirectoryNameGeneratorProfile") +public class ProjectControllerIntegrationForDocsTest extends ControllerIntegrationTest { + + private static final String CURATOR_PASSWORD = "curator_pass"; + private static final String CURATOR_LOGIN = "curator_user"; + + @Autowired + private IUserService userService; + + @Autowired + private IProjectService projectService; + + @Autowired + private ProjectSnippets snippets; + + private User curator; + + @Autowired + private IConfigurationService configurationService; + + @Before + public void setup() { + curator = createCurator(CURATOR_LOGIN, CURATOR_PASSWORD); + configurationService.setConfigurationValue(ConfigurationElementType.MINERVA_ROOT, "https://pdmap.uni.lu/minerva/"); + } + + @After + public void tearDown() throws Exception { + removeProject(TEST_PROJECT); + removeUser(curator); + configurationService.setConfigurationValue(ConfigurationElementType.MINERVA_ROOT, ""); + } + + @Test + public void addComplexProjectAsCurator() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); + try { + UploadedFileEntry fileEntry = createFile( + Files.readAllBytes(Paths.get("./src/test/resources/complex_model_with_submaps.zip")), admin); + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("projectId", TEST_PROJECT), + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("name", "Project name"), + new BasicNameValuePair("version", "0.0.1"), + new BasicNameValuePair("notify-email", "minerva@uni.lu"), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("parser", + "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"), + + new BasicNameValuePair("zip-entries[0][_type]", "MAP"), + new BasicNameValuePair("zip-entries[0][_filename]", "main.xml"), + new BasicNameValuePair("zip-entries[0][_data][root]", "true"), + new BasicNameValuePair("zip-entries[0][_data][name]", "main"), + new BasicNameValuePair("zip-entries[0][_data][type][id]", "UNKNOWN"), + + new BasicNameValuePair("zip-entries[1][_type]", "MAP"), + new BasicNameValuePair("zip-entries[1][_filename]", "submaps/mapping.xml"), + new BasicNameValuePair("zip-entries[1][_data][root]", "false"), + new BasicNameValuePair("zip-entries[1][_data][name]", "mapping"), + new BasicNameValuePair("zip-entries[1][_data][type][id]", "UNKNOWN"), + + new BasicNameValuePair("zip-entries[2][_type]", "MAP"), + new BasicNameValuePair("zip-entries[2][_filename]", "submaps/s1.xml"), + new BasicNameValuePair("zip-entries[2][_data][root]", "false"), + new BasicNameValuePair("zip-entries[2][_data][name]", "s1"), + new BasicNameValuePair("zip-entries[2][_data][type][id]", "UNKNOWN"), + + new BasicNameValuePair("zip-entries[3][_type]", "MAP"), + new BasicNameValuePair("zip-entries[3][_filename]", "submaps/s2.xml"), + new BasicNameValuePair("zip-entries[3][_data][root]", "false"), + new BasicNameValuePair("zip-entries[3][_data][name]", "s2"), + new BasicNameValuePair("zip-entries[3][_data][type][id]", "UNKNOWN"), + + new BasicNameValuePair("zip-entries[4][_type]", "MAP"), + new BasicNameValuePair("zip-entries[4][_filename]", "submaps/s3.xml"), + new BasicNameValuePair("zip-entries[4][_data][root]", "false"), + new BasicNameValuePair("zip-entries[4][_data][name]", "s3"), + new BasicNameValuePair("zip-entries[4][_data][type][id]", "UNKNOWN") + + ))); + + RequestBuilder request = post("/api/projects/{projectId}/", TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().is2xxSuccessful()) + .andDo(document("projects/project_data/create_zip", + projectPathParameters(), + createProjectRequestSnippet(), + + snippets.getProjectSnippet())); + + } finally { + waitForProjectToFinishLoading(TEST_PROJECT); + Project project = projectService.getProjectByProjectId(TEST_PROJECT); + assertEquals(ProjectStatus.DONE, project.getStatus()); + } + } + + @Test + public void addProjectAsCurator() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); + try { + UploadedFileEntry fileEntry = createFile( + new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), + admin); + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("projectId", TEST_PROJECT), + new BasicNameValuePair("name", "New Disease Map"), + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("cache", "false"), + new BasicNameValuePair("description", "this is my awesome project"), + new BasicNameValuePair("notify-email", "notify.me@uni.lu"), + new BasicNameValuePair("disease", "D010300"), + new BasicNameValuePair("organism", "9606"), + new BasicNameValuePair("sbgn", "false"), + new BasicNameValuePair("version", "0.0.1"), + new BasicNameValuePair("annotate", "false"), + new BasicNameValuePair("verify-annotations", "false"), + new BasicNameValuePair("parser", "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); + + RequestBuilder request = post("/api/projects/{projectId}/", TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); + + mockMvc.perform(request).andExpect(status().is2xxSuccessful()) + .andDo(document("projects/project_data/create_simple", + projectPathParameters(), + createProjectRequestSnippet(), + snippets.getProjectSnippet())); + + } finally { + waitForProjectToFinishLoading(TEST_PROJECT); + } + } + + private RequestParametersSnippet createProjectRequestSnippet() { + return requestParameters( + parameterWithName("projectId") + .description("project identifier"), + parameterWithName("file-id") + .description("identifier of the file that should be used to create project"), + parameterWithName("parser") + .description("class of the parser that should be used for parsing the file. Available options: " + + snippets.getParsers()), + parameterWithName("cache") + .description("should the data from external sources be cached after project was created") + .optional(), + parameterWithName("description") + .description("description of the project") + .optional(), + parameterWithName("notify-email") + .description("email address that should be when something change in the project") + .optional(), + parameterWithName("disease") + .description("disease associated with the project (final MESH id)") + .optional(), + parameterWithName("name") + .description("name of the project") + .optional(), + parameterWithName("organism") + .description("organism associated with the project (final TAXONOMY id)") + .optional(), + parameterWithName("sbgn") + .description("should the map be visualized in sbgn-like way") + .optional(), + parameterWithName("semantic-zooming-contains-multiple-overlays") + .description("display each semantic zoom level in separate overlay") + .optional(), + parameterWithName("version") + .description("version of the project") + .optional(), + parameterWithName("mapCanvasType") + .description("type of map canvas engine to be used when visualizing map. Available options: " + + snippets.getOptionsAsString(MapCanvasType.class)) + .optional(), + parameterWithName("annotate") + .description("should the project be automatically annotated") + .optional(), + parameterWithName("verify-annotations") + .description("should the annotations be verified") + .optional(), + parameterWithName("zip-entries") + .description( + "array of parameters describing each file in the zipped input file, file-index is number starting from 0") + .optional() + + ) + .and(createArrayParameters("zip-entries[{number}][_filename]", "name of the file")) + .and(createArrayParameters("zip-entries[{number}][_type]", + "type of the file. Possible values: " + + snippets.getOptionsAsString(ZipEntryFileDeserializer.ZipEntryFileType.class))) + .and(createArrayParameters("zip-entries[{number}][_data][name]", "name of the map/name of the overlay")) + .and(createArrayParameters("zip-entries[{number}][_data][mapping]", + "for submaps - is this map a mapping file (true/false)")) + .and(createArrayParameters("zip-entries[{number}][_data][root]", + "for submaps - is this map a root map (true/false)")) + .and(createArrayParameters("zip-entries[{number}][_data][type][id]", + "for submaps defines type of the connection. Possible values: " + + snippets.getOptionsAsString(SubmodelType.class))) + .and(createArrayParameters("zip-entries[{number}][_data][description]", + "for overlays - description of the overlay")); + } + + private List<ParameterDescriptor> createArrayParameters(final String name, final String description) { + List<ParameterDescriptor> result = new ArrayList<>(); + result.add(parameterWithName(name).description(description).optional()); + for (int i = 0; i < 10; i++) { + result.add(parameterWithName(name.replace("{number}", i + "")).description(description).optional().ignored()); + } + return result; + } + +} diff --git a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java index 05f0ec5ac43031ac89950ed861cc0504258f7d0f..8d65f84bbb5314b557a0a9e6f00188ca66b9b5ab 100644 --- a/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/ProjectControllerIntegrationTest.java @@ -2,6 +2,7 @@ package lcsb.mapviewer.web; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; @@ -14,16 +15,17 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.requestF import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.payload.PayloadDocumentation.subsectionWithPath; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; -import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.nio.file.Paths; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.message.BasicNameValuePair; @@ -37,9 +39,7 @@ import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpSession; import org.springframework.restdocs.payload.FieldDescriptor; import org.springframework.restdocs.payload.JsonFieldType; -import org.springframework.restdocs.request.ParameterDescriptor; import org.springframework.restdocs.request.PathParametersSnippet; -import org.springframework.restdocs.request.RequestParametersSnippet; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.servlet.RequestBuilder; @@ -47,7 +47,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.gson.JsonParser; -import lcsb.mapviewer.converter.zip.ZipEntryFileDeserializer; import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.ProjectStatus; import lcsb.mapviewer.model.cache.UploadedFileEntry; @@ -55,7 +54,6 @@ import lcsb.mapviewer.model.graphics.MapCanvasType; import lcsb.mapviewer.model.map.MiriamType; import lcsb.mapviewer.model.map.layout.ProjectBackground; import lcsb.mapviewer.model.map.layout.ProjectBackgroundStatus; -import lcsb.mapviewer.model.map.model.SubmodelType; import lcsb.mapviewer.model.security.Privilege; import lcsb.mapviewer.model.security.PrivilegeType; import lcsb.mapviewer.model.user.ConfigurationElementType; @@ -117,6 +115,11 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = get("/api/projects/") .session(session); + + Project project = projectService.getProjectByProjectId(BUILT_IN_PROJECT); + project.setDirectory(project.getDirectory().replaceAll("[a-z]", "0")); + projectService.updateProject(project); + String response = mockMvc.perform(request) .andExpect(status().is2xxSuccessful()) .andDo(document("projects/project_data/list", @@ -170,6 +173,29 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest assertEquals("curator should see only limited list of projects", 1, projects); } + @Test + public void testGetLimitedProjectsAsGuest() throws Exception { + Project project2 = new Project(TEST_PROJECT_2); + project2.setOwner(userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN)); + projectService.add(project2); + + RequestBuilder request = get("/api/projects/"); + + String response = mockMvc.perform(request) + .andDo(document("projects/project_data/list_guest", + responseFields( + subsectionWithPath("[]") + .description("list of projects").type(JsonFieldType.ARRAY)))) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + + int projects = new JsonParser() + .parse(response) + .getAsJsonArray().size(); + + assertEquals("guest should see only limited list of projects", 1, projects); + } + @Test public void testUserPrivilegesChangeDuringActiveSession() throws Exception { MockHttpSession session = createSession(CURATOR_LOGIN, CURATOR_PASSWORD); @@ -208,7 +234,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest .description("log entry column that should be used for sorting (default: id)").optional(), parameterWithName("sortOrder").description("log entry sort order (asc, desc)").optional(), parameterWithName("level").description("level of log entry (warning, error)").optional(), - parameterWithName("length").description("number of log entres we want to obtain").optional(), + parameterWithName("length").description("number of log entries we want to obtain").optional(), parameterWithName("search").description("search query used for filtering").optional()), projectPathParameters(), responseFields( @@ -576,232 +602,6 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest mockMvc.perform(request).andExpect(status().isBadRequest()); } - @Test - public void addProjectAsCurator() throws Exception { - User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); - try { - UploadedFileEntry fileEntry = createFile( - new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), - admin); - - String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("projectId", TEST_PROJECT), - new BasicNameValuePair("name", "New Disease Map"), - new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), - new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), - new BasicNameValuePair("cache", "false"), - new BasicNameValuePair("description", "this is my awesome project"), - new BasicNameValuePair("notify-email", "notify.me@uni.lu"), - new BasicNameValuePair("disease", "D010300"), - new BasicNameValuePair("organism", "9606"), - new BasicNameValuePair("sbgn", "false"), - new BasicNameValuePair("version", "0.0.1"), - new BasicNameValuePair("annotate", "false"), - new BasicNameValuePair("verify-annotations", "false"), - new BasicNameValuePair("parser", "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); - - RequestBuilder request = post("/api/projects/{projectId}/", TEST_PROJECT) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .content(body) - .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); - - mockMvc.perform(request).andExpect(status().is2xxSuccessful()) - .andDo(document("projects/project_data/create_simple", - projectPathParameters(), - createProjectRequestSnippet(), - snippets.getProjectSnippet())); - - } finally { - waitForProjectToFinishLoading(TEST_PROJECT); - } - } - - @Test - public void addProjectWithEmptyZipEntries() throws Exception { - User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); - try { - UploadedFileEntry fileEntry = createFile( - new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), - admin); - - String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("projectId", TEST_PROJECT), - new BasicNameValuePair("name", "New Disease Map"), - new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), - new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), - new BasicNameValuePair("cache", "false"), - new BasicNameValuePair("description", "this is my awesome project"), - new BasicNameValuePair("notify-email", "notify.me@uni.lu"), - new BasicNameValuePair("disease", "D010300"), - new BasicNameValuePair("organism", "9606"), - new BasicNameValuePair("sbgn", "false"), - new BasicNameValuePair("version", "0.0.1"), - new BasicNameValuePair("annotate", "false"), - new BasicNameValuePair("verify-annotations", "false"), - new BasicNameValuePair("zip-entries", ""), - new BasicNameValuePair("parser", "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); - - RequestBuilder request = post("/api/projects/{projectId}/", TEST_PROJECT) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .content(body) - .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); - - mockMvc.perform(request).andExpect(status().is2xxSuccessful()) - .andDo(document("projects/project_data/create_simple", - projectPathParameters(), - createProjectRequestSnippet(), - snippets.getProjectSnippet())); - - } finally { - waitForProjectToFinishLoading(TEST_PROJECT); - } - } - - @Test - public void addComplexProjectAsCurator() throws Exception { - User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); - try { - UploadedFileEntry fileEntry = createFile( - Files.readAllBytes(Paths.get("./src/test/resources/complex_model_with_submaps.zip")), admin); - - String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("projectId", TEST_PROJECT), - new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), - new BasicNameValuePair("name", "Project name"), - new BasicNameValuePair("version", "0.0.1"), - new BasicNameValuePair("notify-email", "minerva@uni.lu"), - new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), - new BasicNameValuePair("parser", - "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"), - - new BasicNameValuePair("zip-entries[0][_type]", "MAP"), - new BasicNameValuePair("zip-entries[0][_filename]", "main.xml"), - new BasicNameValuePair("zip-entries[0][_data][root]", "true"), - new BasicNameValuePair("zip-entries[0][_data][name]", "main"), - new BasicNameValuePair("zip-entries[0][_data][type][id]", "UNKNOWN"), - - new BasicNameValuePair("zip-entries[1][_type]", "MAP"), - new BasicNameValuePair("zip-entries[1][_filename]", "submaps/mapping.xml"), - new BasicNameValuePair("zip-entries[1][_data][root]", "false"), - new BasicNameValuePair("zip-entries[1][_data][name]", "mapping"), - new BasicNameValuePair("zip-entries[1][_data][type][id]", "UNKNOWN"), - - new BasicNameValuePair("zip-entries[2][_type]", "MAP"), - new BasicNameValuePair("zip-entries[2][_filename]", "submaps/s1.xml"), - new BasicNameValuePair("zip-entries[2][_data][root]", "false"), - new BasicNameValuePair("zip-entries[2][_data][name]", "s1"), - new BasicNameValuePair("zip-entries[2][_data][type][id]", "UNKNOWN"), - - new BasicNameValuePair("zip-entries[3][_type]", "MAP"), - new BasicNameValuePair("zip-entries[3][_filename]", "submaps/s2.xml"), - new BasicNameValuePair("zip-entries[3][_data][root]", "false"), - new BasicNameValuePair("zip-entries[3][_data][name]", "s2"), - new BasicNameValuePair("zip-entries[3][_data][type][id]", "UNKNOWN"), - - new BasicNameValuePair("zip-entries[4][_type]", "MAP"), - new BasicNameValuePair("zip-entries[4][_filename]", "submaps/s3.xml"), - new BasicNameValuePair("zip-entries[4][_data][root]", "false"), - new BasicNameValuePair("zip-entries[4][_data][name]", "s3"), - new BasicNameValuePair("zip-entries[4][_data][type][id]", "UNKNOWN") - - ))); - - RequestBuilder request = post("/api/projects/{projectId}/", TEST_PROJECT) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .content(body) - .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); - - mockMvc.perform(request).andExpect(status().is2xxSuccessful()) - .andDo(document("projects/project_data/create_zip", - projectPathParameters(), - createProjectRequestSnippet(), - - snippets.getProjectSnippet())); - - } finally { - waitForProjectToFinishLoading(TEST_PROJECT); - Project project = projectService.getProjectByProjectId(TEST_PROJECT); - assertEquals(ProjectStatus.DONE, project.getStatus()); - } - } - - private RequestParametersSnippet createProjectRequestSnippet() { - return requestParameters( - parameterWithName("projectId") - .description("project identifier"), - parameterWithName("file-id") - .description("identifier of the file that should be used to create project"), - parameterWithName("parser") - .description("class of the parser that should be used for parsing the file. Available options: " - + snippets.getParsers()), - parameterWithName("cache") - .description("should the data from external sources be cached after project was created") - .optional(), - parameterWithName("description") - .description("description of the project") - .optional(), - parameterWithName("notify-email") - .description("email address that should be when something change in the project") - .optional(), - parameterWithName("disease") - .description("disease associated with the project (final MESH id)") - .optional(), - parameterWithName("name") - .description("name of the project") - .optional(), - parameterWithName("organism") - .description("organism associated with the project (final TAXONOMY id)") - .optional(), - parameterWithName("sbgn") - .description("should the map be visualized in sbgn-like way") - .optional(), - parameterWithName("semantic-zoom") - .description("should custom semantic zooming be enabled") - .optional(), - parameterWithName("version") - .description("version of the project") - .optional(), - parameterWithName("mapCanvasType") - .description("type of map canvas engine to be used when visualizing map. Available options: " - + snippets.getOptionsAsString(MapCanvasType.class)) - .optional(), - parameterWithName("annotate") - .description("should the project be automatically annotated") - .optional(), - parameterWithName("verify-annotations") - .description("should the annotations be verified") - .optional(), - parameterWithName("zip-entries") - .description( - "array of parameters describing each file in the zipped input file, file-index is number starting from 0") - .optional() - - ) - .and(createArrayParameters("zip-entries[{number}][_filename]", "name of the file")) - .and(createArrayParameters("zip-entries[{number}][_type]", - "type of the file. Possible values: " - + snippets.getOptionsAsString(ZipEntryFileDeserializer.ZipEntryFileType.class))) - .and(createArrayParameters("zip-entries[{number}][_data][name]", "name of the map/name of the overlay")) - .and(createArrayParameters("zip-entries[{number}][_data][mapping]", - "for submaps - is this map a mapping file (true/false)")) - .and(createArrayParameters("zip-entries[{number}][_data][root]", - "for submaps - is this map a root map (true/false)")) - .and(createArrayParameters("zip-entries[{number}][_data][type][id]", - "for submaps defines type of the connection. Possible values: " - + snippets.getOptionsAsString(SubmodelType.class))) - .and(createArrayParameters("zip-entries[{number}][_data][description]", - "for overlays - description of the overlay")); - } - - private List<ParameterDescriptor> createArrayParameters(final String name, final String description) { - List<ParameterDescriptor> result = new ArrayList<>(); - result.add(parameterWithName(name).description(description).optional()); - for (int i = 0; i < 10; i++) { - result.add(parameterWithName(name.replace("{number}", i + "")).description(description).optional().ignored()); - } - return result; - } - @Test public void addInvalidProject() throws Exception { User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); @@ -899,34 +699,9 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest public void removeProjectWithUsedFile() throws Exception { User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); try { - UploadedFileEntry fileEntry = createFile( - new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), - admin); - - String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), - new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), - new BasicNameValuePair("name", "Project name"), - new BasicNameValuePair("version", "0.0.1"), - new BasicNameValuePair("notify-email", "minerva@uni.lu"), - new BasicNameValuePair("parser", - "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); + createFullProject(admin); - RequestBuilder request = post("/api/projects/" + TEST_PROJECT) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .content(body) - .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); - mockMvc.perform(request).andExpect(status().is2xxSuccessful()); - - request = post("/api/projects/" + TEST_PROJECT_2) - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .content(body) - .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); - mockMvc.perform(request).andExpect(status().is2xxSuccessful()); - - waitForProjectToFinishLoading(TEST_PROJECT_2); - - request = delete("/api/projects/{projectId}/", TEST_PROJECT_2) + RequestBuilder request = delete("/api/projects/{projectId}/", TEST_PROJECT_2) .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); mockMvc.perform(request).andExpect(status().is2xxSuccessful()) @@ -939,6 +714,40 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest } } + private void createFullProject(final User admin) + throws UnsupportedEncodingException, IOException, Exception, InterruptedException { + UploadedFileEntry fileEntry = createFile( + new String(Files.readAllBytes(Paths.get("./src/test/resources/generic.xml")), "UTF-8"), + admin); + + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("name", "Project name"), + new BasicNameValuePair("version", "0.0.1"), + new BasicNameValuePair("notify-email", "minerva@uni.lu"), + new BasicNameValuePair("parser", + "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser")))); + + RequestBuilder request = post("/api/projects/" + TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); + mockMvc.perform(request).andExpect(status().is2xxSuccessful()); + + request = post("/api/projects/" + TEST_PROJECT_2) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD)); + mockMvc.perform(request).andExpect(status().is2xxSuccessful()); + + waitForProjectToFinishLoading(TEST_PROJECT_2); + + Project project = projectService.getProjectByProjectId(TEST_PROJECT_2); + project.setDirectory(project.getDirectory().replaceAll("[a-z]", "0")); + projectService.updateProject(project); + } + @Test public void addComplexProjectWithInvalidOverlayName() throws Exception { User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); @@ -1062,6 +871,29 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest responseFields().andWithPrefix("[].", getBackgroundFields()))); } + private List<FieldDescriptor> getUpdateBackgroundFields() { + return Arrays.asList( + fieldWithPath("id") + .type(JsonFieldType.NUMBER) + .description("identifier"), + fieldWithPath("name") + .type(JsonFieldType.STRING) + .description("name"), + fieldWithPath("description") + .type(JsonFieldType.STRING) + .description("description"), + fieldWithPath("creator") + .type(JsonFieldType.STRING) + .description("who created background"), + fieldWithPath("order") + .type(JsonFieldType.NUMBER) + .description("order used when listing all backgrounds"), + fieldWithPath("defaultOverlay") + .type(JsonFieldType.BOOLEAN) + .description( + "should the background be used as default (at most one per project should be marked with true)")); + } + private List<FieldDescriptor> getBackgroundFields() { return Arrays.asList( fieldWithPath("id") @@ -1128,6 +960,8 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest Project project = createAndPersistProject(TEST_PROJECT); ProjectBackground background = new ProjectBackground("weird_title"); background.setId(project.getProjectBackgrounds().get(0).getId()); + background.setCreator(userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN)); + background.setDescription("new description"); ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(ProjectBackground.class, ProjectBackgroundUpdateMixIn.class); @@ -1142,6 +976,7 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest .andExpect(status().is2xxSuccessful()) .andDo(document("projects/project_backgrounds/update_background", backgroundPathParameters(), + requestFields(getUpdateBackgroundFields()), responseFields(getBackgroundFields()))) .andReturn().getResponse().getContentAsString(); @@ -1194,10 +1029,6 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest assertEquals(backgrounds.size() - 1, backgroundCount); } - private PathParametersSnippet projectPathParameters() { - return pathParameters(parameterWithName("projectId").description("project identifier")); - } - private PathParametersSnippet backgroundPathParameters() { return projectPathParameters().and(parameterWithName("backgroundId").description("background identifier")); } @@ -1446,4 +1277,56 @@ public class ProjectControllerIntegrationTest extends ControllerIntegrationTest .andExpect(status().is2xxSuccessful()); } + @Test + public void addComplexProjectWithGenomicLayout() throws Exception { + User admin = userService.getUserByLogin(BUILT_IN_TEST_ADMIN_LOGIN); + MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); + + UploadedFileEntry fileEntry = createFile( + Files.readAllBytes(Paths.get("./src/test/resources/complex_model_with_genomic_layout.zip")), admin); + try { + String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( + new BasicNameValuePair("file-id", String.valueOf(fileEntry.getId())), + new BasicNameValuePair("mapCanvasType", "OPEN_LAYERS"), + new BasicNameValuePair("parser", "lcsb.mapviewer.converter.model.celldesigner.CellDesignerXmlParser"), + + new BasicNameValuePair("zip-entries[0][_type]", "MAP"), + new BasicNameValuePair("zip-entries[0][_filename]", "main.xml"), + new BasicNameValuePair("zip-entries[0][_data][root]", "true"), + new BasicNameValuePair("zip-entries[0][_data][name]", "s1"), + new BasicNameValuePair("zip-entries[0][_data][type][id]", "UNKNOWN"), + new BasicNameValuePair("zip-entries[0][_data][type][name]", "Unknown"), + + new BasicNameValuePair("zip-entries[1][_type]", "OVERLAY"), + new BasicNameValuePair("zip-entries[1][_filename]", "layouts/goodSchema.txt"), + new BasicNameValuePair("zip-entries[1][_data][name]", "test-o") + + ))); + + RequestBuilder request = post("/api/projects/" + TEST_PROJECT) + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .content(body) + .session(session); + + mockMvc.perform(request).andExpect(status().is2xxSuccessful()); + waitForProjectToFinishLoading(TEST_PROJECT); + + RequestBuilder overlayRequest = get("/api/projects/{projectId}/overlays/", TEST_PROJECT) + .session(session); + + String json = mockMvc.perform(overlayRequest) + .andExpect(status().is2xxSuccessful()) + .andReturn().getResponse().getContentAsString(); + List<Map<String, Object>> overlays = objectMapper.readValue(json, new TypeReference<List<Map<String, Object>>>() { + }); + + logger.debug(json); + + assertNotNull(overlays.get(0).get("genomeType")); + assertNotNull(overlays.get(0).get("genomeVersion")); + } finally { + waitForProjectToFinishLoading(TEST_PROJECT); + } + } + } diff --git a/web/src/test/java/lcsb/mapviewer/web/UserControllerAnonymousIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/UserControllerAnonymousIntegrationTest.java index 2a18af22f3d8b678310c1f44ff1359d54ef846a0..26e391ceb1985edb6b4e40ba4c2b9f38f7d0987e 100644 --- a/web/src/test/java/lcsb/mapviewer/web/UserControllerAnonymousIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/UserControllerAnonymousIntegrationTest.java @@ -15,6 +15,8 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import java.util.Map; +import javax.servlet.http.Cookie; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -36,7 +38,6 @@ public class UserControllerAnonymousIntegrationTest extends ControllerIntegratio @Autowired private IUserService userService; - @Before public void setup() { } @@ -153,13 +154,13 @@ public class UserControllerAnonymousIntegrationTest extends ControllerIntegratio MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); RequestBuilder request = post("/api/doLogout") + .contentType(MediaType.APPLICATION_FORM_URLENCODED) + .cookie(new Cookie(Configuration.AUTH_TOKEN, "xxxxxxxx")) .session(session); mockMvc.perform(request) .andDo(document("authentication/logout", - responseFields( - fieldWithPath("status") - .description("status message")))) + responseFields(fieldWithPath("status").description("status message")))) .andExpect(status().is2xxSuccessful()); } @@ -173,7 +174,6 @@ public class UserControllerAnonymousIntegrationTest extends ControllerIntegratio Map<String, Object> result = objectMapper.readValue(content, new TypeReference<Map<String, Object>>() { }); - logger.debug(result); assertNotNull(result.get("preferences")); } diff --git a/web/src/test/java/lcsb/mapviewer/web/UserControllerIntegrationTest.java b/web/src/test/java/lcsb/mapviewer/web/UserControllerIntegrationTest.java index ababc861cf25ad503a3ff5d7b263e74b10e776c4..c06163b510596263606000bb769b6100cb56cc9b 100644 --- a/web/src/test/java/lcsb/mapviewer/web/UserControllerIntegrationTest.java +++ b/web/src/test/java/lcsb/mapviewer/web/UserControllerIntegrationTest.java @@ -24,6 +24,7 @@ import java.util.Calendar; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.UUID; import org.apache.commons.lang3.StringUtils; import org.apache.http.client.entity.UrlEncodedFormEntity; @@ -51,7 +52,6 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.JsonParser; -import lcsb.mapviewer.annotation.services.ModelAnnotator; import lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator; import lcsb.mapviewer.api.users.UserController; import lcsb.mapviewer.api.users.UserController.UserPrivilegesDTO; @@ -92,7 +92,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { private static final String TEST_USER_PASSWORD = "test_pass"; private static final String TEST_USER_LOGIN = "test_user"; - private static final String TEST_LOGIN = "xyz"; + private static final String TEST_LOGIN = "test_login"; private User user; @@ -114,9 +114,6 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { @Autowired private UserController userController; - @Autowired - private ModelAnnotator modelAnnotator; - @Before public void setup() throws Exception { user = createUser(TEST_USER_LOGIN, TEST_USER_PASSWORD); @@ -194,7 +191,8 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { mockMvc.perform(request) .andExpect(status().is2xxSuccessful()); - assertEquals("Privilege wasn't revoked", 0, userService.getUserByLogin(TEST_USER_LOGIN, true).getPrivileges().size()); + assertEquals("Privilege wasn't revoked", 0, + userService.getUserByLogin(TEST_USER_LOGIN, true).getPrivileges().size()); } @Test @@ -420,8 +418,8 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD); String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( - new BasicNameValuePair("name", "FirstName"), - new BasicNameValuePair("password", "FirstName")))); + new BasicNameValuePair("name", "Name"), + new BasicNameValuePair("password", "Password")))); RequestBuilder grantRequest = post("/api/users/{login}", TEST_LOGIN) .contentType(MediaType.APPLICATION_FORM_URLENCODED) @@ -431,7 +429,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { mockMvc.perform(grantRequest) .andDo(document("user/create_user", userPathParameters(), - requestParameters(getUserRequestFieldsWithoutLogin()), + requestParameters(addUserRequestFields()), responseFields(getUserResponseFields()))) .andExpect(status().is2xxSuccessful()); @@ -465,7 +463,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("name", "FirstName"), - new BasicNameValuePair("password", "FirstName"), + new BasicNameValuePair("password", "UserPassword"), new BasicNameValuePair("defaultPrivileges", "true")))); RequestBuilder grantRequest = post("/api/users/" + TEST_LOGIN) @@ -499,7 +497,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { String body = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("name", "FirstName"), - new BasicNameValuePair("password", "FirstName"), + new BasicNameValuePair("password", "UserPassword"), new BasicNameValuePair("defaultPrivileges", "true")))); RequestBuilder grantRequest = post("/api/users/" + TEST_LOGIN) @@ -693,15 +691,13 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { @Test public void resetPassword() throws Exception { configureServerForResetPasswordRequest(); - - RequestBuilder request = post("/api/users/" + TEST_USER_LOGIN + ":requestResetPassword"); - - mockMvc.perform(request) - .andExpect(status().is2xxSuccessful()); - String newPassword = "pass2"; - ResetPasswordToken token = userService.getPasswordTokens(TEST_USER_LOGIN).get(0); + Calendar expires = Calendar.getInstance(); + expires.add(Calendar.DAY_OF_MONTH, 1); + ResetPasswordToken token = new ResetPasswordToken(user, UUID.randomUUID().toString().replaceAll("[a-z]", "0"), + expires); + userService.add(token); String content = EntityUtils.toString(new UrlEncodedFormEntity(Arrays.asList( new BasicNameValuePair("token", token.getToken()), @@ -719,7 +715,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { .description("new password"), parameterWithName("token") .optional() - .description("reset poassowrd token obtained using email")))) + .description("reset password token obtained using email")))) .andExpect(status().is2xxSuccessful()); createSession(TEST_USER_LOGIN, newPassword); @@ -808,7 +804,8 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { user.setEmail("test@test.xyz"); userService.updateUser(user); - configurationService.setConfigurationValue(ConfigurationElementType.MINERVA_ROOT, "https://minerva-dev.lcsb.uni.lu/minerva/"); + configurationService.setConfigurationValue(ConfigurationElementType.MINERVA_ROOT, + "https://minerva-dev.lcsb.uni.lu/minerva/"); } @Test @@ -850,11 +847,11 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { .optional() .type(JsonFieldType.STRING), fieldWithPath("connectedToLdap") - .description("is user account connected to ldap") + .description("is user account connected to LDAP") .optional() .type(JsonFieldType.BOOLEAN), fieldWithPath("ldapAccountAvailable") - .description("does is account exist in ldap") + .description("does the account exist in LDAP") .optional() .type(JsonFieldType.BOOLEAN), fieldWithPath("email") @@ -918,6 +915,24 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { return result; } + private List<ParameterDescriptor> addUserRequestFields() { + return Arrays.asList( + parameterWithName("name") + .optional() + .description("first name"), + parameterWithName("surname") + .optional() + .description("last name"), + parameterWithName("password") + .description("user password"), + parameterWithName("email") + .optional() + .description("email address"), + parameterWithName("defaultPrivileges") + .optional() + .description("should the default privileges be added to the user after user creation")); + } + private List<ParameterDescriptor> getUserRequestFieldsWithoutLogin() { return Arrays.asList( parameterWithName("password") @@ -925,10 +940,10 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { .description("user password"), parameterWithName("connectedToLdap") .optional() - .description("is user account connected to ldap"), + .description("is user account connected to LDAP"), parameterWithName("ldapAccountAvailable") .optional() - .description("does is account exist in ldap"), + .description("does is account exist in LDAP"), parameterWithName("email") .optional() .description("email address"), @@ -994,7 +1009,8 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { uniprotAnnotator.addAnnotatorParameter(new AnnotatorOutputParameter(MiriamType.UNIPROT)); uniprotAnnotator.addAnnotatorParameter(new AnnotatorOutputParameter(MiriamType.EC)); uniprotAnnotator.addAnnotatorParameter(new AnnotatorOutputParameter(MiriamType.ENTREZ)); - uniprotAnnotator.addAnnotatorParameter(new AnnotatorConfigParameter(AnnotatorParamDefinition.KEGG_ORGANISM_IDENTIFIER, "XXX")); + uniprotAnnotator + .addAnnotatorParameter(new AnnotatorConfigParameter(AnnotatorParamDefinition.KEGG_ORGANISM_IDENTIFIER, "XXX")); preferences.addClassAnnotator(new UserClassAnnotators(Gene.class, Arrays.asList(uniprotAnnotator))); RequestBuilder request = patch("/api/users/{login}:updatePreferences", TEST_USER_LOGIN) @@ -1024,8 +1040,10 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest { UserAnnotationSchema preferences = new UserAnnotationSchema(); UserPreferencesDTO data = new UserPreferencesDTO(preferences); - preferences.addClassRequiredAnnotations(new UserClassRequiredAnnotations(Protein.class, Arrays.asList(MiriamType.HGNC, MiriamType.HGNC_SYMBOL))); - preferences.addClassRequiredAnnotations(new UserClassRequiredAnnotations(SimpleMolecule.class, Arrays.asList(MiriamType.CHEBI))); + preferences.addClassRequiredAnnotations( + new UserClassRequiredAnnotations(Protein.class, Arrays.asList(MiriamType.HGNC, MiriamType.HGNC_SYMBOL))); + preferences.addClassRequiredAnnotations( + new UserClassRequiredAnnotations(SimpleMolecule.class, Arrays.asList(MiriamType.CHEBI))); preferences.getClassRequiredAnnotators().get(1).setRequireAtLeastOneAnnotation(false); RequestBuilder request = patch("/api/users/{login}:updatePreferences", TEST_USER_LOGIN) diff --git a/web/src/test/java/lcsb/mapviewer/web/serialization/ProjectBackgroundUpdateMixIn.java b/web/src/test/java/lcsb/mapviewer/web/serialization/ProjectBackgroundUpdateMixIn.java index 51c649c3405edfb4d9b06ced01b7c2263ebad2e2..dcab549d802fefad027dd01096292dcaeb3b8228 100644 --- a/web/src/test/java/lcsb/mapviewer/web/serialization/ProjectBackgroundUpdateMixIn.java +++ b/web/src/test/java/lcsb/mapviewer/web/serialization/ProjectBackgroundUpdateMixIn.java @@ -3,10 +3,13 @@ package lcsb.mapviewer.web.serialization; import java.util.List; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lcsb.mapviewer.model.Project; import lcsb.mapviewer.model.map.layout.ProjectBackgroundImageLayer; import lcsb.mapviewer.model.map.layout.ProjectBackgroundStatus; +import lcsb.mapviewer.model.user.User; +import lcsb.mapviewer.modelutils.serializer.model.user.UserAsLoginSerializer; public abstract class ProjectBackgroundUpdateMixIn { @JsonIgnore @@ -26,7 +29,10 @@ public abstract class ProjectBackgroundUpdateMixIn { @JsonIgnore public abstract double getProgress(); - + @JsonIgnore public abstract List<ProjectBackgroundImageLayer> getProjectBackgroundImageLayer(); + + @JsonSerialize(using = UserAsLoginSerializer.class) + public abstract User getCreator(); } diff --git a/web/src/test/java/lcsb/mapviewer/web/utils/CommandFormatterWithReplacingPostFilenameHeader.java b/web/src/test/java/lcsb/mapviewer/web/utils/CommandFormatterWithReplacingPostFilenameHeader.java index 608e42fdd17351e5089f551dc58d842d1564df91..b42b9465db3d4735d39ef7221928fbfc202ea16c 100644 --- a/web/src/test/java/lcsb/mapviewer/web/utils/CommandFormatterWithReplacingPostFilenameHeader.java +++ b/web/src/test/java/lcsb/mapviewer/web/utils/CommandFormatterWithReplacingPostFilenameHeader.java @@ -2,6 +2,8 @@ package lcsb.mapviewer.web.utils; import java.util.List; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.restdocs.cli.CommandFormatter; import org.springframework.util.CollectionUtils; @@ -14,11 +16,20 @@ import lcsb.mapviewer.common.Configuration; * reference @filename. The filename is taken from header "post-filename" which * will be removed from the curl sample. * + * <p> + * It is also a workaround the issue that restdocs ignores fact that curl by + * default uses application/x-www-form-urlencoded content-type if no content + * type is provided. + * </p> + * + * * @author Piotr Gawron * */ public class CommandFormatterWithReplacingPostFilenameHeader implements CommandFormatter { + protected static Logger logger = LogManager.getLogger(); + private String separator; /** @@ -41,14 +52,14 @@ public class CommandFormatterWithReplacingPostFilenameHeader implements CommandF @Override public String format(final List<String> elements) { if (CollectionUtils.isEmpty(elements)) { - return ""; - } - String contentFileName = null; - for (final String element : elements) { - if (element.startsWith("-H 'post-filename:")) { - contentFileName = element.replace("-H 'post-filename: ", "").replace("'", ""); + if (session) { + return String.format(this.separator) + "--cookie \"" + Configuration.AUTH_TOKEN + "=xxxxxxxx\""; } + return ""; } + String contentFileName = getContentFileName(elements); + String contentType = getContentType(elements); + if (session) { elements.add("--cookie \"" + Configuration.AUTH_TOKEN + "=xxxxxxxx\""); } @@ -58,14 +69,42 @@ public class CommandFormatterWithReplacingPostFilenameHeader implements CommandF if (element.startsWith("-d") && contentFileName != null) { element = "--data-binary @" + contentFileName; } - if (!element.startsWith("-H 'post-filename:")) { + if (!element.startsWith("-H 'post-filename:") + && !element.toLowerCase().startsWith("-h 'content-type:")) { result.append(String.format(this.separator)); result.append(element); } } + if (contentType != null && !contentType.isEmpty()) { + result.append(String.format(this.separator)); + result.append("-H 'Content-Type: " + contentType + "'"); + } return result.toString(); } + public String getContentType(final List<String> elements) { + String contentType = "application/octet-stream"; + for (String orgString : elements) { + String string = orgString.replaceAll("\\s+", "") + .replaceAll("'", "") + .replaceAll("\"", ""); + if (string.toLowerCase().startsWith("-hcontent-type:")) { + return string.split(":")[1]; + } + } + return contentType; + } + + private String getContentFileName(final List<String> elements) { + String contentFileName = null; + for (final String element : elements) { + if (element.startsWith("-H 'post-filename:")) { + contentFileName = element.replace("-H 'post-filename: ", "").replace("'", ""); + } + } + return contentFileName; + } + public void setSessionAvailable(final boolean session) { this.session = session; } diff --git a/web/src/test/java/lcsb/mapviewer/web/utils/CustomCurlRequestSnippet.java b/web/src/test/java/lcsb/mapviewer/web/utils/CustomCurlRequestSnippet.java index 3c37f8e3e963d06d5720b3a02564f54c81df4a25..0766e3a0054f08696859796e94923fb65d6fa49d 100644 --- a/web/src/test/java/lcsb/mapviewer/web/utils/CustomCurlRequestSnippet.java +++ b/web/src/test/java/lcsb/mapviewer/web/utils/CustomCurlRequestSnippet.java @@ -2,6 +2,8 @@ package lcsb.mapviewer.web.utils; import java.util.Map; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.springframework.restdocs.cli.CommandFormatter; import org.springframework.restdocs.cli.CurlRequestSnippet; import org.springframework.restdocs.operation.Operation; @@ -17,6 +19,8 @@ import org.springframework.restdocs.operation.Operation; */ public class CustomCurlRequestSnippet extends CurlRequestSnippet { + protected static Logger logger = LogManager.getLogger(); + private final CommandFormatter commandFormatter; public CustomCurlRequestSnippet(final CommandFormatter commandFormatter) { @@ -35,11 +39,19 @@ public class CustomCurlRequestSnippet extends CurlRequestSnippet { boolean session = false; if (obj instanceof org.springframework.mock.web.MockHttpServletRequest) { session = (((org.springframework.mock.web.MockHttpServletRequest) obj).getSession() != null); + if (session) { + session = !((org.springframework.mock.web.MockHttpServletRequest) obj).getSession().isNew(); + } } if (commandFormatter instanceof CommandFormatterWithReplacingPostFilenameHeader) { ((CommandFormatterWithReplacingPostFilenameHeader) commandFormatter).setSessionAvailable(session); } - return super.createModel(operation); + Map<String, Object> result = super.createModel(operation); + + String options = (String) result.get("options"); + // get rid of writeIncludeHeadersInOutputOption + result.put("options", options.replace("-i ", "")); + return result; } } diff --git a/web/src/test/resources/complex_model_with_genomic_layout.zip b/web/src/test/resources/complex_model_with_genomic_layout.zip new file mode 100644 index 0000000000000000000000000000000000000000..b8df8b8a9ac8bca2b9428088ad125f76fd83cc48 Binary files /dev/null and b/web/src/test/resources/complex_model_with_genomic_layout.zip differ