package net.enilink.komma.owl.editor.instances;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.CellLabelProvider;
import org.eclipse.jface.viewers.ColumnViewer;
import org.eclipse.jface.viewers.ContentViewer;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import net.enilink.commons.iterator.IExtendedIterator;
import net.enilink.komma.common.adapter.IAdapterFactory;
import net.enilink.komma.core.IEntity;
import net.enilink.komma.core.IQuery;
import net.enilink.komma.core.IReference;
import net.enilink.komma.core.IStatement;
import net.enilink.komma.core.IValue;
import net.enilink.komma.core.Statement;
import net.enilink.komma.edit.domain.IEditingDomain;
import net.enilink.komma.edit.properties.EditingHelper.Type;
import net.enilink.komma.edit.provider.ISearchableItemProvider;
import net.enilink.komma.edit.provider.SparqlSearchableItemProvider;
import net.enilink.komma.edit.ui.celleditor.PropertyCellEditingSupport;
import net.enilink.komma.edit.ui.provider.AdapterFactoryLabelProvider;
import net.enilink.komma.edit.ui.provider.LazyAdapterFactoryContentProvider;
import net.enilink.komma.em.concepts.IClass;
import net.enilink.komma.em.concepts.IProperty;
import net.enilink.komma.em.concepts.IResource;
import net.enilink.komma.em.util.ISparqlConstants;
import net.enilink.komma.model.IObject;
import net.enilink.komma.model.ModelUtil;
import net.enilink.vocab.rdfs.RDFS;
public class InstanceTablePart extends InstancesPart {
static final int LIMIT = 10000;
class ContentProvider extends LazyAdapterFactoryContentProvider implements ISearchableItemProvider {
Object[] elements;
public ContentProvider(IAdapterFactory adapterFactory) {
super(adapterFactory);
}
public IExtendedIterator<?> find(Object expression, Object parent, int limit) {
SparqlSearchableItemProvider searchableProvider = new SparqlSearchableItemProvider() {
@Override
protected String getQueryFindPatterns(Object parent) {
return "?s a ?parent . ";
}
};
return searchableProvider.find(expression, currentInput, 20);
}
}
class LabelProvider extends AdapterFactoryLabelProvider implements ITableLabelProvider {
public LabelProvider(IAdapterFactory adapterFactory) {
super(adapterFactory);
}
@Override
public String getColumnText(Object object, int columnIndex) {
if (properties != null && columnIndex < properties.size()) {
IProperty property = properties.get(columnIndex);
IResource resource = (IResource) object;
if (property == null) {
// return the object name
if (!rdfsLabelShown) {
return super.getColumnText(object, columnIndex);
} else {
return ModelUtil.getPName(object);
}
}
// access all values to fill the property set cache
Object[] values = resource.getAsSet(property).toArray();
if (values.length > 0) {
return super.getText(values[0]);
}
return null;
}
return super.getColumnText(object, columnIndex);
}
@Override
public Image getColumnImage(Object object, int columnIndex) {
return null;
}
}
class Comparator extends ViewerComparator {
int column;
int direction = SWT.UP;
int getDirection() {
return direction;
}
void setColumn(int column) {
if (column == this.column) {
// Same column as last sort; toggle the direction
direction = direction == SWT.DOWN ? SWT.UP : SWT.DOWN;
} else {
// New column; do an ascending sort
this.column = column;
direction = SWT.UP;
}
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
ITableLabelProvider labelProvider = (ITableLabelProvider) ((ContentViewer) viewer).getLabelProvider();
String l1 = labelProvider.getColumnText(e1, column);
String l2 = labelProvider.getColumnText(e2, column);
int result = (l1 == null ? "" : l1).compareToIgnoreCase(l2 == null ? "" : l2);
return direction == SWT.DOWN ? -result : result;
}
}
protected LabelProvider labelProvider;
protected IClass currentInput;
protected boolean sortAscending = true;
protected IReference sortProperty = null;
protected List<IProperty> properties;
protected boolean rdfsLabelShown;
@Override
protected StructuredViewer createViewer(Composite parent) {
Table table = getWidgetFactory().createTable(parent,
SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL | SWT.FULL_SELECTION | SWT.MULTI);
TableViewer viewer = new TableViewer(table);
viewer.getTable().setHeaderVisible(true);
viewer.setUseHashlookup(true);
return viewer;
}
@Override
protected void adapterFactoryChanged() {
getViewer().setContentProvider(new ContentProvider(getAdapterFactory()));
if (labelProvider != null) {
labelProvider.dispose();
}
labelProvider = new LabelProvider(getAdapterFactory());
createContextMenuFor(getViewer());
}
private SelectionAdapter getSelectionAdapter(final TableColumn column, final int index) {
return new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
TableViewer tableViewer = (TableViewer) getViewer();
Table table = tableViewer.getTable();
table.setSortColumn(column);
int dir = table.getSortDirection();
dir = dir == SWT.UP ? dir = SWT.DOWN : SWT.UP;
table.setSortDirection(dir);
sortAscending = dir == SWT.UP;
IProperty p = properties.get(index);
sortProperty = p == null ? null : p.getReference();
refresh();
}
};
}
@Override
protected void setInputToViewer(StructuredViewer viewer, IClass input) {
currentInput = input;
if (input == null) {
viewer.setInput(null);
} else {
TableViewer tableViewer = (TableViewer) viewer;
Table table = tableViewer.getTable();
for (TableColumn column : table.getColumns()) {
column.dispose();
}
properties = new ArrayList<>();
// null for the object itself
properties.add(null);
properties.addAll(input.getEntityManager()
.createQuery(ISparqlConstants.PREFIX + "SELECT DISTINCT ?p WHERE { ?r a ?c; ?p ?o . "
+ "filter (?p != rdf:type && not exists { ?r ?otherP ?o . ?otherP rdfs:subPropertyOf ?p filter (?otherP != ?p) }) }")
.setParameter("c", input).evaluate(IProperty.class).toList());
int col = 0;
rdfsLabelShown = false;
TableColumn sortColumn = null;
for (final IProperty property : properties) {
rdfsLabelShown |= RDFS.PROPERTY_LABEL.equals(property);
TableViewerColumn viewerColumn = new TableViewerColumn(tableViewer, SWT.LEFT);
TableColumn column = viewerColumn.getColumn();
column.setText(property == null ? "Instance" : labelProvider.getText(property));
column.setResizable(true);
column.setMoveable(true);
column.addSelectionListener(getSelectionAdapter(column, col++));
column.pack();
if (property == sortProperty || property != null && property.equals(sortProperty)) {
sortColumn = column;
}
viewerColumn.setLabelProvider(new CellLabelProvider() {
@Override
public void update(ViewerCell cell) {
int columnIndex = cell.getColumnIndex();
cell.setText(labelProvider.getColumnText(cell.getElement(), columnIndex));
}
});
if (property != null) {
viewerColumn.setEditingSupport(new PropertyCellEditingSupport(((ColumnViewer) viewer), Type.VALUE,
SWT.MULTI | SWT.WRAP | SWT.V_SCROLL) {
@Override
protected IStatement getStatement(Object element) {
List<IValue> values = ((IResource) element).getPropertyValues(property, false).toList();
return new Statement((IEntity) element, property, !values.isEmpty() ? values.get(0) : null);
}
@Override
protected IEditingDomain getEditingDomain() {
return InstanceTablePart.this.getEditingDomain();
}
});
}
}
if (sortColumn != null) {
table.setSortColumn(sortColumn);
table.setSortDirection(sortAscending ? SWT.UP : SWT.DOWN);
}
boolean sortByProperty = sortProperty != null && properties.contains(sortProperty);
String queryStr;
if (sortByProperty) {
queryStr = ISparqlConstants.PREFIX + "SELECT DISTINCT ?r WHERE { ?r a ?c; ?p ?o } order by "
+ (sortAscending ? "?o" : "desc(?o)") + " limit " + LIMIT;
} else {
queryStr = ISparqlConstants.PREFIX + "SELECT DISTINCT ?r WHERE { ?r a ?c } order by "
+ (sortAscending || sortProperty != null ? "?r" : "desc(?r)") + " limit " + LIMIT;
}
IQuery<?> query = input.getEntityManager().createQuery(queryStr).setParameter("c", input);
if (sortByProperty) {
query.setParameter("p", sortProperty);
}
List<IObject> instances = query.evaluateRestricted(IObject.class).toList();
viewer.setInput(instances.toArray());
}
}
}