All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.rhocas.featuregen.ap.FeatureIDEVariantProcessor Maven / Gradle / Ivy

There is a newer version: 2.0.0
Show newest version
package de.rhocas.featuregen.ap;

import com.google.common.base.Objects;
import de.rhocas.featuregen.ap.FeatureIDEFeatures;
import de.rhocas.featuregen.ap.FeatureIDEVariant;
import de.rhocas.featuregen.ap.FeatureNameConverter;
import de.rhocas.featuregen.ap.NameProvider;
import de.rhocas.featuregen.featureide.model.configuration.Configuration;
import de.rhocas.featuregen.featureide.model.configuration.Feature;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import org.eclipse.xtend.lib.macro.AbstractClassProcessor;
import org.eclipse.xtend.lib.macro.TransformationContext;
import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
import org.eclipse.xtend.lib.macro.declaration.EnumerationTypeDeclaration;
import org.eclipse.xtend.lib.macro.declaration.EnumerationValueDeclaration;
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
import org.eclipse.xtend.lib.macro.declaration.MutableConstructorDeclaration;
import org.eclipse.xtend.lib.macro.declaration.Type;
import org.eclipse.xtend.lib.macro.declaration.TypeReference;
import org.eclipse.xtend.lib.macro.declaration.Visibility;
import org.eclipse.xtend.lib.macro.file.FileSystemSupport;
import org.eclipse.xtend.lib.macro.file.Path;
import org.eclipse.xtend.lib.macro.services.AnnotationReferenceBuildContext;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtend2.lib.StringConcatenationClient;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Functions.Function0;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;

/**
 * This is the annotation processor for {@link FeatureIDEVariant}.
 * 
 * @author Nils Christian Ehmke
 * 
 * @since 1.0.0
 */
@SuppressWarnings("all")
public final class FeatureIDEVariantProcessor extends AbstractClassProcessor {
  @Extension
  private final NameProvider _nameProvider = new NameProvider();
  
  @Extension
  private final FeatureNameConverter _featureNameConverter = new FeatureNameConverter();
  
  private final JAXBContext jaxbContext = new Function0() {
    public JAXBContext apply() {
      try {
        JAXBContext _newInstance = JAXBContext.newInstance(Configuration.class);
        return _newInstance;
      } catch (Throwable _e) {
        throw Exceptions.sneakyThrow(_e);
      }
    }
  }.apply();
  
  @Override
  public void doTransform(final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    this.addPrivateConstructor(annotatedClass);
    this.makeFinal(annotatedClass);
    final Configuration configurationModel = this.getConfigurationModel(annotatedClass, context);
    if (((configurationModel != null) && this.featuresAnnotationCanBeFound(annotatedClass, context))) {
      this.addSelectedFeaturesAnnotation(configurationModel, annotatedClass, context);
      this.addVariantInterface(configurationModel, annotatedClass, context);
    }
  }
  
  public MutableConstructorDeclaration addPrivateConstructor(final MutableClassDeclaration annotatedClass) {
    final Procedure1 _function = (MutableConstructorDeclaration it) -> {
      it.setVisibility(Visibility.PRIVATE);
      StringConcatenationClient _client = new StringConcatenationClient() {
        @Override
        protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
        }
      };
      it.setBody(_client);
    };
    return annotatedClass.addConstructor(_function);
  }
  
  public boolean featuresAnnotationCanBeFound(final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Type _annotatedFeaturesClass = this.getAnnotatedFeaturesClass(annotatedClass, context);
    final ClassDeclaration featuresClass = ((ClassDeclaration) _annotatedFeaturesClass);
    final AnnotationReference annotationReference = featuresClass.findAnnotation(context.findTypeGlobally(FeatureIDEFeatures.class));
    if ((annotationReference != null)) {
      return true;
    } else {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("The referenced class ");
      String _simpleName = featuresClass.getSimpleName();
      _builder.append(_simpleName);
      _builder.append(" must be annotated with ");
      String _simpleName_1 = FeatureIDEFeatures.class.getSimpleName();
      _builder.append(_simpleName_1);
      _builder.append(".");
      context.addError(annotatedClass, _builder.toString());
      return false;
    }
  }
  
  private void makeFinal(final MutableClassDeclaration annotatedClass) {
    annotatedClass.setFinal(true);
  }
  
  private void addVariantInterface(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    final Type variantInterface = this.getVariantInterface(configurationModel, annotatedClass, context);
    TypeReference _newSelfTypeReference = context.newSelfTypeReference(variantInterface);
    annotatedClass.setImplementedInterfaces(Collections.unmodifiableList(CollectionLiterals.newArrayList(_newSelfTypeReference)));
  }
  
  private Type getVariantInterface(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Type _xblockexpression = null;
    {
      final String fullQualifiedName = this.getFullQualifiedVariantName(configurationModel, annotatedClass, context);
      _xblockexpression = context.findTypeGlobally(fullQualifiedName);
    }
    return _xblockexpression;
  }
  
  private String getFullQualifiedVariantName(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    String _xblockexpression = null;
    {
      Type annotatedFeaturesClass = this.getAnnotatedFeaturesClass(annotatedClass, context);
      final Feature root = this.getRoot(configurationModel);
      _xblockexpression = this._nameProvider.getFullQualifiedVariantInterfaceName(annotatedFeaturesClass, root.getName());
    }
    return _xblockexpression;
  }
  
  private void addSelectedFeaturesAnnotation(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    final Type selectedFeaturesAnnotation = this.getSelectedFeaturesAnnotation(configurationModel, annotatedClass, context);
    final Procedure1 _function = (AnnotationReferenceBuildContext it) -> {
      it.setEnumValue("value", ((EnumerationValueDeclaration[])Conversions.unwrapArray(this.getSelectedFeatures(configurationModel, annotatedClass, context), EnumerationValueDeclaration.class)));
    };
    annotatedClass.addAnnotation(context.newAnnotationReference(selectedFeaturesAnnotation, _function));
  }
  
  private Type getSelectedFeaturesAnnotation(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Type _xblockexpression = null;
    {
      final String fullQualifiedName = this.getFullQualifiedSelectedFeaturesAnnotationName(configurationModel, annotatedClass, context);
      _xblockexpression = context.findTypeGlobally(fullQualifiedName);
    }
    return _xblockexpression;
  }
  
  private String getFullQualifiedSelectedFeaturesAnnotationName(final Configuration configurationModel, final MutableClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    String _xblockexpression = null;
    {
      Type annotatedFeaturesClass = this.getAnnotatedFeaturesClass(annotatedClass, context);
      final Feature root = this.getRoot(configurationModel);
      _xblockexpression = this._nameProvider.getFullQualifiedSelectedFeaturesAnnotationName(annotatedFeaturesClass, root.getName());
    }
    return _xblockexpression;
  }
  
  private Type getAnnotatedFeaturesClass(final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Type _xblockexpression = null;
    {
      final AnnotationReference annotationReference = annotatedClass.findAnnotation(context.findTypeGlobally(FeatureIDEVariant.class));
      _xblockexpression = annotationReference.getClassValue("featuresClass").getType();
    }
    return _xblockexpression;
  }
  
  private Feature getRoot(final Configuration configurationModel) {
    Feature _xblockexpression = null;
    {
      final List features = configurationModel.getFeature();
      _xblockexpression = IterableExtensions.head(features);
    }
    return _xblockexpression;
  }
  
  private Configuration getConfigurationModel(final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Configuration _xblockexpression = null;
    {
      final Path modelFilePath = this.getModelFilePath(annotatedClass, context);
      Configuration _xifexpression = null;
      boolean _isFile = context.isFile(modelFilePath);
      if (_isFile) {
        _xifexpression = this.readConfigurationModel(modelFilePath, context);
      } else {
        StringConcatenation _builder = new StringConcatenation();
        _builder.append("The configuration file could not be found (Assumed path was: \'");
        _builder.append(modelFilePath);
        _builder.append("\').");
        context.addError(annotatedClass, _builder.toString());
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }
  
  private Path getModelFilePath(final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    final AnnotationReference annotationReference = annotatedClass.findAnnotation(context.findTypeGlobally(FeatureIDEVariant.class));
    String value = annotationReference.getStringValue("value");
    boolean _equals = Objects.equal(value, "");
    if (_equals) {
      String _simpleName = annotatedClass.getSimpleName();
      String _plus = (_simpleName + ".xml");
      value = _plus;
    }
    Path path = null;
    boolean _startsWith = value.startsWith("/");
    if (_startsWith) {
      path = context.getProjectFolder(annotatedClass.getCompilationUnit().getFilePath());
    } else {
      path = annotatedClass.getCompilationUnit().getFilePath().getParent();
    }
    return path.append("/").append(value);
  }
  
  private Configuration readConfigurationModel(final Path modelFilePath, @Extension final FileSystemSupport fileSystemSupport) {
    try {
      final Unmarshaller unmarshaller = this.jaxbContext.createUnmarshaller();
      final InputStream stream = fileSystemSupport.getContentsAsStream(modelFilePath);
      try {
        Object _unmarshal = unmarshaller.unmarshal(stream);
        return ((Configuration) _unmarshal);
      } finally {
        stream.close();
      }
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }
  
  private Iterable getSelectedFeatures(final Configuration configurationModel, final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    Iterable _xblockexpression = null;
    {
      final EnumerationTypeDeclaration featureEnum = this.getFeatureEnum(configurationModel, annotatedClass, context);
      final List features = configurationModel.getFeature();
      Type _annotatedFeaturesClass = this.getAnnotatedFeaturesClass(annotatedClass, context);
      final ClassDeclaration featuresClass = ((ClassDeclaration) _annotatedFeaturesClass);
      final AnnotationReference annotationReference = featuresClass.findAnnotation(context.findTypeGlobally(FeatureIDEFeatures.class));
      final Function1 _function = (Feature it) -> {
        return it.getName();
      };
      final Function1 _function_1 = (String it) -> {
        return this._featureNameConverter.convertToValidSimpleFeatureName(it, annotationReference);
      };
      final Function1 _function_2 = (String it) -> {
        return featureEnum.findDeclaredValue(it);
      };
      _xblockexpression = IterableExtensions.filterNull(ListExtensions.map(ListExtensions.map(ListExtensions.map(features, _function), _function_1), _function_2));
    }
    return _xblockexpression;
  }
  
  private EnumerationTypeDeclaration getFeatureEnum(final Configuration configurationModel, final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    EnumerationTypeDeclaration _xblockexpression = null;
    {
      final String fullQualifiedName = this.getFullQualifiedFeatureEnumName(configurationModel, annotatedClass, context);
      Type _findTypeGlobally = context.findTypeGlobally(fullQualifiedName);
      _xblockexpression = ((EnumerationTypeDeclaration) _findTypeGlobally);
    }
    return _xblockexpression;
  }
  
  private String getFullQualifiedFeatureEnumName(final Configuration configurationModel, final ClassDeclaration annotatedClass, @Extension final TransformationContext context) {
    String _xblockexpression = null;
    {
      Type annotatedFeaturesClass = this.getAnnotatedFeaturesClass(annotatedClass, context);
      final Feature root = this.getRoot(configurationModel);
      _xblockexpression = this._nameProvider.getFullQualifiedFeaturesEnumName(annotatedFeaturesClass, root.getName());
    }
    return _xblockexpression;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy