/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.xsd.ui.editor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.dialogs.ListDialog;
import org.eclipse.xsd.XSDConstrainingFacet;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleFinal;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.TransactionRunnable;
import org.teiid.designer.core.search.MetadataSearch;
import org.teiid.designer.core.transaction.UnitOfWork;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.metamodels.xsd.XsdUtil;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.common.util.UiUtil;
import org.teiid.designer.ui.forms.ComponentCategory;
import org.teiid.designer.ui.forms.ComponentSetEvent;
import org.teiid.designer.ui.forms.ComponentSetMonitor;
import org.teiid.designer.ui.forms.LinkedComponentSet;
import org.teiid.designer.ui.views.DatatypeHierarchyView;
import org.teiid.designer.ui.viewsupport.ModelObjectUtilities;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.xsd.ui.ModelerXsdUiConstants;
/**
* The FacetModel is an insulating layer above metadata, and serves as the underlying model for the SDE View.
*
* @since 8.0
*/
public class FacetModel implements ComponentSetMonitor{
static final String TITLE_BASE_NOT_ALLOWED = GUIFacetHelper.getString("FacetModel.title_BaseNotAllowed"); //$NON-NLS-1$
static final String DESC_BASE_NOT_ALLOWED_SAME = GUIFacetHelper.getString("FacetModel.desc_BaseNotAllowedSame"); //$NON-NLS-1$
static final String DESC_BASE_NOT_ALLOWED_CHILD = GUIFacetHelper.getString("FacetModel.desc_BaseNotAllowedChild"); //$NON-NLS-1$
private ComponentCategory[] ccats = GUIFacetHelper.getCategories(this);
XSDSimpleTypeDefinition simpleType;
boolean isReadOnly;
boolean editorIsReadOnly;
boolean ignoreEvents;
private Map idToFacet = new HashMap();
private Map idToCategory = new HashMap();
XSDSchema schema;
public FacetModel() {
// hook myself up to all the LCSs:
for (int i = 0; i < ccats.length; i++) {
ComponentCategory cat = ccats[i];
cat.setMonitor(this);
idToCategory.put(cat.getID(), cat);
// set up a quick mapping so I can easily update fields:
Iterator itor = cat.getComponentSets().iterator();
while (itor.hasNext()) {
LinkedComponentSet set = (LinkedComponentSet)itor.next();
idToFacet.put(set.getID(), set);
} // endwhile
} // endfor
}
public ComponentCategory[] getCategories() {
return ccats;
}
public XSDSimpleTypeDefinition getSimpleType() {
return simpleType;
}
public void setSchema( XSDSchema schema ) {
this.schema = schema;
LinkedComponentSet lcs = getComponentSet(GUIFacetHelper.FAKE_FACET_NAMESPACE);
lcs.setValue(schema.getTargetNamespace());
// enable editing of the targ namespace if possible:
boolean readOnly;
ModelResource mRes = ModelUtilities.getModelResourceForModelObject(schema);
if (mRes != null) {
readOnly = mRes.isReadOnly();
} else {
readOnly = true;
} // endif
lcs.setEditible(readOnly);
}
public void setSimpleType( XSDSimpleTypeDefinition simpleType ) {
this.simpleType = null; // don't update last selection any longer
ignoreEvents = true;
// get readonly state:
determineReadOnly(simpleType);
// set fields:
if (simpleType != null) {
// clear the fields and set new data in:
clear();
setFields(simpleType);
// show/hide facets:
resetDisplayedCategories(simpleType);
} else {
// hide things, don't bother clearing:
getCategory(GUIFacetHelper.CATEGORY_ID).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_INHERITANCE).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_ENTERPRISE).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_BOUNDS).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_NUMERIC).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_FORMAT).setVisible(false);
getCategory(GUIFacetHelper.CATEGORY_LENGTH).setVisible(false);
} // endif
ignoreEvents = false;
this.simpleType = simpleType;
setGUIReadOnly(isReadOnly);
}
void resetDisplayedCategories( XSDSimpleTypeDefinition simpleType ) {
boolean needsNumeric = FacetHelper.needsNumeric(simpleType);
boolean needsBounds = FacetHelper.needsBounds(simpleType);
// boolean nn2 = simpleType.getNumericFacet().isValue();
// boolean nb2 = simpleType.getBoundedFacet().isValue();
// show main things:
getCategory(GUIFacetHelper.CATEGORY_ID).setVisible(true);
getCategory(GUIFacetHelper.CATEGORY_INHERITANCE).setVisible(true);
getCategory(GUIFacetHelper.CATEGORY_ENTERPRISE).setVisible(true);
// show other things:
getCategory(GUIFacetHelper.CATEGORY_BOUNDS).setVisible(needsBounds);
getCategory(GUIFacetHelper.CATEGORY_NUMERIC).setVisible(needsNumeric);
getCategory(GUIFacetHelper.CATEGORY_FORMAT).setVisible(!needsBounds); // because anything needing bounds is not string
getCategory(GUIFacetHelper.CATEGORY_LENGTH).setVisible(!needsBounds); // because anything needing bounds is not string
}
private void determineReadOnly( XSDSimpleTypeDefinition simpleType ) {
ModelResource mRes = ModelUtilities.getModelResourceForModelObject(simpleType);
if (mRes != null) {
isReadOnly = mRes.isReadOnly();
} else {
isReadOnly = true;
} // endif
ModelResource schemaModelResource = ModelUtilities.getModelResourceForModelObject(this.schema);
if( schemaModelResource != null ) {
setEditorReadOnly(schemaModelResource.isReadOnly());
}
}
public boolean isReadOnly() {
return isReadOnly;
}
public void setGUIReadOnly( boolean ro ) {
// set proper readonly state:
determineReadOnly(simpleType);
if (ro == true // can always set to read only
|| isReadOnly == false) { // but only allow writing if isRO says so.
// loop through all categories:
for (int i = 0; i < ccats.length; i++) {
ComponentCategory cat = ccats[i];
cat.setEnabled(!ro);
} // endfor
} // endif
}
void setEditorReadOnly(boolean editorIsReadOnly) {
this.editorIsReadOnly = editorIsReadOnly;
}
boolean isEditorReadOnly() {
return this.editorIsReadOnly;
}
void setFields( XSDSimpleTypeDefinition simpleType ) {
boolean prevIgnore = ignoreEvents;
ignoreEvents = true;
// ID:
getComponentSet(GUIFacetHelper.FAKE_FACET_NAME).setValue(simpleType.getName());
getComponentSet(GUIFacetHelper.FAKE_FACET_NAMESPACE).setValue(simpleType.getTargetNamespace());
getComponentSet(GUIFacetHelper.FAKE_FACET_DESCRIPTION).setValue(CoreStringUtil.collapseWhitespace(ModelObjectUtilities.getDescription(simpleType)));
// Inherit:
getComponentSet(GUIFacetHelper.FAKE_FACET_BASETYPE).setValue(simpleType.getBaseTypeDefinition());
getComponentSet(GUIFacetHelper.GROUP_INHERITANCE_LINKS_AND_PREVENT).setValue(new Object[] {simpleType,
getStringFinals(simpleType.getLexicalFinal())});
// Enterprise:
FacetValue entFV = FacetHelper.getEnterpriseFacetValue(simpleType);
final boolean isEnterprise = ModelerCore.getWorkspaceDatatypeManager().isEnterpriseDatatype(simpleType);
getComponentSet(GUIFacetHelper.FAKE_FACET_ENTERPRISE).setValue(new Boolean(isEnterprise));
final LinkedComponentSet entcs = getComponentSet(GUIFacetHelper.FAKE_FACET_RUNTIME);
entcs.setValue(entFV);
// change editible state later:
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
entcs.setEditible(isEnterprise && !isReadOnly);
}
});
// Other facets:
Set setFacets = FacetHelper.getUsefulFacets(simpleType);
Set multisToRefresh = new HashSet();
Iterator itor = setFacets.iterator();
while (itor.hasNext()) {
EObject eobj = (EObject)itor.next();
if (!(eobj instanceof XSDConstrainingFacet)) {
continue;
} // endif
XSDConstrainingFacet facet = (XSDConstrainingFacet)eobj;
String facetID = FacetHelper.getFacetName(facet);
LinkedComponentSet lcs = getComponentSet(facetID);
if (lcs != null) {
FacetValue fv = FacetHelper.getFacetValue(simpleType, facet);
if (lcs instanceof MultiFacetSet) {
// enum or pattern:
MultiFacetSet mfs = (MultiFacetSet)lcs;
mfs.addValue(fv, false);
multisToRefresh.add(mfs);
} else {
// just a single dude:
lcs.setValue(fv);
} // endif -- multi
} // endif -- component set present
} // endwhile -- over useful facet set
itor = multisToRefresh.iterator();
while (itor.hasNext()) {
MultiFacetSet mfs = (MultiFacetSet)itor.next();
mfs.reflow();
} // endwhile
ignoreEvents = prevIgnore;
}
void clear() {
// unset fields:
Iterator itor = idToFacet.values().iterator();
while (itor.hasNext()) {
LinkedComponentSet lcs = (LinkedComponentSet)itor.next();
// never clear namespace:
if (lcs.getID() != GUIFacetHelper.FAKE_FACET_NAMESPACE) {
lcs.setValue(null);
} // endif
} // endwhile
}
LinkedComponentSet getComponentSet( String facetID ) {
// translate to proper facet id:
if (facetID == FacetHelper.FACET_MAX_EXCLUSIVE || facetID == FacetHelper.FACET_MAX_INCLUSIVE) {
facetID = FacetHelper.FAKE_FACET_MAXIMUM;
} else if (facetID == FacetHelper.FACET_MIN_EXCLUSIVE || facetID == FacetHelper.FACET_MIN_INCLUSIVE) {
facetID = FacetHelper.FAKE_FACET_MINIMUM;
} // endif
// get the LCS:
return (LinkedComponentSet)idToFacet.get(facetID);
}
private ComponentCategory getCategory( String catID ) {
return (ComponentCategory)idToCategory.get(catID);
}
private static Collection getStringFinals( Collection simpleFinals ) {
Collection rv = new ArrayList(simpleFinals.size());
Iterator itor = simpleFinals.iterator();
while (itor.hasNext()) {
XSDSimpleFinal fin = (XSDSimpleFinal)itor.next();
rv.add(fin.getName());
} // endwhile
return rv;
}
@Override
public void update( final ComponentSetEvent event ) {
if (!ignoreEvents && simpleType != null) {
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) {
final String id = event.componentSet.getID();
if (event.value instanceof FacetValue && !GUIFacetHelper.FAKE_FACET_RUNTIME.equals(id)) {
FacetValue fv = (FacetValue)event.value;
// see if we need to do an extra dereference (Table support)
if (fv.value instanceof FacetValue) {
fv = (FacetValue)fv.value;
} // endif
// need to add, edit, or remove?
if (event.isDelete) {
// may need to remove, if we have a facet:
if (fv.facet != null) {
// remove:
FacetHelper.removeFacet(simpleType, fv.facet);
fv.clear();
} // endif
} else {
// add or edit:
fv.facet = FacetHelper.addOrSetFacetValue(simpleType, id, fv);
} // endif
} else {
// must have come from one of the fundamental things:
// switch on ID:
if (GUIFacetHelper.FAKE_FACET_NAME == id) { // ----------------------------------------------
ModelObjectUtilities.rename(simpleType, (String)event.value, this);
} else if (GUIFacetHelper.FAKE_FACET_NAMESPACE == id) { // ----------------------------------
XsdUtil.setTargetNamespace((XSDSchema)ModelObjectUtilities.getRealEObject(simpleType.getSchema()),
(String)event.value);
// force the base type component to pick up the change, if applicable:
LinkedComponentSet baseType = getComponentSet(GUIFacetHelper.FAKE_FACET_BASETYPE);
baseType.setValue(null);
baseType.setValue(simpleType.getBaseTypeDefinition());
} else if (GUIFacetHelper.FAKE_FACET_PREVENT_RESTRICTIONS == id) { // -----------------------
// get the monitored list:
List current = simpleType.getLexicalFinal();
// clear the current settings:
current.clear();
// iterate through all selected:
Set newVals = (Set)event.value;
Iterator itor = newVals.iterator();
while (itor.hasNext()) {
String element = (String)itor.next();
current.add(XSDSimpleFinal.get(element));
} // endwhile
} else if (GUIFacetHelper.FAKE_FACET_RUNTIME == id) { // ------------------------------------
FacetValue fv = (FacetValue)event.value;
FacetHelper.setEnterpriseFacetValue(simpleType, fv);
} else if (GUIFacetHelper.FAKE_FACET_ENTERPRISE == id) { // ---------------------------------
// enable/disable things as needed:
boolean isEnterprise = ((Boolean)event.value).booleanValue();
LinkedComponentSet rtlcs = getComponentSet(GUIFacetHelper.FAKE_FACET_RUNTIME);
rtlcs.setEditible(isEnterprise);
if (isEnterprise) {
// we are enterprise, set:
FacetHelper.setEnterpriseFacetValue(simpleType, ((AbstractFacetSet)rtlcs).getFacetValue());
} else {
// not enterprise, remove:
ModelerCore.getModelEditor().unsetEnterpriseDatatypePropertyValue(simpleType);
} // endif
} else if (GUIFacetHelper.FAKE_FACET_BASETYPE == id) { // -----------------------------------
XSDSimpleTypeDefinition newBaseType = (XSDSimpleTypeDefinition)event.value;
if (newBaseType == simpleType) {
// we do not allow the base type to be the same as the current type:
event.doit = false;
MessageDialog.openError(null, TITLE_BASE_NOT_ALLOWED, DESC_BASE_NOT_ALLOWED_SAME);
} else if (FacetHelper.isSubtypeOf(newBaseType, simpleType)) {
// we do not allow subtypes to be set as base types:
event.doit = false;
MessageDialog.openError(null, TITLE_BASE_NOT_ALLOWED, DESC_BASE_NOT_ALLOWED_CHILD);
} else {
ModelerCore.getDatatypeManager(simpleType).setBasetypeDefinition(simpleType, newBaseType);
// reread everything, so that we can get new info, including new inherited facets:
ignoreEvents = true;
clear();
// show/hide facets:
resetDisplayedCategories(simpleType);
setFields(simpleType);
ignoreEvents = false;
} // endif
} else if (GUIFacetHelper.FAKE_FACET_DESCRIPTION == id) { // --------------------------------
ModelObjectUtilities.setDescription(simpleType, (String)event.value, this);
} else if (GUIFacetHelper.FAKE_FACET_CREATE_SUBTYPE == id) { // -----------------------------
// We need to check the read-only state of the datatypes editor, rather than the "selected datatype"
// This will allow creating a sub-type of a built-in datatype that IS read-only
if( isEditorReadOnly() ) {
MessageDialog.openConfirm(null, ModelerXsdUiConstants.Util.getString("FacetModel.read_only.title"), //$NON-NLS-1$
ModelerXsdUiConstants.Util.getString("FacetModel.read_only.cannotCreateSubtypeMessage")); //$NON-NLS-1$
return null;
}
final XSDSimpleTypeDefinition newType = GUIFacetHelper.createType(schema, simpleType);
if (newType != null) {
uow.setDescription(ModelerXsdUiConstants.Util.getString("FacetModel.transaction_create", newType.getName())); //$NON-NLS-1$
uow.setSource(schema);
Display.getDefault().asyncExec(new Runnable() {
@Override
public void run() {
// run later to help selection work right:
GUIFacetHelper.showObject(newType);
}
});
} // endif
} else if (GUIFacetHelper.FAKE_FACET_FIND_SUBTYPES == id) {
MessageDialog.openInformation(null,
"Find subtypes", "find subtypes not implemented; specified was: " + event.value);//$NON-NLS-1$ //$NON-NLS-2$
} else if (GUIFacetHelper.FAKE_FACET_OPEN_HIERARCHY == id) {
try {
DatatypeHierarchyView datatypes = (DatatypeHierarchyView)UiUtil.getWorkbenchPage().showView(UiConstants.Extensions.DATATYPE_HIERARCHY_VIEW);
datatypes.revealType(simpleType);
} catch (PartInitException ex) {
ModelerXsdUiConstants.Util.log(ex);
} // endtry
} else if (GUIFacetHelper.FAKE_FACET_FIND_USES == id) {
MetadataSearch search = ModelerCore.createMetadataSearch();
search.setDatatype(simpleType, false);
search.execute(new NullProgressMonitor());
List resultsl = search.getResults();
ListDialog ld = new ListDialog(null) {
@Override
protected int getTableStyle() {
return SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
}
};
ld.setInput(resultsl);
ld.setAddCancelButton(true);
ld.setBlockOnOpen(true);
ld.setContentProvider(new ListSCP());
ld.setLabelProvider(ModelUtilities.getEMFLabelProvider());
ld.setMessage("Pat's zany message"); //$NON-NLS-1$
ld.setTitle("Pat's zany title"); //$NON-NLS-1$
ld.setInitialElementSelections(resultsl);
ld.open();
MessageDialog.openInformation(null,
"Find uses", "find uses not implemented; specified was: " + event.value);//$NON-NLS-1$ //$NON-NLS-2$
} // endif -- id switch
} // endif -- fake or real facet
return null;
}
}; // endanon transaction
try {
ModelerCore.getModelEditor().executeAsTransaction(runnable,
ModelerXsdUiConstants.Util.getString("FacetModel.Set_on_simple_data_type_properties"), true, true, this); //$NON-NLS-1$
} catch (ModelerCoreException mce) {
ModelerXsdUiConstants.Util.log(mce);
}
} // endif -- ignorable
}
//
// Inner classes:
//
public class ListSCP implements IStructuredContentProvider {
@Override
public Object[] getElements( Object inputElement ) {
if (inputElement != null) {
return ((Collection)inputElement).toArray();
} // endif
return new Object[0];
}
@Override
public void dispose() {
// ignore
}
@Override
public void inputChanged( Viewer viewer,
Object oldInput,
Object newInput ) {
// ignore
}
} // endclass ListSCP
}