package net.enilink.komma.edit.ui.properties.internal.parts;
import java.util.Collection;
import net.enilink.komma.common.adapter.IAdapterFactory;
import net.enilink.komma.common.command.CommandResult;
import net.enilink.komma.common.notify.INotification;
import net.enilink.komma.common.notify.INotificationListener;
import net.enilink.komma.common.notify.NotificationFilter;
import net.enilink.komma.common.ui.assist.ContentProposals;
import net.enilink.komma.core.IEntity;
import net.enilink.komma.core.IEntityManager;
import net.enilink.komma.core.ILiteral;
import net.enilink.komma.core.IReference;
import net.enilink.komma.core.IStatement;
import net.enilink.komma.core.IStatementPattern;
import net.enilink.komma.core.Literal;
import net.enilink.komma.core.Statement;
import net.enilink.komma.core.StatementPattern;
import net.enilink.komma.core.Statements;
import net.enilink.komma.core.URI;
import net.enilink.komma.core.URIs;
import net.enilink.komma.edit.domain.IEditingDomain;
import net.enilink.komma.edit.properties.IResourceProposal;
import net.enilink.komma.edit.properties.EditingHelper;
import net.enilink.komma.edit.properties.EditingHelper.Type;
import net.enilink.komma.edit.properties.IProposalSupport;
import net.enilink.komma.edit.ui.assist.JFaceContentProposal;
import net.enilink.komma.edit.ui.assist.JFaceProposalProvider;
import net.enilink.komma.edit.ui.provider.AdapterFactoryLabelProvider;
import net.enilink.komma.edit.ui.views.AbstractEditingDomainPart;
import net.enilink.komma.edit.ui.views.AbstractEditingDomainView;
import net.enilink.komma.model.IModelAware;
import net.enilink.komma.model.IModelSet;
import net.enilink.komma.model.ModelUtil;
import net.enilink.komma.model.event.IStatementNotification;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalListener;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
public class StatementView extends AbstractEditingDomainView {
class StatementPart extends AbstractEditingDomainPart implements
INotificationListener<INotification> {
class MyEditingHelper extends EditingHelper {
MyEditingHelper(Type type) {
super(type);
}
@Override
protected IEditingDomain getEditingDomain() {
return StatementPart.this.getEditingDomain();
}
};
IAdapterFactory adapterFactory;
AdapterFactoryLabelProvider labelProvider;
CLabel sLabel;
Label pIcon;
Text pText;
Text valueText;
Text langText;
Text typeText;
Button okButton;
IStatement stmt;
IResourceProposal acceptedResourceProposal;
MyEditingHelper propertyHelper = new MyEditingHelper(Type.PROPERTY);
MyEditingHelper valueHelper = new MyEditingHelper(Type.VALUE);
IModelSet modelSet;
@Override
public void createContents(Composite parent) {
parent.setLayout(new GridLayout(2, true));
sLabel = getWidgetFactory().createCLabel(parent, "");
sLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true,
false));
Composite pComposite = getWidgetFactory().createComposite(parent);
pComposite.setLayout(new GridLayout(2, false));
pComposite.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING,
true, false));
pIcon = getWidgetFactory().createLabel(pComposite, "");
GridData data = new GridData(SWT.RIGHT, SWT.BEGINNING, false, false);
data.widthHint = 20;
pIcon.setLayoutData(data);
pText = getWidgetFactory().createText(pComposite, "");
pText.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true,
false));
pText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
setDirty(true);
}
});
createProposalAdapter(pText, propertyHelper);
valueText = getWidgetFactory().createText(parent, "",
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.verticalIndent = 10;
data.horizontalSpan = 2;
valueText.setLayoutData(data);
valueText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
acceptedResourceProposal = null;
setDirty(true);
}
});
ContentProposalAdapter valueProposalAdapter = createProposalAdapter(
valueText, valueHelper);
valueProposalAdapter
.addContentProposalListener(new IContentProposalListener() {
@Override
public void proposalAccepted(IContentProposal proposal) {
if (((JFaceContentProposal) proposal).getDelegate() instanceof IResourceProposal) {
IResourceProposal resourceProposal = (IResourceProposal) ((JFaceContentProposal) proposal)
.getDelegate();
acceptedResourceProposal = resourceProposal
.getUseAsValue() ? resourceProposal
: null;
setDirty(true);
}
}
});
Composite footer = getWidgetFactory().createComposite(parent);
footer.setLayout(new GridLayout(5, false));
data = new GridData(SWT.FILL, SWT.END, true, false);
data.horizontalSpan = 2;
footer.setLayoutData(data);
getWidgetFactory().createLabel(footer, "@");
langText = getWidgetFactory().createText(footer, "",
SWT.SINGLE | SWT.H_SCROLL);
data = new GridData();
data.widthHint = 50;
langText.setLayoutData(data);
langText.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
if (!langText.getText().isEmpty()
&& !typeText.getText().isEmpty()) {
typeText.setText("");
}
}
});
langText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
setDirty(true);
}
});
Label typeLabel = getWidgetFactory().createLabel(footer, "^^");
data = new GridData();
data.horizontalIndent = 10;
typeLabel.setLayoutData(data);
typeText = getWidgetFactory().createText(footer, "",
SWT.SINGLE | SWT.H_SCROLL);
createProposalAdapter(typeText, new MyEditingHelper(
Type.LITERAL_LANG_TYPE));
typeText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true,
false));
typeText.addFocusListener(new FocusAdapter() {
@Override
public void focusLost(FocusEvent e) {
if (!typeText.getText().isEmpty()
&& !langText.getText().isEmpty()) {
langText.setText("");
}
}
});
typeText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
setDirty(true);
}
});
okButton = getWidgetFactory().createButton(footer, "OK", SWT.PUSH);
data = new GridData();
data.horizontalIndent = 10;
okButton.setLayoutData(data);
okButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
commit(false);
}
});
getWidgetFactory().paintBordersFor(parent);
// disable controls
refresh();
}
protected ContentProposalAdapter createProposalAdapter(Text text,
final EditingHelper editingHelper) {
return ContentProposals.enableContentProposal(text,
new IContentProposalProvider() {
@Override
public IContentProposal[] getProposals(String contents,
int position) {
if (stmt != null) {
IProposalSupport proposalSupport = editingHelper
.getProposalSupport(stmt);
if (proposalSupport != null) {
return JFaceProposalProvider.wrap(
proposalSupport
.getProposalProvider())
.getProposals(contents, position);
}
}
return new IContentProposal[0];
}
}, null);
}
@Override
public boolean setEditorInput(Object input) {
if (input instanceof IStatement || input == null) {
this.stmt = (IStatement) input;
setStale(true);
return true;
} else if (input instanceof StatementNode) {
this.stmt = ((StatementNode) input).getStatement();
setStale(true);
return true;
}
return false;
}
protected URI toURI(IEntityManager em, String pnameOrUri) {
if (pnameOrUri.matches("<.*>")) {
try {
return URIs.createURI(pnameOrUri.substring(1,
pnameOrUri.length() - 1));
} catch (IllegalArgumentException e) {
// should be shown in UI
}
} else {
String prefix = "";
int colon = pnameOrUri.indexOf(':');
if (colon >= 0) {
prefix = pnameOrUri.substring(0, colon);
pnameOrUri = pnameOrUri.substring(colon + 1,
pnameOrUri.length());
}
URI ns = em.getNamespace(prefix);
if (ns != null) {
return ns.appendLocalPart(pnameOrUri);
}
}
return null;
}
@Override
public void commit(boolean onSave) {
if (isDirty() && stmt != null) {
IEntityManager em = ((IEntity) stmt.getSubject())
.getEntityManager();
String lang = langText.getText().trim();
String type = typeText.getText().trim();
Object newValue = acceptedResourceProposal;
if (!lang.isEmpty()) {
newValue = new Literal(valueText.getText(), lang);
} else if (!type.isEmpty()) {
URI literalType = toURI(em, type);
if (literalType != null) {
newValue = new Literal(valueText.getText(), literalType);
} else {
// unknown literal type
}
}
if (newValue == null) {
newValue = valueText.getText();
}
URI prop = toURI(em, pText.getText().trim());
if (prop != null) {
if (!prop.equals(stmt.getPredicate())) {
stmt = new Statement(stmt.getSubject(), prop, null);
}
CommandResult result = valueHelper.setValue(stmt,
((IEntity) stmt.getSubject()).getEntityManager(),
newValue);
if (result.getStatus().isOK()
&& result.getReturnValue() != null) {
stmt = new Statement(stmt.getSubject(),
stmt.getPredicate(), result.getReturnValue());
}
}
}
setDirty(false);
}
@Override
public void refresh() {
addPattern = null;
IAdapterFactory newAdapterFactory = getAdapterFactory();
if (adapterFactory == null
|| !adapterFactory.equals(newAdapterFactory)) {
adapterFactory = newAdapterFactory;
if (labelProvider != null) {
labelProvider.dispose();
labelProvider = null;
}
if (adapterFactory != null) {
labelProvider = new AdapterFactoryLabelProvider(
adapterFactory);
}
}
updateListener();
boolean enabled = labelProvider != null && stmt != null;
valueText.setEnabled(enabled);
pText.setEnabled(enabled);
if (enabled) {
sLabel.setText(ModelUtil.getLabel(stmt.getSubject()));
sLabel.setImage(labelProvider.getImage(stmt.getSubject()));
if (stmt.getPredicate() != null) {
pText.setText(labelProvider.getText(stmt.getPredicate()));
pIcon.setImage(labelProvider.getImage(stmt.getPredicate()));
} else {
pText.setText("");
pIcon.setImage(null);
}
Object value = stmt.getObject();
valueText.setText(labelProvider.getText(value));
if (value instanceof ILiteral) {
ILiteral literal = (ILiteral) value;
langText.setText(literal.getLanguage() == null ? ""
: literal.getLanguage());
typeText.setText(literal.getDatatype() == null ? ""
: labelProvider.getText(((IEntity) stmt
.getSubject()).getEntityManager().find(
literal.getDatatype())));
} else {
langText.setText("");
typeText.setText("");
}
langText.setEnabled(!(value instanceof IReference));
typeText.setEnabled(!(value instanceof IReference));
} else {
langText.setEnabled(false);
typeText.setEnabled(false);
}
acceptedResourceProposal = null;
super.refresh();
}
protected void updateListener() {
if (stmt != null && stmt.getSubject() instanceof IModelAware) {
IModelSet stmtModelSet = ((IModelAware) (stmt.getSubject()))
.getModel().getModelSet();
if (modelSet == null || !modelSet.equals(stmtModelSet)) {
if (modelSet != null) {
modelSet.removeListener(this);
}
stmtModelSet.addListener(this);
modelSet = stmtModelSet;
}
} else if (modelSet != null) {
modelSet.removeListener(this);
modelSet = null;
}
}
@Override
public void setDirty(boolean dirty) {
if (okButton != null) {
okButton.setEnabled(dirty);
}
super.setDirty(dirty);
}
@Override
public void dispose() {
if (modelSet != null) {
modelSet.removeListener(this);
}
}
protected IStatementPattern addPattern;
@Override
public void notifyChanged(
Collection<? extends INotification> notifications) {
if (stmt != null) {
for (INotification notification : notifications) {
IStatementNotification n = (IStatementNotification) notification;
if (!n.isAdd()) {
if (n.getStatement().equalsIgnoreContext(stmt)) {
addPattern = new StatementPattern(
stmt.getSubject(), stmt.getPredicate(),
null);
}
} else if (addPattern != null
&& Statements.matchesIgnoreContext(
n.getStatement(), addPattern)) {
stmt = resolve(
((IEntity) stmt.getSubject())
.getEntityManager(),
n.getStatement());
setStale(true);
getForm().refreshStale();
return;
}
}
}
}
protected IStatement resolve(IEntityManager em, IStatement stmt) {
Object obj = stmt.getObject();
if (obj instanceof IReference) {
obj = em.find((IReference) obj);
}
return new Statement(em.find(stmt.getSubject()), em.find(stmt
.getPredicate()), obj);
}
@Override
public NotificationFilter<INotification> getFilter() {
return NotificationFilter.instanceOf(IStatementNotification.class);
}
}
public StatementView() {
setEditPart(new StatementPart());
}
}