package rtt.annotation.editor.data.jaxb; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.List; import java.util.Map.Entry; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import rtt.annotation.editor.AnnotationEditorPlugin; import rtt.annotation.editor.data.AnnotationExporter; import rtt.annotation.editor.data.AnnotationImporter; import rtt.annotation.editor.data.jaxb.model.AnnotatedClass; import rtt.annotation.editor.data.jaxb.model.AnnotationModel; import rtt.annotation.editor.data.jaxb.model.Init; import rtt.annotation.editor.data.jaxb.model.ObjectFactory; import rtt.annotation.editor.data.jaxb.model.Value; import rtt.annotation.editor.model.ClassElement; import rtt.annotation.editor.model.ClassModel; import rtt.annotation.editor.model.ClassModel.PackageElement; import rtt.annotation.editor.model.FieldElement; import rtt.annotation.editor.model.MethodElement; import rtt.annotation.editor.model.annotation.Annotatable; import rtt.annotation.editor.model.annotation.Annotation; import rtt.annotation.editor.model.annotation.InitAnnotation; import rtt.annotation.editor.model.annotation.NodeAnnotation; import rtt.annotation.editor.model.annotation.ValueAnnotation; public class JAXBAnnotationManager implements AnnotationImporter, AnnotationExporter { private static JAXBAnnotationManager INSTANCE = null; private ObjectFactory factory = new ObjectFactory(); private JAXBContext context = null; private JAXBAnnotationManager() throws JAXBException { factory = new ObjectFactory(); context = JAXBContext.newInstance(AnnotationModel.class); } public static synchronized final JAXBAnnotationManager getInstance() { if (INSTANCE == null) { try { INSTANCE = new JAXBAnnotationManager(); } catch (JAXBException e) { throw new IllegalStateException("Could not initialize jaxb manager.", e); } } return INSTANCE; } @Override public String getExtension() { return "*.rtta"; } @Override public void importAnnotations(ClassModel model, Path importPath) { AnnotationModel annotationModel = null; try (InputStream in = Files.newInputStream(importPath, StandardOpenOption.READ)) { Unmarshaller unmarshaller = context.createUnmarshaller(); annotationModel = (AnnotationModel) unmarshaller.unmarshal(in); } catch (Exception e) { AnnotationEditorPlugin.logException("Could not import annotations", e); } List<ClassElement> classes = null; for (AnnotatedClass annotatedClass : annotationModel.getAnnotatedClass()) { classes = model.getClasses(annotatedClass.getPackage()); for (ClassElement classElement : classes) { if (classElement.getName().equals(annotatedClass.getName())) { NodeAnnotation nodeAnnotation = null; if (annotatedClass.isNode()) { nodeAnnotation = Annotation.create(NodeAnnotation.class); } classElement.setAnnotation(nodeAnnotation); classElement.setChanged(); setValueFields(annotatedClass.getValueField(), classElement); setValueMethods(annotatedClass.getValueMethod(), classElement); setInits(annotatedClass.getInitMethod(), classElement); } } } } private void setValueFields(List<Value> valueFields, ClassElement classElement) { FieldElement<ValueAnnotation> fieldElement = null; for (Value value : valueFields) { fieldElement = classElement.getValuableField(value.getName(), value.getType()); if (fieldElement != null) { fieldElement.setAnnotation(createValueAnnotation(value)); fieldElement.setChanged(); } } } private void setValueMethods(List<Value> valueMethods, ClassElement classElement) { MethodElement<ValueAnnotation> methodElement = null; for (Value value : valueMethods) { methodElement = classElement.getValuableMethod(value.getName(), value.getType()); if (methodElement != null) { methodElement.setAnnotation(createValueAnnotation(value)); methodElement.setChanged(); } } } private ValueAnnotation createValueAnnotation(Value value) { ValueAnnotation annotation = Annotation.create(ValueAnnotation.class); annotation.setValueIndex(value.getValueIndex()); annotation.setValueName(value.getValueName()); annotation.setInformational(value.isValueInformational()); return annotation; } private void setInits(List<Init> initMethod, ClassElement classElement) { MethodElement<InitAnnotation> methodElement = null; for (Init init : initMethod) { methodElement = classElement.getInitializableMethod(init.getName()); if (methodElement != null) { methodElement.setAnnotation(createInitAnnotation(init)); methodElement.setChanged(); } } } private InitAnnotation createInitAnnotation(Init init) { InitAnnotation annotation = Annotation.create(InitAnnotation.class); annotation.setWithParams(init.isWithParams()); return annotation; } @Override public void exportAnnotations(ClassModel model, Path exportPath) { AnnotationModel jaxbAnnotationModel = factory.createAnnotationModel(); for (Entry<PackageElement, List<ClassElement>> classEntry : model.getClassElements().entrySet()) { for (ClassElement classElement : classEntry.getValue()) { AnnotatedClass annotatedClass = null; if (isAnnotated(classElement)) { annotatedClass = factory.createAnnotatedClass(); annotatedClass.setName(classElement.getName()); annotatedClass.setPackage(classElement.getPackageName()); annotatedClass.setNode(classElement.hasAnnotation()); addValueFields(classElement.getValuableFields(), annotatedClass.getValueField()); addValueMethods(classElement.getValuableMethods(), annotatedClass.getValueMethod()); addInits(classElement.getInitializableMethods(), annotatedClass.getInitMethod()); jaxbAnnotationModel.getAnnotatedClass().add(annotatedClass); } } } try (OutputStream out = Files.newOutputStream(exportPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE)){ Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(jaxbAnnotationModel, out); } catch (Exception e) { AnnotationEditorPlugin.logException("Could not export annotations", e); } } private boolean isAnnotated(ClassElement classElement) { return classElement.hasAnnotation() || classElement.hasAnnotatedValueMembers() || classElement.hasAnnotatedInitializeMembers(); } private void addValueFields(List<FieldElement<ValueAnnotation>> fields, List<Value> valueAnnotatables) { Value valueAnnotated = null; for (FieldElement<ValueAnnotation> fieldElement : fields) { valueAnnotated = createValue(fieldElement); if (valueAnnotated != null) { valueAnnotated.setType(fieldElement.getType()); valueAnnotatables.add(valueAnnotated); } } } private void addValueMethods(List<MethodElement<ValueAnnotation>> methods, List<Value> valueAnnotatables) { Value valueAnnotated = null; for (MethodElement<ValueAnnotation> methodElement : methods) { valueAnnotated = createValue(methodElement); if (valueAnnotated != null) { valueAnnotated.setType(methodElement.getType()); valueAnnotatables.add(valueAnnotated); } } } private Value createValue(Annotatable<ValueAnnotation> annotatable) { Value valueAnnotated = null; if (annotatable.hasAnnotation()) { valueAnnotated = factory.createValue(); valueAnnotated.setName(annotatable.getName()); ValueAnnotation annotation = annotatable.getAnnotation(); valueAnnotated.setValueIndex(annotation.getValueIndex()); valueAnnotated.setValueName(annotation.getValueName()); valueAnnotated.setValueInformational(annotation.isInformational()); } return valueAnnotated; } private void addInits(List<? extends Annotatable<InitAnnotation>> annotatables, List<Init> initAnnotatables) { Init initAnnotated = null; for (Annotatable<InitAnnotation> annotatable : annotatables) { if (annotatable.hasAnnotation()) { initAnnotated = factory.createInit(); initAnnotated.setName(annotatable.getName()); InitAnnotation annotation = annotatable.getAnnotation(); initAnnotated.setWithParams(annotation.isWithParams()); initAnnotatables.add(initAnnotated); } } } }