edu.toronto.cs.phenotips.tools.PropertyDisplayer.java Source code

Java tutorial

Introduction

Here is the source code for edu.toronto.cs.phenotips.tools.PropertyDisplayer.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package edu.toronto.cs.phenotips.tools;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.solr.common.SolrDocument;

import com.xpn.xwiki.api.Property;

import edu.toronto.cs.phenotips.solr.HPOScriptService;

public class PropertyDisplayer {
    private static final String TYPE_KEY = "type";

    private static final String GROUP_TYPE_KEY = "group_type";

    private static final String ID_KEY = "id";

    private static final String TITLE_KEY = "title";

    private static final String CATEGORIES_KEY = "categories";

    private static final String DATA_KEY = "data";

    private static final String ITEM_TYPE_SECTION = "section";

    private static final String ITEM_TYPE_SUBSECTION = "subsection";

    private static final String ITEM_TYPE_FIELD = "field";

    private static final String INDEXED_NAME_KEY = "name";

    private static final String INDEXED_CATEGORY_KEY = "term_category";

    private static final String INDEXED_PARENT_KEY = "is_a";

    protected HPOScriptService ontologyService;

    private final FormData data;

    protected final String[] fieldNames;

    protected final String propertyName;

    private Map<String, Map<String, String>> metadata;

    private List<FormSection> sections = new LinkedList<FormSection>();

    PropertyDisplayer(Collection<Map<String, ?>> template, FormData data, HPOScriptService ontologyService) {
        this.data = data;
        this.ontologyService = ontologyService;
        this.fieldNames = new String[2];
        this.fieldNames[0] = data.getPositiveFieldName();
        this.fieldNames[1] = data.getNegativeFieldName();
        this.propertyName = data.getPositivePropertyName();
        this.prepareMetaData();
        List<String> customYesSelected = new LinkedList<String>();
        if (data.getSelectedValues() != null) {
            customYesSelected.addAll(data.getSelectedValues());
        }
        List<String> customNoSelected = new LinkedList<String>();
        if (data.getNegativeFieldName() != null && data.getSelectedNegativeValues() != null) {
            customNoSelected.addAll(data.getSelectedNegativeValues());
        }
        for (Map<String, ?> sectionTemplate : template) {
            if (isSection(sectionTemplate)) {
                this.sections.add(generateSection(sectionTemplate, customYesSelected, customNoSelected));
            }
        }
        Map<String, List<String>> yCustomCategories = new HashMap<String, List<String>>();
        Map<String, List<String>> nCustomCategories = new HashMap<String, List<String>>();
        for (String value : customYesSelected) {
            List<String> categories = new LinkedList<String>();
            categories.addAll(this.getCategoriesFromOntology(value));
            categories.addAll(this.getCategoriesFromCustomMapping(value, data.getCustomCategories()));
            if (categories.isEmpty()) {
                categories.add("HP:0000118");
            }
            yCustomCategories.put(value, categories);
        }
        for (String value : customNoSelected) {
            List<String> categories = new LinkedList<String>();
            categories.addAll(this.getCategoriesFromOntology(value));
            categories.addAll(this.getCategoriesFromCustomMapping(value, data.getCustomNegativeCategories()));
            if (categories.isEmpty()) {
                categories.add("HP:0000118");
            }
            nCustomCategories.put(value, categories);
        }
        for (FormSection section : this.sections) {
            List<String> yCustomFieldIDs = this.assignCustomFields(section, yCustomCategories);
            List<String> nCustomFieldIDs = this.assignCustomFields(section, nCustomCategories);
            for (String val : yCustomFieldIDs) {
                section.addCustomElement(this.generateField(val, null, false, true, false));
                yCustomCategories.remove(val);
            }
            for (String val : nCustomFieldIDs) {
                section.addCustomElement(this.generateField(val, null, false, false, true));
                nCustomCategories.remove(val);
            }
        }
    }

    public String display() {
        StringBuilder str = new StringBuilder();
        for (FormSection section : this.sections) {
            str.append(section.display(this.data.getMode(), this.fieldNames));
        }
        return str.toString();
    }

    private boolean isSection(Map<String, ?> item) {
        return ITEM_TYPE_SECTION.equals(item.get(TYPE_KEY)) && Collection.class.isInstance(item.get(CATEGORIES_KEY))
                && String.class.isInstance(item.get(TITLE_KEY)) && Collection.class.isInstance(item.get(DATA_KEY));
    }

    private boolean isSubsection(Map<String, ?> item) {
        return ITEM_TYPE_SUBSECTION.equals(item.get(TYPE_KEY)) && String.class.isInstance(item.get(TITLE_KEY))
                && Collection.class.isInstance(item.get(DATA_KEY));
    }

    private boolean isField(Map<String, ?> item) {
        return item.get(TYPE_KEY) == null || ITEM_TYPE_FIELD.equals(item.get(TYPE_KEY)) && item.get(ID_KEY) != null
                && String.class.isAssignableFrom(item.get(ID_KEY).getClass());
    }

    @SuppressWarnings("unchecked")
    private FormSection generateSection(Map<String, ?> sectionTemplate, List<String> customYesSelected,
            List<String> customNoSelected) {
        String title = (String) sectionTemplate.get(TITLE_KEY);
        Collection<String> categories = (Collection<String>) sectionTemplate.get(CATEGORIES_KEY);
        FormSection section = new FormSection(title, this.propertyName, categories);
        generateData(section, sectionTemplate, customYesSelected, customNoSelected);
        return section;
    }

    private FormElement generateSubsection(Map<String, ?> subsectionTemplate, List<String> customYesSelected,
            List<String> customNoSelected) {
        String title = (String) subsectionTemplate.get(TITLE_KEY);
        String type = (String) subsectionTemplate.get(GROUP_TYPE_KEY);
        if (type == null) {
            type = "";
        }
        FormGroup subsection = new FormSubsection(title, type);
        generateData(subsection, subsectionTemplate, customYesSelected, customNoSelected);
        return subsection;
    }

    @SuppressWarnings("unchecked")
    private void generateData(FormGroup formGroup, Map<String, ?> groupTemplate, List<String> customYesSelected,
            List<String> customNoSelected) {
        Collection<Map<String, ?>> data = (Collection<Map<String, ?>>) groupTemplate.get(DATA_KEY);
        for (Map<String, ?> item : data) {
            if (isSubsection(item)) {
                formGroup.addElement(generateSubsection(item, customYesSelected, customNoSelected));
            } else if (isField(item)) {
                formGroup.addElement(generateField(item, customYesSelected, customNoSelected));
            }
        }
    }

    private FormElement generateField(Map<String, ?> fieldTemplate, List<String> customYesSelected,
            List<String> customNoSelected) {
        String id = (String) fieldTemplate.get(ID_KEY);
        boolean yesSelected = customYesSelected.remove(id);
        boolean noSelected = customNoSelected.remove(id);
        return this.generateField(id, (String) fieldTemplate.get(TITLE_KEY), yesSelected, noSelected);

    }

    private FormElement generateField(String id, String title, boolean expandable, boolean yesSelected,
            boolean noSelected) {
        String hint = getLabelFromOntology(id);
        if (id.equals(hint) && title != null) {
            hint = title;
        }
        String metadata = "";
        Map<String, String> metadataValues = this.metadata.get(id);
        if (metadataValues != null) {
            metadata = metadataValues
                    .get(noSelected ? this.data.getNegativePropertyName() : this.data.getPositivePropertyName());
        }
        return new FormField(id, StringUtils.defaultIfEmpty(title, hint), hint, StringUtils.defaultString(metadata),
                expandable, yesSelected, noSelected);
    }

    private FormElement generateField(String id, String title, boolean yesSelected, boolean noSelected) {
        return generateField(id, title, hasDescendantsInOntology(id), yesSelected, noSelected);
    }

    private List<String> assignCustomFields(FormSection section, Map<String, List<String>> customCategories) {
        List<String> assigned = new LinkedList<String>();
        if (section.getCategories().size() == 0) {
            assigned.addAll(customCategories.keySet());
        } else {
            for (String value : customCategories.keySet()) {
                List<String> categories = customCategories.get(value);
                for (String c : categories) {
                    if (section.getCategories().contains(c)) {
                        assigned.add(value);
                        break;
                    }
                }
            }
        }
        return assigned;
    }

    private String getLabelFromOntology(String id) {
        if (!id.startsWith("HP:")) {
            return id;
        }
        SolrDocument phObj = this.ontologyService.get(id);
        if (phObj != null) {
            return (String) phObj.get(INDEXED_NAME_KEY);
        }
        return id;
    }

    private boolean hasDescendantsInOntology(String id) {
        if (!id.startsWith("HP:")) {
            return false;
        }
        Map<String, String> params = new HashMap<String, String>();
        params.put(INDEXED_PARENT_KEY, id);
        return (this.ontologyService.get(params) != null);
    }

    @SuppressWarnings("unchecked")
    private List<String> getCategoriesFromOntology(String value) {
        if (!value.startsWith("HP:")) {
            return Collections.emptyList();
        }
        SolrDocument termObj = this.ontologyService.get(value);
        if (termObj != null && termObj.get(INDEXED_CATEGORY_KEY) != null
                && List.class.isAssignableFrom(termObj.get(INDEXED_CATEGORY_KEY).getClass())) {
            return (List<String>) termObj.get(INDEXED_CATEGORY_KEY);
        }
        return new LinkedList<String>();
    }

    private List<String> getCategoriesFromCustomMapping(String value, Map<String, List<String>> customCategories) {
        for (Map.Entry<String, List<String>> category : customCategories.entrySet()) {
            if (StringUtils.equals(value, category.getKey()) && category.getValue() != null) {
                return category.getValue();
            }
        }
        return new LinkedList<String>();
    }

    private void prepareMetaData() {
        this.metadata = new HashMap<String, Map<String, String>>();
        for (com.xpn.xwiki.api.Object o : this.data.getDocument().getObjects("PhenoTips.PhenotypeMetaClass")) {
            String name = "";
            String category = "";
            StringBuilder value = new StringBuilder();
            for (String propname : o.getxWikiClass().getEnabledPropertyNames()) {
                Property property = o.getProperty(propname);
                Object propvalue = property.getValue();
                if (propvalue == null) {
                    continue;
                }
                if (StringUtils.equals("target_property_name", propname)) {
                    category = propvalue.toString();
                } else if (StringUtils.equals("target_property_value", propname)) {
                    name = propvalue.toString();
                } else {
                    value.append(o.get(propname).toString().replaceAll("\\{\\{/?html[^}]*+}}", "")
                            .replaceAll("<(/?)p>", "<$1dd>"));
                }
            }
            if (StringUtils.isNotBlank(name) && value.length() > 0) {
                Map<String, String> subvalues = this.metadata.get(name);
                if (subvalues == null) {
                    subvalues = new HashMap<String, String>();
                    this.metadata.put(name, subvalues);
                }
                subvalues.put(category, "<div class='phenotype-details'><dl>" + value.toString() + "</dl></div>");
            }

        }
    }
}