// ============================================================================
//
// Copyright (C) 2006-2016 Talend Inc. - www.talend.com
//
// This source code is available under agreement available at
// %InstallDIR%\features\org.talend.rcp.branding.%PRODUCTNAME%\%PRODUCTNAME%license.txt
//
// You should have received a copy of the agreement
// along with this program; if not, write to Talend SA
// 9 rue Pages 92150 Suresnes, France
//
// ============================================================================
package com.amalto.workbench.detailtabs.sections.handlers;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDFactory;
import org.eclipse.xsd.XSDIdentityConstraintCategory;
import org.eclipse.xsd.XSDIdentityConstraintDefinition;
import org.eclipse.xsd.XSDXPathDefinition;
import org.eclipse.xsd.XSDXPathVariety;
import org.eclipse.xsd.util.XSDSchemaBuildingTools;
import com.amalto.workbench.detailtabs.exception.CommitException;
import com.amalto.workbench.detailtabs.exception.CommitValidationException;
import com.amalto.workbench.detailtabs.sections.model.entity.EntityWrapper;
import com.amalto.workbench.detailtabs.sections.model.entity.FieldWrapper;
import com.amalto.workbench.detailtabs.sections.model.entity.KeyWrapper;
import com.amalto.workbench.i18n.Messages;
import com.amalto.workbench.providers.datamodel.SchemaTreeContentProvider;
import com.amalto.workbench.utils.Util;
public class EntityCommitHandler extends CommitHandler<EntityWrapper> {
private static final String ERR_ENTITY_NULLENTITYNAME = Messages.EntityCommitHandler_EntityNameCannotbeEmpty;
private static final String ERR_ENTITY_CONTAINEMPTY = Messages.EntityCommitHandler_EntityNameCannotContainEmpty;
private static final String ERR_ENTITY_DULPLICATEENTITYNAME = Messages.EntityCommitHandler_EntityNameExist;
private static final String ERR_KEY_NULLKEYNAME = Messages.EntityCommitHandler_KeyNameCannotbeEmpty;
private static final String ERR_KEY_CONTAINEMPTY = Messages.EntityCommitHandler_KeyNameCannotContainEmpty;
private static final String ERR_KEY_DUPLICATEKEYNAME = Messages.EntityCommitHandler_KeyNameExist;
private static final String ERR_KEY_NOFIELDS = Messages.EntityCommitHandler_MustAtLeastOnField;
private static final String ERR_KEY_MULTIUNIQUE = Messages.EntityCommitHandler_AtMostUniqueKey;
private static final String ERR_SELECTOR_WRONGFORMAT = Messages.EntityCommitHandler_KeySelectorInWrongFormat;
private static final String ERR_FIELD_WRONGFORMAT = Messages.EntityCommitHandler_KeyFieldInWrongFormat;
public EntityCommitHandler(EntityWrapper entityWrapper) {
super(entityWrapper);
}
@Override
protected boolean doSubmit() throws CommitException {
try {
return (commitEntityName() | commitEnitityKeys());
} catch (Exception e) {
throw new CommitException(e.getMessage(), e);
}
}
@Override
protected void validateCommit() throws CommitValidationException {
validateEntityName();
validateEntityKeys();
}
private boolean commitEntityName() {
XSDElementDeclaration xsdElementDeclaration = getCommitedObj().getSourceEntity();
String oldName = xsdElementDeclaration.getName();
if (oldName.equals(getCommitedObj().getName())) {
return false;
}
xsdElementDeclaration.setName(getCommitedObj().getName());
xsdElementDeclaration.updateElement();
updateReferenceForNewName(xsdElementDeclaration, oldName);
// to correct unique's name
for (Object idConsObj : xsdElementDeclaration.getIdentityConstraintDefinitions()) {
XSDIdentityConstraintDefinition idCons = (XSDIdentityConstraintDefinition) idConsObj;
if (idCons.getName().equals(oldName)) {
idCons.setName(xsdElementDeclaration.getName());
idCons.updateElement();
break;
}
}
return true;
}
private void updateReferenceForNewName(XSDElementDeclaration xsdElementDeclaration, String oldName) {
IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IWorkbenchPartSite site = activePage.getActivePart().getSite();
SchemaTreeContentProvider contentProvider = new SchemaTreeContentProvider(site, getCommitedObj().getSchema());
Object[] objs = Util.getAllObject(site, new ArrayList<Object>(), contentProvider);
Object[] allForeignKeyAndInfos = Util.getAllForeignKeyRelatedInfos(site, new ArrayList<Object>(), contentProvider,
new HashSet<Object>());
Util.updateReference(xsdElementDeclaration, objs, allForeignKeyAndInfos, oldName, getCommitedObj().getName());
}
private boolean commitEnitityKeys() {
return commitKeyRemoval() | commitKeyUpdate() | commitKeyAddition();
}
private boolean commitKeyRemoval() {
boolean hasChanges = false;
for (XSDIdentityConstraintDefinition eachNeedRemovedKey : getNeedRemovedKeys()) {
getCommitedObj().getSourceEntity().getIdentityConstraintDefinitions().remove(eachNeedRemovedKey);
getCommitedObj().getSourceEntity().updateElement();
hasChanges = true;
}
return hasChanges;
}
private boolean commitKeyUpdate() {
boolean hasChanges = false;
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
if (eachKeyWrapper.isUserCreated()) {
continue;
}
hasChanges = hasChanges | commitKeyUpdate_Selector(eachKeyWrapper) | commitKeyUpdate_Fields(eachKeyWrapper);
}
return hasChanges;
}
private boolean commitKeyAddition() {
boolean hasChanges = false;
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
if (!eachKeyWrapper.isUserCreated()) {
continue;
}
hasChanges = true;
XSDFactory factory = XSDSchemaBuildingTools.getXSDFactory();
XSDIdentityConstraintDefinition newKey = factory.createXSDIdentityConstraintDefinition();
newKey.setName(eachKeyWrapper.getName());
newKey.setIdentityConstraintCategory(eachKeyWrapper.getType());
XSDXPathDefinition selector = factory.createXSDXPathDefinition();
selector.setValue(eachKeyWrapper.getSelector());
selector.setVariety(XSDXPathVariety.SELECTOR_LITERAL);
newKey.setSelector(selector);
for (FieldWrapper newFields : eachKeyWrapper.getFields()) {
XSDXPathDefinition field = factory.createXSDXPathDefinition();
field.setValue(newFields.getXPath());
field.setVariety(XSDXPathVariety.FIELD_LITERAL);
newKey.getFields().add(field);
}
getCommitedObj().getSourceEntity().getIdentityConstraintDefinitions().add(newKey);
getCommitedObj().getSourceEntity().updateElement();
}
return hasChanges;
}
private boolean commitKeyUpdate_Selector(KeyWrapper keyWrapper) {
if (keyWrapper.getSourceKey().getSelector().getValue().equals(keyWrapper.getSelector())) {
return false;
}
XSDXPathDefinition newXpath = XSDSchemaBuildingTools.getXSDFactory().createXSDXPathDefinition();
newXpath.setValue(keyWrapper.getSelector());
newXpath.setVariety(XSDXPathVariety.SELECTOR_LITERAL);
keyWrapper.getSourceKey().setSelector(newXpath);
keyWrapper.getSourceKey().updateElement();
return true;
}
private boolean commiKeyUpdate_Name(KeyWrapper keyWrapper) {
if (keyWrapper.getSourceKey().getName().equals(keyWrapper.getName())) {
return false;
}
keyWrapper.getSourceKey().setName(keyWrapper.getName());
keyWrapper.getSourceKey().updateElement();
return true;
}
private boolean commitKeyUpdate_Fields(KeyWrapper keyWrapper) {
return commitKeyUpdate_Fields_Removal(keyWrapper) | commitKeyUpdate_Fields_Update(keyWrapper)
| commitKeyUpdate_Fields_Addition(keyWrapper);
}
private boolean commitKeyUpdate_Fields_Removal(KeyWrapper keyWrapper) {
boolean hasChanges = false;
for (XSDXPathDefinition eachNeedRemovedField : getNeedRemovedFields(keyWrapper)) {
keyWrapper.getSourceKey().getFields().remove(eachNeedRemovedField);
keyWrapper.getSourceKey().updateElement();
hasChanges = true;
}
return hasChanges;
}
private boolean commitKeyUpdate_Fields_Update(KeyWrapper keyWrapper) {
boolean hasChanges = false;
for (FieldWrapper eachField : keyWrapper.getFields()) {
if (eachField.isUserCreated()) {
continue;
}
if (eachField.getSourceField().getValue().equals(eachField.getXPath())) {
continue;
}
eachField.getSourceField().setValue(eachField.getXPath());
eachField.getSourceField().updateElement();
hasChanges = true;
}
return hasChanges;
}
private boolean commitKeyUpdate_Fields_Addition(KeyWrapper keyWrapper) {
boolean hasChanges = false;
for (FieldWrapper eachField : keyWrapper.getFields()) {
if (!eachField.isUserCreated()) {
continue;
}
XSDXPathDefinition newXpath = XSDSchemaBuildingTools.getXSDFactory().createXSDXPathDefinition();
newXpath.setValue(eachField.getXPath());
newXpath.setVariety(XSDXPathVariety.FIELD_LITERAL);
keyWrapper.getSourceKey().getFields().add(newXpath);
keyWrapper.getSourceKey().updateElement();
hasChanges = true;
}
return hasChanges;
}
private XSDXPathDefinition[] getNeedRemovedFields(KeyWrapper keyWrapper) {
List<XSDXPathDefinition> curLeftFields = new ArrayList<XSDXPathDefinition>();
List<XSDXPathDefinition> needRemovedFields = new ArrayList<XSDXPathDefinition>();
for (FieldWrapper eachField : keyWrapper.getFields()) {
if (!eachField.isUserCreated()) {
curLeftFields.add(eachField.getSourceField());
}
}
for (XSDXPathDefinition eachSourceField : keyWrapper.getSourceKey().getFields()) {
if (!curLeftFields.contains(eachSourceField)) {
needRemovedFields.add(eachSourceField);
}
}
return needRemovedFields.toArray(new XSDXPathDefinition[0]);
}
private XSDIdentityConstraintDefinition[] getNeedRemovedKeys() {
List<XSDIdentityConstraintDefinition> curLeftSourceKeys = new ArrayList<XSDIdentityConstraintDefinition>();
List<XSDIdentityConstraintDefinition> needRemovedKeys = new ArrayList<XSDIdentityConstraintDefinition>();
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
if (!eachKeyWrapper.isUserCreated()) {
curLeftSourceKeys.add(eachKeyWrapper.getSourceKey());
}
}
for (XSDIdentityConstraintDefinition eachSourceKey : getCommitedObj().getSourceEntity()
.getIdentityConstraintDefinitions()) {
if (!curLeftSourceKeys.contains(eachSourceKey)) {
needRemovedKeys.add(eachSourceKey);
}
}
return needRemovedKeys.toArray(new XSDIdentityConstraintDefinition[0]);
}
private void validateEntityName() throws CommitValidationException {
if (getCommitedObj().getName() == null || "".equals(getCommitedObj().getName().trim())) {//$NON-NLS-1$
throw new CommitValidationException(ERR_ENTITY_NULLENTITYNAME);
}
if (getCommitedObj().getName().replaceAll("\\s", "").length() != getCommitedObj().getName().length()) {
throw new CommitValidationException(ERR_ENTITY_CONTAINEMPTY);
}
for (XSDElementDeclaration eachElement : getCommitedObj().getSchema().getElementDeclarations()) {
if (eachElement.equals(getCommitedObj().getSourceEntity())) {
continue;
}
if (eachElement.getName().equalsIgnoreCase(getCommitedObj().getName())) {
throw new CommitValidationException(ERR_ENTITY_DULPLICATEENTITYNAME + " : " + getCommitedObj().getName());//$NON-NLS-1$
}
}
}
private void validateEntityKeys() throws CommitValidationException {
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
validateEachKey(eachKeyWrapper);
}
validateKeyUnique();
validateDuplicateKeyNameInEntityWrapper();
}
private void validateKeyUnique() throws CommitValidationException {
int uniqueKeyCount = 0;
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
if (eachKeyWrapper.getType() == XSDIdentityConstraintCategory.UNIQUE_LITERAL) {
uniqueKeyCount++;
}
}
if (uniqueKeyCount > 1) {
throw new CommitValidationException(ERR_KEY_MULTIUNIQUE);
}
}
private void validateDuplicateKeyNameInEntityWrapper() throws CommitValidationException {
Set<String> keyWrapperNames = new HashSet<String>();
for (KeyWrapper eachKeyWrapper : getCommitedObj().getKeys()) {
keyWrapperNames.add(eachKeyWrapper.getName());
}
if (keyWrapperNames.size() != getCommitedObj().getKeys().length) {
throw new CommitValidationException(ERR_KEY_DUPLICATEKEYNAME);
}
}
private void validateEachKey(KeyWrapper checkedKeyWrapper) throws CommitValidationException {
validateEachKeyName(checkedKeyWrapper);
validateEachKeySelector(checkedKeyWrapper);
validateEachKeyFieldsCount(checkedKeyWrapper);
for (FieldWrapper eachFieldWrapper : checkedKeyWrapper.getFields()) {
validateEachField(checkedKeyWrapper, eachFieldWrapper);
}
}
private void validateEachKeyName(KeyWrapper checkedKeyWrapper) throws CommitValidationException {
if (checkedKeyWrapper.getName() == null || "".equals(checkedKeyWrapper.getName().trim())) {//$NON-NLS-1$
throw new CommitValidationException(ERR_KEY_NULLKEYNAME);
}
if (checkedKeyWrapper.getName().replaceAll("\\s", "").length() != checkedKeyWrapper.getName().length()) {//$NON-NLS-1$//$NON-NLS-2$
throw new CommitValidationException(ERR_KEY_CONTAINEMPTY);
}
for (XSDIdentityConstraintDefinition eachId : getCommitedObj().getSchema().getIdentityConstraintDefinitions()) {
if (eachId.equals(checkedKeyWrapper.getSourceKey())
|| eachId.getContainer().equals(getCommitedObj().getSourceEntity())) {
continue;
}
if (eachId.getName().equals(checkedKeyWrapper.getName())) {
throw new CommitValidationException(ERR_KEY_DUPLICATEKEYNAME + " : " + checkedKeyWrapper.getName());//$NON-NLS-1$
}
}
}
private void validateEachKeySelector(KeyWrapper checkedKeyWrapper) throws CommitValidationException {
if (checkedKeyWrapper.getSelector() == null || "".equals(checkedKeyWrapper.getSelector().trim())) {//$NON-NLS-1$
throw new CommitValidationException(ERR_SELECTOR_WRONGFORMAT + " : key " + checkedKeyWrapper.getName());//$NON-NLS-1$
}
}
private void validateEachKeyFieldsCount(KeyWrapper checkedKeyWrapper) throws CommitValidationException {
if (checkedKeyWrapper.getFields().length == 0) {
throw new CommitValidationException(ERR_KEY_NOFIELDS + " : key " + checkedKeyWrapper.getName());//$NON-NLS-1$
}
}
private void validateEachField(KeyWrapper checkedKeyWrapper, FieldWrapper eachFieldWrapper) throws CommitValidationException {
if (eachFieldWrapper.getXPath() == null || "".equals(eachFieldWrapper.getXPath().trim())) {//$NON-NLS-1$
throw new CommitValidationException(ERR_FIELD_WRONGFORMAT + " : key " + checkedKeyWrapper.getName());//$NON-NLS-1$
}
}
}