diff --git a/LDK/api-src/org/labkey/api/ldk/table/ContainerScopedTable.java b/LDK/api-src/org/labkey/api/ldk/table/ContainerScopedTable.java index 975f117e..3575eeca 100644 --- a/LDK/api-src/org/labkey/api/ldk/table/ContainerScopedTable.java +++ b/LDK/api-src/org/labkey/api/ldk/table/ContainerScopedTable.java @@ -122,7 +122,7 @@ public DataIteratorBuilder persistRows(DataIteratorBuilder data, DataIteratorCon protected class UpdateService extends SimpleQueryUpdateService { - private KeyManager _keyManager = new KeyManager(); + private final KeyManager _keyManager = new KeyManager(); public UpdateService(SimpleUserSchema.SimpleTable ti) { diff --git a/LDK/src/org/labkey/ldk/LDKController.java b/LDK/src/org/labkey/ldk/LDKController.java index 3f40d163..168ac090 100644 --- a/LDK/src/org/labkey/ldk/LDKController.java +++ b/LDK/src/org/labkey/ldk/LDKController.java @@ -847,14 +847,10 @@ public ModelAndView getView(QueryForm form, BindException errors) throws Excepti if (keyField != null) { + // Note: the ContainerContext will need to be set within QueryView DetailsURL importUrl = DetailsURL.fromString("/query/importData.view?schemaName=" + schemaName + "&query.queryName=" + queryName + "&keyField=" + keyField); - importUrl.setContainerContext(getContainer()); - DetailsURL updateUrl = DetailsURL.fromString("/ldk/manageRecord.view?schemaName=" + schemaName + "&query.queryName=" + queryName + "&keyField=" + keyField + "&key=${" + keyField + "}"); - updateUrl.setContainerContext(getContainer()); - DetailsURL deleteUrl = DetailsURL.fromString("/query/deleteQueryRows.view?schemaName=" + schemaName + "&query.queryName=" + queryName); - deleteUrl.setContainerContext(getContainer()); url.addParameter("importURL", importUrl.toString()); url.addParameter("updateURL", updateUrl.toString()); @@ -866,7 +862,7 @@ public ModelAndView getView(QueryForm form, BindException errors) throws Excepti url.addParameter("queryName", queryName); url.addParameter("allowChooseQuery", false); - WebPartFactory factory = Portal.getPortalPartCaseInsensitive("Query"); + WebPartFactory factory = Portal.getPortalPart("Query"); Portal.WebPart part = factory.createWebPart(); part.setProperties(url.getQueryString()); diff --git a/laboratory/api-src/org/labkey/api/laboratory/query/ContainerIncrementingTable.java b/laboratory/api-src/org/labkey/api/laboratory/query/ContainerIncrementingTable.java index bc3e7843..0845cbc6 100644 --- a/laboratory/api-src/org/labkey/api/laboratory/query/ContainerIncrementingTable.java +++ b/laboratory/api-src/org/labkey/api/laboratory/query/ContainerIncrementingTable.java @@ -59,7 +59,7 @@ public ContainerIncrementingTable(UserSchema us, TableInfo st, ContainerFilter c } @Override - public SimpleUserSchema.SimpleTable init() + public SimpleUserSchema.SimpleTable init() { super.init(); diff --git a/laboratory/src/org/labkey/laboratory/query/LaboratoryTableCustomizer.java b/laboratory/src/org/labkey/laboratory/query/LaboratoryTableCustomizer.java index af8a869d..5f0ae687 100644 --- a/laboratory/src/org/labkey/laboratory/query/LaboratoryTableCustomizer.java +++ b/laboratory/src/org/labkey/laboratory/query/LaboratoryTableCustomizer.java @@ -7,6 +7,7 @@ import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import org.labkey.api.data.AbstractTableInfo; +import org.labkey.api.data.BaseColumnInfo; import org.labkey.api.data.ColumnInfo; import org.labkey.api.data.Container; import org.labkey.api.data.ContainerFilter; @@ -18,7 +19,7 @@ import org.labkey.api.data.SQLFragment; import org.labkey.api.data.TableCustomizer; import org.labkey.api.data.TableInfo; -import org.labkey.api.data.WrappedColumn; +import org.labkey.api.data.WrappedColumnInfo; import org.labkey.api.gwt.client.FacetingBehaviorType; import org.labkey.api.laboratory.LaboratoryService; import org.labkey.api.ldk.LDKService; @@ -183,13 +184,16 @@ public void customizeColumns(AbstractTableInfo ti) { container.setHidden(true); - WrappedColumn wrappedContainer = new WrappedColumn(container, "workbook"); - wrappedContainer.setLabel("Workbook"); + BaseColumnInfo wrappedContainer = WrappedColumnInfo.wrapAsCopy(ti, FieldKey.fromString("workbook"), container, "Workbook", null); + wrappedContainer.setName("workbook"); + wrappedContainer.setCalculated(true); + wrappedContainer.setShownInInsertView(false); + wrappedContainer.setShownInUpdateView(false); wrappedContainer.setFk(QueryForeignKey .from(ti.getUserSchema(), ti.getContainerFilter()) .schema(us) .to("workbooks", LaboratoryWorkbooksTable.WORKBOOK_COL, "workbookId")); - wrappedContainer.setURL(DetailsURL.fromString("/project/start.view")); + wrappedContainer.setURL(DetailsURL.fromString("/project/begin.view")); wrappedContainer.setShownInDetailsView(true); wrappedContainer.setFacetingBehaviorType(FacetingBehaviorType.ALWAYS_OFF); wrappedContainer.setDisplayColumnFactory(new DisplayColumnFactory() @@ -290,11 +294,15 @@ private void appendDemographicsCols(final UserSchema us, AbstractTableInfo ti, C if (ti.getColumn(name) != null) continue; - WrappedColumn col = new WrappedColumn(subjectCol, name); - col.setLabel(qd.getLabel()); + BaseColumnInfo col = WrappedColumnInfo.wrapAsCopy(ti, FieldKey.fromString(name), subjectCol, qd.getLabel(), null); + col.setName(name); + col.setCalculated(true); + col.setShownInInsertView(false); + col.setShownInUpdateView(false); col.setReadOnly(true); col.setIsUnselectable(true); col.setUserEditable(false); + col.setKeyField(false); UserSchema targetSchema = qd.getTableInfo(targetContainer, us.getUser()).getUserSchema(); col.setFk(new QueryForeignKey(us, ti.getContainerFilter(), targetSchema, null, qd.getQueryName(), qd.getTargetColumn(), qd.getTargetColumn()) @@ -366,12 +374,16 @@ private void appendMajorEventsCol(final UserSchema us, AbstractTableInfo ds, fin final String pkColSelectName = pk.getFieldKey().toSQLString(); final String pkColRawName = pk.getName(); - MutableColumnInfo col = new WrappedColumn(pk, name); - col.setLabel("Major Events"); + BaseColumnInfo col = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(name), pk, "Major Events", null); col.setDescription("This column shows all major events recorded in this subject's history and will calculate the time elapsed between the current sample and these dates."); + col.setName(name); + col.setCalculated(true); + col.setShownInInsertView(false); + col.setShownInUpdateView(false); col.setReadOnly(true); col.setIsUnselectable(true); col.setUserEditable(false); + col.setKeyField(false); final String schemaName = ds.getUserSchema().getSchemaPath().toSQLString(); final String subjectSelectName = ds.getSqlDialect().makeLegalIdentifier(subjectColName); @@ -384,11 +396,10 @@ private void appendMajorEventsCol(final UserSchema us, AbstractTableInfo ds, fin @Override public TableInfo getLookupTableInfo() { - Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - UserSchema effectiveUs = us.getContainer().isWorkbookOrTab() ? QueryService.get().getUserSchema(us.getUser(), target, us.getSchemaPath()) : us; - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, effectiveUs, colName); + Container parentContainer = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); + QueryDefinition qd = createQueryDef(us, colName); - qd.setSql(getMajorEventsSql(target, schemaName, querySelectName, pkColSelectName, subjectSelectName, dateSelectName)); + qd.setSql(getMajorEventsSql(parentContainer, schemaName, querySelectName, pkColSelectName, subjectSelectName, dateSelectName)); qd.setIsTemporary(true); List errors = new ArrayList<>(); @@ -444,21 +455,24 @@ private void appendOverlapingProjectsCol(final UserSchema us, AbstractTableInfo final String subjectSelectName = ds.getSqlDialect().makeLegalIdentifier(subjectColName); final String dateSelectName = dateColName == null ? null : ds.getSqlDialect().makeLegalIdentifier(dateColName); - WrappedColumn col = new WrappedColumn(pk, name); - col.setLabel("Overlapping Groups"); + BaseColumnInfo col = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(name), pk, "Overlapping Groups", null); col.setDescription("This column shows all groups to which this subject belonged at the time of this sample."); + col.setName(name); + col.setCalculated(true); + col.setShownInInsertView(false); + col.setShownInUpdateView(false); col.setReadOnly(true); col.setIsUnselectable(true); col.setUserEditable(false); + col.setKeyField(false); col.setFk(new LookupForeignKey(){ @Override public TableInfo getLookupTableInfo() { - Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - UserSchema effectiveUs = us.getContainer().isWorkbookOrTab() ? QueryService.get().getUserSchema(us.getUser(), target, us.getSchemaPath()) : us; - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, effectiveUs, colName); + Container parentContainer = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); + QueryDefinition qd = createQueryDef(us, colName); - qd.setSql(getOverlapSql(target, schemaName, querySelectName, pkColSelectName, subjectSelectName, dateSelectName)); + qd.setSql(getOverlapSql(parentContainer, schemaName, querySelectName, pkColSelectName, subjectSelectName, dateSelectName)); qd.setIsTemporary(true); List errors = new ArrayList<>(); @@ -490,20 +504,24 @@ public TableInfo getLookupTableInfo() //add pivot column String pivotColName = "overlappingProjectsPivot"; - WrappedColumn col2 = new WrappedColumn(pk, pivotColName); - col2.setLabel("Overlapping Group List"); + BaseColumnInfo col2 = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(pivotColName), pk, "Overlapping Group List", null); + col2.setName(pivotColName); + col2.setCalculated(true); + col2.setShownInInsertView(false); + col2.setShownInUpdateView(false); col2.setDescription("Shows groups to which this subject belonged at the time of this sample."); col2.setHidden(true); col2.setReadOnly(true); col2.setIsUnselectable(true); col2.setUserEditable(false); + col2.setKeyField(false); final String lookupColName = ds.getName() + "_overlappingProjectsPivot"; col2.setFk(new LookupForeignKey(){ @Override public TableInfo getLookupTableInfo() { Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, us, lookupColName); + QueryDefinition qd = createQueryDef(us, lookupColName); qd.setSql(getOverlapPivotSql(target, schemaName, querySelectName, pkColSelectName, subjectColName, dateColName)); qd.setIsTemporary(true); @@ -555,21 +573,24 @@ public void appendProjectsCol(final UserSchema us, AbstractTableInfo ds, final S final String publicTableName = ds.getPublicName(); final String colName = ds.getName() + "_allProjects"; - WrappedColumn col = new WrappedColumn(pk, name); - col.setLabel("Groups"); + BaseColumnInfo col = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(name), pk, "Groups", null); + col.setName(name); + col.setCalculated(true); + col.setShownInInsertView(false); + col.setShownInUpdateView(false); col.setDescription("This column shows all groups to which this subject has ever been a member, regardless of whether that assignment overlaps with the current data point"); col.setReadOnly(true); col.setIsUnselectable(true); col.setUserEditable(false); + col.setKeyField(false); col.setFk(new LookupForeignKey(){ @Override public TableInfo getLookupTableInfo() { - Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - UserSchema effectiveUs = us.getContainer().isWorkbookOrTab() ? QueryService.get().getUserSchema(us.getUser(), target, us.getSchemaPath()) : us; - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, effectiveUs, colName); + Container parentContainer = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); + QueryDefinition qd = createQueryDef(us, colName); - qd.setSql(getOverlapSql(target, schemaName, querySelectName, pkColSelectName, subjectSelectName, null)); + qd.setSql(getOverlapSql(parentContainer, schemaName, querySelectName, pkColSelectName, subjectSelectName, null)); qd.setIsTemporary(true); List errors = new ArrayList<>(); @@ -602,20 +623,23 @@ public TableInfo getLookupTableInfo() //add pivot column String pivotColName = "allProjectsPivot"; final String lookupName = ds.getName() + "_allProjectsPivot"; - WrappedColumn col2 = new WrappedColumn(pk, pivotColName); - col2.setLabel("Group Summary List"); + BaseColumnInfo col2 = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(pivotColName), pk, "Group Summary List", null); + col2.setName(pivotColName); + col2.setCalculated(true); + col2.setShownInInsertView(false); + col2.setShownInUpdateView(false); col2.setDescription("Shows groups to which this subject belonged at any point in time."); col2.setHidden(true); col2.setReadOnly(true); col2.setIsUnselectable(true); col2.setUserEditable(false); + col2.setKeyField(false); col2.setFk(new LookupForeignKey(){ @Override public TableInfo getLookupTableInfo() { Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - UserSchema effectiveUs = us.getContainer().isWorkbookOrTab() ? QueryService.get().getUserSchema(us.getUser(), target, us.getSchemaPath()) : us; - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, effectiveUs, lookupName); + QueryDefinition qd = createQueryDef(us, lookupName); qd.setSql(getOverlapPivotSql(target, schemaName, querySelectName, pkColSelectName, subjectSelectName, null)); qd.setIsTemporary(true); @@ -749,11 +773,15 @@ private void appendRelativeDatesCol(final UserSchema us, AbstractTableInfo ds, f final String pkColSelectName = pk.getFieldKey().toSQLString(); final String pkColRawName = pk.getName(); - WrappedColumn col = new WrappedColumn(pk, name); - col.setLabel("Relative Dates"); + BaseColumnInfo col = WrappedColumnInfo.wrapAsCopy(ds, FieldKey.fromString(name), pk, "Relative Dates", null); + col.setName(name); + col.setCalculated(true); + col.setShownInInsertView(false); + col.setShownInUpdateView(false); col.setReadOnly(true); col.setIsUnselectable(true); col.setUserEditable(false); + col.setKeyField(false); final String colName = ds.getName() + "_relativeDates"; final String schemaName = ds.getUserSchema().getSchemaPath().toSQLString(); @@ -765,9 +793,8 @@ private void appendRelativeDatesCol(final UserSchema us, AbstractTableInfo ds, f @Override public TableInfo getLookupTableInfo() { - Container target = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); - UserSchema effectiveUs = us.getContainer().isWorkbookOrTab() ? QueryService.get().getUserSchema(us.getUser(), target, us.getSchemaPath()) : us; - QueryDefinition qd = QueryService.get().createQueryDef(us.getUser(), target, effectiveUs, colName); + Container parentContainer = us.getContainer().isWorkbookOrTab() ? us.getContainer().getParent() : us.getContainer(); + QueryDefinition qd = createQueryDef(us, colName); qd.setSql("SELECT\n" + "t." + pkColSelectName + ",\n" + @@ -795,7 +822,7 @@ public TableInfo getLookupTableInfo() "ROUND(CONVERT(age_in_months(p.startdate, s." + dateSelectName + "), DOUBLE) / 12, 1) AS YearsPostStartDecimal,\n" + "\n" + "FROM " + schemaName + "." + publicTableName + " s\n" + - "JOIN \"" + target.getPath() + "\".laboratory.project_usage p\n" + + "JOIN \"" + parentContainer.getPath() + "\".laboratory.project_usage p\n" + "ON (s." + subjectSelectName + " = p.subjectId AND CONVERT(p.startdate, DATE) <= CONVERT(s." + dateSelectName + ", DATE) AND CONVERT(s." + dateSelectName + ", DATE) <= CONVERT(COALESCE(p.enddate, {fn curdate()}), DATE))\n" + "WHERE s." + dateSelectName + " IS NOT NULL and s." + subjectSelectName + " IS NOT NULL\n" + "\n" + @@ -830,6 +857,28 @@ public TableInfo getLookupTableInfo() ds.addColumn(col); } + private QueryDefinition createQueryDef(UserSchema us, String queryName) + { + if (!us.getContainer().isWorkbook()) + { + return QueryService.get().createQueryDef(us.getUser(), us.getContainer(), us, queryName); + } + + // The rationale is that if we are querying from a workbook, preferentially translate to the parent US + // However, there are situations like workbook-scoped lists, where that query might not exist on the parent + UserSchema parentUserSchema = QueryService.get().getUserSchema(us.getUser(), us.getContainer().getParent(), us.getSchemaPath()); + assert parentUserSchema != null; + + if (parentUserSchema.getTableNames().contains(queryName)) + { + return QueryService.get().createQueryDef(parentUserSchema.getUser(), parentUserSchema.getContainer(), parentUserSchema, queryName); + } + else + { + return QueryService.get().createQueryDef(us.getUser(), us.getContainer(), us, queryName); + } + } + public UserSchema getUserSchema(AbstractTableInfo ds, String name) { UserSchema us = ds.getUserSchema();