/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.molgenis.matrix.component.sqlbackend; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.persistence.EntityManager; import org.apache.commons.lang.StringUtils; import org.molgenis.matrix.component.SliceablePhenoMatrixMV; import org.molgenis.matrix.component.general.MatrixQueryRule; import org.molgenis.pheno.Measurement; import org.molgenis.protocol.Protocol; /** * This backend will function as a Multi-value backend for the Pheno (EAV) * model. The model works by constructing select queries on views that are * generated when data is loaded into pheno model * * @author jorislops */ public class EAVViewBackend implements Backend { private final String joinColumn; private final String tablePrefix; private HashMap<String, List<String>> ambiguityTable; private final EntityManager em; private final SliceablePhenoMatrixMV<?, ?, ?> matrix; private String leftJoinTable; public EAVViewBackend(SliceablePhenoMatrixMV<?, ?, ?> matrix, String tablePrefix, String leftJoinTable) { this.matrix = matrix; this.em = matrix.getEntityManager(); this.tablePrefix = tablePrefix; this.joinColumn = matrix.JOIN_COLUMN; this.leftJoinTable = leftJoinTable; } @Override public String createQuery(boolean count, List<MatrixQueryRule> rules) { StringBuilder sql = new StringBuilder("SELECT "); LinkedHashMap<Protocol, List<Measurement>> measurementsByProtocol = matrix.getMeasurementsByProtocol(); String firstTableName = tablePrefix; boolean hasJoinTable = StringUtils.isNotEmpty(leftJoinTable); if (hasJoinTable) { firstTableName += leftJoinTable; } else { firstTableName += tablePrefix + measurementsByProtocol.keySet().toArray(new Protocol[1])[0].getName(); } final String firstTableAlias = firstTableName + "_PK"; if (count) { sql.append(" COUNT(*) "); } else { // Select part ambiguityTable = BackendUtils.buildAmbiguityTable(measurementsByProtocol, leftJoinTable, joinColumn); if (hasJoinTable) { sql.append(String.format("%s.%s", firstTableAlias, joinColumn)); } int cnt = 0; for (Map.Entry<Protocol, List<Measurement>> entry : measurementsByProtocol.entrySet()) { for (Measurement m : entry.getValue()) { if (!(hasJoinTable && m.getName().equalsIgnoreCase(joinColumn))) { String tableName = String.format("%s%s", tablePrefix, entry.getKey().getName()); String column = String.format("%s.%s", tableName, m.getName()); if (ambiguityTable.containsKey(m.getName()) && ambiguityTable.get(m.getName()).size() > 1) { column = String.format("%s %s_%s", column, tableName, m.getName()); } if (cnt > 0 || hasJoinTable) { sql.append(", "); } sql.append(column); } ++cnt; } } } sql.append(" FROM "); if (hasJoinTable) { sql.append(String.format("%s %s", firstTableName, firstTableAlias)); } // From part int cnt = 0; for (Protocol p : measurementsByProtocol.keySet()) { String tableName = String.format("%s%s", tablePrefix, p.getName()); if (cnt > 0 || hasJoinTable) { sql.append(String.format(" %s JOIN %s ON (%s.%s = %s.%s)", hasJoinTable ? "LEFT" : "", tableName, firstTableAlias, joinColumn, tableName, joinColumn)); } else { sql.append(tableName); } ++cnt; } // Where part String where = BackendUtils.getFilterCondition(rules, em, true, tablePrefix); if (StringUtils.isNotEmpty(where)) { sql.append(" WHERE ").append(where); } Protocol sortProtocol = matrix.getSortProtocol(); if (sortProtocol != null) { sql.append(String.format(" ORDER BY %s%s.%s %s", tablePrefix, sortProtocol.getName(), matrix .getSortMeasurement().getName(), matrix.getSortOrder())); } return sql.toString(); } }