/*******************************************************************************
* Copyright (c) 2011 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.obeonetwork.dsl.entityrelation.design.services.label;
import java.util.ArrayList;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.emf.ecore.EObject;
import org.obeonetwork.dsl.entityrelation.Attribute;
import org.obeonetwork.dsl.entityrelation.LogicalElement;
import org.obeonetwork.dsl.entityrelation.LogicalModel;
import org.obeonetwork.dsl.entityrelation.NamedElement;
import org.obeonetwork.dsl.entityrelation.util.EntityRelationSwitch;
import org.obeonetwork.dsl.typeslibrary.NativeType;
import org.obeonetwork.dsl.typeslibrary.NativeTypeKind;
import org.obeonetwork.dsl.typeslibrary.NativeTypesLibrary;
import org.obeonetwork.dsl.typeslibrary.TypeInstance;
import org.obeonetwork.dsl.typeslibrary.TypesLibrary;
import org.obeonetwork.dsl.typeslibrary.TypesLibraryFactory;
public class EntityRelationEditLabelServices extends EntityRelationSwitch<LogicalElement> {
private String editedLabelContent;
public LogicalElement editLogicalElementLabel(LogicalElement element, String editedLabelContent) {
this.editedLabelContent = editedLabelContent;
return doSwitch(element);
}
@Override
public LogicalElement caseAttribute(Attribute attribute) {
// the label can be in the form "attributeName : typeName (precision, length)"
int pos = editedLabelContent.indexOf(':');
if (pos != -1) {
String attributeName = editedLabelContent.substring(0, pos - 1).trim();
attribute.setName(attributeName);
String typeDef = editedLabelContent.substring(pos + 1).trim();
// Retrieve types libraries
LogicalModel logicalModel = getLogicalModel(attribute);
if (logicalModel != null) {
Collection<NativeTypesLibrary> nativeTypesLibraries = new ArrayList<NativeTypesLibrary>();
for (TypesLibrary library : logicalModel.getUsedLibraries()) {
if (library instanceof NativeTypesLibrary) {
nativeTypesLibraries.add((NativeTypesLibrary)library);
}
}
setType(attribute, typeDef, nativeTypesLibraries);
}
} else {
// there is only a name
return super.caseNamedElement(attribute);
}
return attribute;
}
private int getIntValue(String stringValue) {
int result;
try {
result = Integer.parseInt(stringValue);
} catch (NumberFormatException e) {
result = 0;
}
return result;
}
private void setType(Attribute attribute, String typeName, Collection<NativeTypesLibrary> typesLibraries) {
for (NativeTypesLibrary nativeTypesLibrary : typesLibraries) {
for (NativeType nativeType : nativeTypesLibrary.getNativeTypes()) {
String typePattern = getNativeTypePattern(nativeType);
String typeRegexPattern = null;
if (nativeType.getSpec() == NativeTypeKind.ENUM) {
typeRegexPattern = typePattern;
} else {
typeRegexPattern = typePattern.replace("%n", "(.*)");
typeRegexPattern = typeRegexPattern.replace("%p", "(.*)");
}
if (typeRegexPattern != null) {
Pattern ptn = null;
try {
ptn = Pattern.compile(typeRegexPattern, Pattern.CASE_INSENSITIVE);
} catch (Exception e){
// Do nothing, the loop will try the other types
}
if (ptn != null) {
Matcher matcher = ptn.matcher(typeName);
if (matcher.matches()) {
// Ensure there is a type instance
if (attribute.getType() == null || (attribute.getType() instanceof TypeInstance == false)) {
TypeInstance type = TypesLibraryFactory.eINSTANCE.createTypeInstance();
type.setNativeType(nativeType);
attribute.setType(type);
}
TypeInstance columnType = ((TypeInstance)attribute.getType());
columnType.setNativeType(nativeType);
switch(nativeType.getSpec()) {
case SIMPLE :
// Nothing special to do
return;
case LENGTH :
// Retrieve length
String lengthString = matcher.group(1).trim();
// Ensure its a string representing an int
int length = getIntValue(lengthString);
columnType.setLength(length);
return;
case LENGTH_AND_PRECISION :
int nPos = typePattern.indexOf("%n");
int pPos = typePattern.indexOf("%p");
String nString = null;
String pString = null;
if (nPos < pPos) {
nString = matcher.group(1).trim();
nString = matcher.group(2).trim();
} else {
nString = matcher.group(2).trim();
pString = matcher.group(1).trim();
}
int nValue = getIntValue(nString);
int pValue = getIntValue(pString);
columnType.setLength(nValue);
columnType.setPrecision(pValue);
break;
case ENUM :
// Retrieves values
columnType.getLiterals().clear();
String valuesString = matcher.group(1).trim();
for (String value : valuesString.split(",")) {
columnType.getLiterals().add(value.trim());
}
return;
}
}
}
}
}
}
}
private String getNativeTypePattern(NativeType nativeType) {
String label = nativeType.getName();
label = label.replaceAll("\\(", "\\(");
label = label.replaceAll("\\)", "\\)");
switch(nativeType.getSpec()) {
case LENGTH :
if (!label.contains("%n")) {
return label + "\\(%n\\)";
}
break;
case LENGTH_AND_PRECISION :
if (!label.contains("%n") && !label.contains("%p")) {
return label + "\\(%n, %p\\)";
} else if (!label.contains("%n")) {
return label + "\\(%n\\)";
} else if (!label.contains("%p")) {
return label + "\\(%p\\)";
}
break;
case ENUM :
return label + "\\((.*)\\)";
}
return label;
}
private LogicalModel getLogicalModel(EObject object) {
if (object.eContainer() != null) {
if (object.eContainer() instanceof LogicalModel) {
return (LogicalModel)object.eContainer();
} else {
return getLogicalModel(object.eContainer());
}
}
return null;
}
@Override
public LogicalElement caseNamedElement(NamedElement object) {
object.setName(editedLabelContent);
return object;
}
}