Commit 35671093 authored by Daniel Bluhm's avatar Daniel Bluhm

Add PersistenceExtractor

Removed now unneeded classes and files. Passing all tests.
Signed-off-by: Daniel Bluhm's avatarDaniel Bluhm <bluhmdj@ornl.gov>
parent 33bfd9b1
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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:
* Michael Walsh - Initial implementation
*******************************************************************************/
package org.eclipse.ice.dev.annotations.processors;
import java.io.IOException;
import javax.annotation.processing.ProcessingEnvironment;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
/**
* Abstract class for service classes that generate
* {@link org.eclipse.ice.dev.annotations.processors.VelocitySourceWriter}s
*
* @author Michael Walsh
*/
public abstract class AbstractWriterGenerator {
/**
* Used to create JavaFileObjects
*/
protected ProcessingEnvironment processingEnv;
/**
* Constructor
*
* @param processingEnv necessary to write source files with
*/
AbstractWriterGenerator(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}
/**
* Generates object used for writing templated class to
*
* @param name of file
* @return JavaFileObject used to write generated class file to
* @throws IOException file writing
*/
public JavaFileObject createFileObjectForName(String name) throws IOException {
return processingEnv.getFiler().createSourceFile(name);
}
/**
* Generate resource file objec
*
* @param name of file
* @return JavaFileObject used to write generated class file to
* @throws IOException file writing
*/
public FileObject createResourceForName(String name) throws IOException {
return processingEnv.getFiler().createResource(
StandardLocation.SOURCE_OUTPUT, "", "frontend/" + name + ".ts"
);
}
}
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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:
* Michael Walsh - Initial implementation
*******************************************************************************/
package org.eclipse.ice.dev.annotations.processors;
import javax.lang.model.element.Element;
import lombok.Builder;
import lombok.Data;
/**
* Input POJO for the flavors of the ICEAnnotationExtractionService
*
* @author Michael Walsh
*/
@Data
@Builder
public class AnnotationExtractionRequest {
/**
* Element to be extracted from
*/
private Element element;
/**
* Included list of static default fields in addition to fields specified in
* element
*/
@Builder.Default
private boolean includeDefaults = true;
/**
* Base name for the generated classes
*/
private String className;
}
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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:
* Michael Walsh - Initial implementation
*******************************************************************************/
package org.eclipse.ice.dev.annotations.processors;
import java.util.Map;
import lombok.Builder;
import lombok.Data;
/**
* Typical response from the flavors of ICEAnnotationExtractionService
*
* @author Michael Walsh
*/
@Data
@Builder
public class AnnotationExtractionResponse {
/**
* Pojo containing metadata about fields to be included in Velocity generated
* classes
*/
private Fields fields;
/**
* Map containing metadata surrounding the class types to be generated, e.g.
* package name
*/
private Map<TemplateProperty, Object> classMetadata;
}
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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
* Copyright (c) 2020- UT-Battelle, LLC. 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:
* Michael Walsh - Initial implementation
* Contributors: Michael Walsh - Initial implementation
*******************************************************************************/
package org.eclipse.ice.dev.annotations.processors;
import java.io.IOException;
import java.io.Writer;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.processing.Filer;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
......@@ -38,22 +31,7 @@ import lombok.Builder;
* @author Michael Walsh
*/
public class DataElementAnnotationExtractor
implements AnnotationExtractor<DataElementMetadata>
{
/**
* Annotations to not be transfered from member variables of Spec classes to
* final generated classes
*/
private static final List<String> nonTransferableAnnotations =
Stream.of(DataField.class, DataField.Default.class)
.map(Class::getCanonicalName)
.collect(
Collectors.collectingAndThen(
Collectors.toList(), Collections::unmodifiableList
)
);
implements AnnotationExtractor<DataElementMetadata> {
/**
* Logger.
*/
......@@ -70,10 +48,10 @@ public class DataElementAnnotationExtractor
private DataFieldExtractor dataFieldExtractor;
/**
* Constructor that lets you initialize the {@link DataElementAnnotationExtractor} with different
* implementations of {@link ICEAnnotationExtractionService} and {@link WriterGenerator}
* @param annotationExtractionService
* @param writerGenerator
* Create DataElement Annotation Extractor.
* @param elementUtils Elements from processing environment.
* @param dataFieldExtractor Extractor for elements annotated with
* DataField.
*/
@Builder
public DataElementAnnotationExtractor(
......
......@@ -27,7 +27,6 @@ import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
......@@ -91,11 +90,6 @@ public class DataElementProcessor extends AbstractProcessor {
*/
protected DataElementAnnotationExtractor extractor;
/**
* Util class for various specific data extraction from Elements
*/
private SpecExtractionHelper specExtractionHelper = new SpecExtractionHelper();
@Override
public synchronized void init(final ProcessingEnvironment env) {
this.messager = env.getMessager();
......@@ -114,7 +108,8 @@ public class DataElementProcessor extends AbstractProcessor {
for (final Element elem : roundEnv.getElementsAnnotatedWith(DataElement.class)) {
try {
DataElementMetadata data = this.extractor.extract(elem);
Optional<PersistenceMetadata> persistence = Optional.empty();
Optional<PersistenceMetadata> persistence =
new PersistenceExtractor().extractIfApplies(elem);
Set<WriterGenerator> generators = WriterGeneratorFactory.create(
data,
persistence
......
......@@ -61,7 +61,7 @@ public class DataElementWriterGenerator implements WriterGenerator {
.types(nonDefaults.getTypes())
.build());
} catch (UnsupportedOperationException e) {
logger.warn("Failed to create typescript writer for element:", e);
logger.info("Failed to create typescript writer for element:", e);
}
return writers;
......
......@@ -49,6 +49,11 @@ public class DataFieldExtractor implements AnnotationExtractor<Field> {
@Override
public Field extract(Element element) throws InvalidElementException {
DataField fieldInfo = element.getAnnotation(DataField.class);
if (fieldInfo == null) {
throw new InvalidElementException(
"DataField annotation not found on element."
);
}
return Field.builder()
.name(extractFieldName(element))
.type(extractFieldType(element))
......
package org.eclipse.ice.dev.annotations.processors;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import org.eclipse.ice.dev.annotations.DataField;
/**
* An AnnotatedElement subclass representing a DataField.
* @author Daniel Bluhm
*/
public class DataFieldSpec extends AnnotatedElement {
/**
* Set of Annotation names that extractAnnotations should filter out.
*/
private static final Set<String> ANNOTATION_CLASS_NAMES = Set.of(
DataField.class,
DataField.Default.class
).stream()
.map(cls -> cls.getCanonicalName())
.collect(Collectors.toSet());
/**
* Used to get DataField Annotation values.
*/
private DataField fieldInfo;
/**
* Instantiate a DataFieldSpec.
* @param element annotated with {@code @DataField}
* @param elementUtils Elements helper class from processing environment
*/
public DataFieldSpec(Element element, Elements elementUtils) {
super(element, elementUtils);
this.fieldInfo = this.element.getAnnotation(DataField.class);
}
/**
* Determine if the passed field is a DataField.
* @param element to check
* @return whether element is a DataField
*/
public static boolean isDataField(Element element) {
return element.getAnnotation(DataField.class) != null;
}
/**
* Return the set of access modifiers on this Field.
* @return extract field modifiers
* @see Modifier
*/
private Set<Modifier> extractModifiers() {
return this.element.getModifiers();
}
/**
* Return the set of annotations on this DataField, excepting the DataField
* Annotation itself.
* @return extracted annotations, excluding DataField related annotations
*/
private List<String> extractAnnotations() {
return this.element.getAnnotationMirrors().stream()
.filter(mirror -> !ANNOTATION_CLASS_NAMES.contains(
mirror.getAnnotationType().toString()
))
.map(mirror -> mirror.toString())
.collect(Collectors.toList());
}
/**
* Return the class of this Field.
* @return extracted field type
*/
private TypeMirror extractFieldType() {
return this.element.asType();
}
/**
* Return the name of this Field.
* @return extracted field name
*/
private String extractFieldName() {
return this.element.getSimpleName().toString();
}
/**
* Return the DocString of this Field.
* @return extracted doc comment
*/
private String extractDocString() {
return this.elementUtils.getDocComment(this.element);
}
/**
* Extract the defaultValue of this Field. Checks for {@link DataField.Default}
* and if not present checks for a constant expression if the field is
* {@code final}.
* @return extracted default value
*/
private String extractDefaultValue() {
String retval = null;
DataField.Default defaults = this.element.getAnnotation(DataField.Default.class);
if (defaults != null) {
if (defaults.isString()) {
retval = this.elementUtils.getConstantExpression(defaults.value());
} else {
retval = defaults.value();
}
} else if (this.element.getModifiers().contains(Modifier.FINAL)) {
retval = this.elementUtils.getConstantExpression(
((VariableElement) this.element).getConstantValue()
);
}
return retval;
}
/**
* Return this DataFieldSpec as a Field.
* @return field
*/
public Field toField() {
return Field.builder()
.name(extractFieldName())
.type(extractFieldType())
.defaultValue(extractDefaultValue())
.docString(extractDocString())
.annotations(extractAnnotations())
.modifiersToString(extractModifiers())
.getter(fieldInfo.getter())
.setter(fieldInfo.setter())
.match(fieldInfo.match())
.unique(fieldInfo.unique())
.searchable(fieldInfo.searchable())
.nullable(fieldInfo.nullable())
.build();
}
}
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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:
* Michael Walsh - Initial implementation
*******************************************************************************/
package org.eclipse.ice.dev.annotations.processors;
import javax.lang.model.element.Element;
import org.eclipse.ice.dev.annotations.DataElement;
import org.eclipse.ice.dev.annotations.Persisted;
/**
* Class that encompasses the initial naming schema if generated files
*
* @author Michael Walsh
*
*/
public class DefaultNameGenerator implements NameGenerator {
/**
* The value appended to DataElement implementation class names.
*/
private static final String IMPL_SUFFIX = "Implementation";
/**
* The value appended to DataElement Persistence Handler class names.
*/
private static final String PERSISTENCE_SUFFIX = "PersistenceHandler";
/**
* Used for pulling data from annotations on {@link Element}s
*/
private SpecExtractionHelper specExtractionHelper = new SpecExtractionHelper();
/**
* Return the element name as extracted from the DataElement annotation.
*
* @return the extracted name
*/
@Override
public String extractName(Element element) {
return specExtractionHelper.getAnnotation(element, DataElement.class).map(DataElement::name).orElse(null);
}
/**
* Return the collection name as extracted from the Persisted annotation.
*
* @return the extracted collection name
*/
@Override
public String extractCollectionName(Element element) {
return specExtractionHelper.getAnnotation(element, Persisted.class).map(Persisted::collection).orElse(null);
}
/**
* Get the name of the Implementation to be generated.
*
* @return implementation name
*/
@Override
public String getImplName(String name) {
return name + IMPL_SUFFIX;
}
/**
* Get the fully qualified name of the Implementation to be generated.
*
* @return fully qualified implementation name
*/
@Override
public String getQualifiedImplName(String fullyQualifiedName) {
return fullyQualifiedName + IMPL_SUFFIX;
}
/**
* Get the name of the Persistence Handler to be generated.
*
* @return persistence handler name
*/
@Override
public String getPersistenceHandlerName(String name) {
return name + PERSISTENCE_SUFFIX;
}
/**
* Generate the fully qualified name for a persistence handler
*
* @param fullyQualifiedName
* @return fullyQualifiedName for a persistence handler
*/
@Override
public String getQualifiedPersistenceHandlerName(String fullyQualifiedName) {
return fullyQualifiedName + PERSISTENCE_SUFFIX;
}
/**
* Get the interface name of the persistence handler.
*
* Right now, this is simply the IPersistenceHandler interface. In the future
* this will be a data element specific interface.
*
* @return Interface name of the Persistence Handler
*/
@Override
public String getPersistenceHandlerInterfaceName() {
return org.eclipse.ice.data.IPersistenceHandler.class.getSimpleName();
}
}
/*******************************************************************************
* Copyright (c) 2020- UT-Battelle, LLC.
* 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:
* Michael Walsh - Initial implementation
*******************************************************************************/