blob: 228b43b42186a6352fcd4a82fe34edddb5d9628c [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2013 Tasktop Technologies and others.
* 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:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.reviews.connector;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.mylyn.tasks.core.TaskRepository;
import org.eclipse.mylyn.tasks.core.data.AbstractTaskSchema;
import org.eclipse.mylyn.tasks.core.data.DefaultTaskSchema;
import org.eclipse.mylyn.tasks.core.data.TaskAttribute;
import org.eclipse.mylyn.tasks.core.data.TaskAttributeMapper;
import org.eclipse.mylyn.tasks.core.data.TaskData;
public abstract class EmfTaskSchema extends AbstractTaskSchema {
public static final String TYPE_EMF_REFERENCE = "emf.reference"; //$NON-NLS-1$
public static final String TYPE_EMF_GENERIC = "emf.generic"; //$NON-NLS-1$
public static final String TYPE_EMF_UNSUPPORTED = "emf.unsupported"; //$NON-NLS-1$
private final DefaultTaskSchema parent = DefaultTaskSchema.getInstance();
public static class FieldFeature {
Field parentField;
EStructuralFeature feature;
Flag[] flags;
boolean readOnly;
public FieldFeature(Field taskAttribute, EStructuralFeature emfFeature) {
super();
this.parentField = taskAttribute;
this.feature = emfFeature;
}
public FieldFeature(Field taskAttribute, EStructuralFeature emfFeature, boolean readOnly, Flag... flags) {
this(taskAttribute, emfFeature);
this.readOnly = readOnly;
this.flags = flags;
}
@Override
public int hashCode() {
// ignore
return parentField.hashCode() * 31 + feature.hashCode();
}
@Override
public boolean equals(Object other) {
return other instanceof FieldFeature && ObjectUtils.equals(parentField, ((FieldFeature) other).parentField)
&& ObjectUtils.equals(feature, ((FieldFeature) other).feature);
}
}
private final Map<EStructuralFeature, Field> fieldByFeature = new HashMap<EStructuralFeature, Field>();
private final Map<String, EStructuralFeature> featureByTaskKey = new HashMap<String, EStructuralFeature>();
private boolean keyFieldDefined;
public void initialize() {
for (FieldFeature fieldFeature : getSchemaPairs()) {
if (fieldFeature.parentField.getKey() == parent.TASK_KEY.getKey()) {
keyFieldDefined = true;
break;
}
}
for (FieldFeature fieldFeature : getSchemaPairs()) {
createField(fieldFeature);
}
for (EClass schemaClass : getSchemaEClasses()) {
for (EStructuralFeature feature : schemaClass.getEAllStructuralFeatures()) {
//Don't replace explicitly mapped features.
if (isSupported(feature) && fieldByFeature.get(feature) == null) {
createField(feature);
}
}
}
}
@Override
public void initialize(TaskData taskData) {
if (!keyFieldDefined) {
DefaultTaskSchema.getInstance().TASK_KEY.createAttribute(taskData.getRoot());
}
for (Field field : getFields()) {
TaskAttribute attribute = field.createAttribute(taskData.getRoot());
EStructuralFeature feature = getFeature(attribute.getId());
if (feature instanceof EAttribute) {
EAttribute emfAttribute = (EAttribute) feature;
if (emfAttribute.getEAttributeType() instanceof EEnum) {
EEnum enumerator = (EEnum) emfAttribute.getEAttributeType();
for (EEnumLiteral literal : enumerator.getELiterals()) {
attribute.putOption(literal.getLiteral(), literal.getName());
}
}
}
}
}
protected abstract EClass[] getSchemaEClasses();
protected abstract FieldFeature[] getSchemaPairs();
public String getTaskType(EStructuralFeature feature) {
if (feature instanceof EReference) {
return TYPE_EMF_REFERENCE;
}
int classifierID = feature.getEType().getClassifierID();
switch (classifierID) {
case EcorePackage.EBIG_DECIMAL:
return TaskAttribute.TYPE_DOUBLE;
case EcorePackage.EBIG_INTEGER:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.EBOOLEAN:
return TaskAttribute.TYPE_BOOLEAN;
case EcorePackage.EBOOLEAN_OBJECT:
return TaskAttribute.TYPE_BOOLEAN;
case EcorePackage.EBYTE:
return TaskAttribute.TYPE_SHORT_TEXT;
case EcorePackage.EBYTE_OBJECT:
return TaskAttribute.TYPE_SHORT_TEXT;
case EcorePackage.ECHAR:
return TaskAttribute.TYPE_SHORT_TEXT;
case EcorePackage.ECHARACTER_OBJECT:
return TaskAttribute.TYPE_SHORT_TEXT;
case EcorePackage.EDATE:
return TaskAttribute.TYPE_DATE;
case EcorePackage.EDOUBLE:
return TaskAttribute.TYPE_DOUBLE;
case EcorePackage.EDOUBLE_OBJECT:
return TaskAttribute.TYPE_DOUBLE;
case EcorePackage.EFLOAT:
return TaskAttribute.TYPE_DOUBLE;
case EcorePackage.EFLOAT_OBJECT:
return TaskAttribute.TYPE_DOUBLE;
case EcorePackage.EINT:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.EINTEGER_OBJECT:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.ELONG:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.ELONG_OBJECT:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.ESHORT:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.ESHORT_OBJECT:
return TaskAttribute.TYPE_INTEGER;
case EcorePackage.ESTRING:
return TaskAttribute.TYPE_LONG_RICH_TEXT;
case EcorePackage.EBYTE_ARRAY:
return TYPE_EMF_GENERIC;
case EcorePackage.EDIAGNOSTIC_CHAIN:
return TYPE_EMF_UNSUPPORTED;
default:
return TYPE_EMF_UNSUPPORTED;
}
}
public boolean isSupported(EStructuralFeature feature) {
return !getTaskType(feature).startsWith("emf"); //$NON-NLS-1$
}
private void addEmfField(EStructuralFeature feature, Field field) {
fieldByFeature.put(feature, field);
featureByTaskKey.put(field.getKey(), feature);
}
protected Field createField(EStructuralFeature feature, Flag... flags) {
String key = getKey(feature);
String label = getLabel(feature);
String type = getTaskType(feature);
flags = (Flag[]) ArrayUtils.add(flags, Flag.ATTRIBUTE);
Field field = createField(key, label, type, key, flags);
addEmfField(feature, field);
return field;
}
protected Field createField(FieldFeature fieldFeature) {
Field parentField = fieldFeature.parentField;
EStructuralFeature emfAttribute = fieldFeature.feature;
String key = getKey(emfAttribute);
FieldFactory factory = inheritFrom(parentField).key(key);
if (fieldFeature.readOnly) {
factory.addFlags(Flag.READ_ONLY);
} else {
factory.removeFlags(Flag.READ_ONLY);
}
Field field = factory.create();
addEmfField(emfAttribute, field);
featureByTaskKey.put(parentField.getKey(), emfAttribute);
return field;
}
public String getKey(EStructuralFeature feature) {
return "emf." + feature.getEContainingClass().getEPackage().getName() + "." //$NON-NLS-1$//$NON-NLS-2$
+ feature.getEContainingClass().getName().toLowerCase() + "." + feature.getName().toLowerCase(); //$NON-NLS-1$
}
public String getLabel(EStructuralFeature feature) {
return WordUtils.capitalizeFully(StringUtils.join(StringUtils.splitByCharacterTypeCamelCase(feature.getName()),
' '));
}
/**
* Finds the feature corresponding to the supplied task key. Features are matched on both attributes and matched
* attributes.
*
* @param feature
* @return
*/
public EStructuralFeature getFeature(String key) {
return featureByTaskKey.get(key);
}
/**
* Finds the field corresponding to the given structural feature.
*
* @param feature
* @return
*/
public Field getFieldByFeature(EStructuralFeature feature) {
return fieldByFeature.get(feature);
}
public TaskAttributeMapper getAttributeMapper(TaskRepository repository) {
return new EmfAttributeMapper(this, repository);
}
}