private void addOrReplaceGene(List<Gene> allGenes, Gene gene) { // need index for replacement; performance is not critical since this code is only // used for old 1.2.x. patient JSONs for (int i = 0; i < allGenes.size(); i++) { if (StringUtils.equals(allGenes.get(i).getId(), gene.getId())) { allGenes.set(i, gene); return; } } allGenes.add(gene); }
/** * Create a map of gene ID to gene properties that merges existing and updated gene data. * * @param genes the gene data to add to patient * @param storedGenes the gene data already stored in patient * @return a list of merged genes */ private Map<String, Gene> getMergedGenes( @Nullable final Iterable<Gene> genes, @Nullable final Iterable<Gene> storedGenes) { // If map keys collide, merge genes in favor of the new value return Stream.of(storedGenes, genes) .filter(Objects::nonNull) .flatMap(s -> StreamSupport.stream(s.spliterator(), false)) .collect(Collectors.toMap(gene -> gene.getId(), Function.identity(), (v1, v2) -> v2, LinkedHashMap::new)); }
/** * Supports both 1.3-m5 and older 1.3-xx format. 1.3-m5 and newer format: {"id": ENSEMBL_Id [[, "gene": HGNC_Symbol] * , ...] } 1.3-old format: {"gene": HGNC_Symbol [, ...] } */ private void parseGenesJson(JSONObject json, List<Gene> accumulatedGenes) { JSONArray genesJson = json.optJSONArray(GENES_STRING); Set<String> alreadyCollectedGeneNames = new HashSet<>(); if (genesJson != null) { for (int i = 0; i < genesJson.length(); ++i) { JSONObject geneJson = genesJson.getJSONObject(i); // gene ID is either the "id" field, or, if missing, the "gene" field // if both missing, gene is not created if (StringUtils.isBlank(geneJson.optString(JSON_GENE_ID)) && StringUtils.isBlank(geneJson.optString(JSON_GENE_SYMBOL))) { continue; } Gene gene = new PhenoTipsGene(geneJson); if (gene == null || alreadyCollectedGeneNames.contains(gene.getId())) { continue; } accumulatedGenes.add(gene); alreadyCollectedGeneNames.add(gene.getId()); } } }
/** * Extracts rejected genes from provided {@code genes} data. * * @param genes a {@link PatientData} object containing gene data for the {@link #patient} * @return a set of rejected {@link VocabularyTerm genes} */ private Set<VocabularyTerm> extractRejectedGenes(@Nullable final PatientData<Gene> genes) { if (genes == null) { return Collections.emptySet(); } final Set<VocabularyTerm> rejected = new HashSet<>(); final Vocabulary hgnc = this.vocabularyManager.getVocabulary(HGNC); for (final Gene gene : genes) { if (REJECTED.equals(gene.getStatus()) || REJECTED_CANDIDATE.equals(gene.getStatus())) { final String geneID = gene.getId(); final VocabularyTerm geneObj = hgnc.getTerm(geneID); CollectionUtils.addIgnoreNull(rejected, geneObj); } } return rejected; }
/** * Saves a {@code gene} for the provided {@code patient}. * * @param docX the {@link XWikiDocument} for patient * @param gene a gene to be saved * @param context the {@link XWikiContext} object */ private void saveGene( @Nonnull final XWikiDocument docX, @Nonnull final Gene gene, @Nonnull final XWikiContext context) { try { final BaseObject xwikiObject = docX.newXObject(Gene.GENE_CLASS, context); setXWikiObjectProperty(INTERNAL_GENE_KEY, gene.getId(), xwikiObject, context); String status = gene.getStatus(); // setting status to default 'candidate' if not defined yet setXWikiObjectProperty(INTERNAL_STATUS_KEY, StringUtils.isNotBlank(status) ? status : INTERNAL_CANDIDATE_VALUE, xwikiObject, context); setXWikiObjectProperty(INTERNAL_STRATEGY_KEY, gene.getStrategy(), xwikiObject, context); setXWikiObjectProperty(INTERNAL_COMMENTS_KEY, gene.getComment(), xwikiObject, context); } catch (final XWikiException e) { this.logger.error("Failed to save a specific gene: [{}]", e.getMessage()); } }