@@ -0,0 +1,1546 @@
+package org.intermine.webservice.server.core;%0A%0Aimport org.intermine.model.FastPathObject;%0Aimport org.intermine.model.InterMineObject;%0Aimport org.intermine.pathquery.Path;%0Aimport org.intermine.util.DynamicUtil;%0Aimport org.intermine.util.TypeUtil;%0A%0Apublic final class TableCell%0A%7B%0A    private final FastPathObject fpo;%0A    %0A    private final Path column;%0A%0A    public TableCell(FastPathObject fpo, Path view) %7B%0A        this.fpo = fpo;%0A        this.column = view;%0A    %7D%0A    %0A    public TableCell(Path view) %7B%0A        this.fpo = null;%0A        this.column = view;%0A    %7D%0A    %0A    public Object getValue() %7B%0A        if (fpo == null) %7B%0A            return null;%0A        %7D%0A        try %7B%0A            return fpo.getFieldValue(column.getEndFieldDescriptor().getName());%0A        %7D catch (IllegalAccessException e) %7B%0A            throw new RuntimeException(%22Error retrieving field value.%22, e);%0A        %7D%0A    %7D;%0A    %0A    public FastPathObject getObject() %7B%0A        return fpo;%0A    %7D%0A    %0A    public String getType() %7B%0A        if (fpo == null) %7B%0A            return null;%0A        %7D%0A        String cls = DynamicUtil.getSimpleClassName(fpo.getClass());%0A        return TypeUtil.unqualifiedName(cls);%0A    %7D%0A    %0A    public Path getColumn() %7B%0A        return column;%0A    %7D%0A    %0A    public Integer getId() %7B%0A        if (fpo instanceof InterMineObject) %7B%0A            return ((InterMineObject) fpo).getId();%0A        %7D%0A        return null;%0A    %7D%0A    %0A    @Override%0A    public String toString() %7B%0A        return String.format(%22TableCell %5B %25s=%25s %5D%22, column, getValue());%0A    %7D%0A%7D%0A

The missing part of the outer-join puzzle