Package org.modeshape.sequencer.javafile

Source Code of org.modeshape.sequencer.javafile.ClassSourceFileRecorder

/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.sequencer.javafile;

import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ABSTRACT;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ANNOTATION;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ANNOTATIONS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ANNOTATION_MEMBER;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.CLASS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.CONSTRUCTORS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ENUM;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.ENUM_VALUES;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.FIELD;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.FIELDS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.FINAL;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.IMPORTS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.INTERFACE;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.INTERFACES;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.METHOD;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.METHODS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.METHOD_PARAMETERS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.NAME;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.NATIVE;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.PACKAGE;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.PARAMETER;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.PARAMETERS;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.RETURN_TYPE_CLASS_NAME;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.SEQUENCED_DATE;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.STATIC;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.STRICT_FP;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.SUPER_CLASS_NAME;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.SYNCHRONIZED;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.TRANSIENT;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.TYPE_CLASS_NAME;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.VALUE;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.VISIBILITY;
import static org.modeshape.sequencer.classfile.ClassFileSequencerLexicon.VOLATILE;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.modeshape.common.util.StringUtil;
import org.modeshape.jcr.api.sequencer.Sequencer;
import org.modeshape.jcr.api.sequencer.Sequencer.Context;
import org.modeshape.sequencer.classfile.metadata.Visibility;
import org.modeshape.sequencer.javafile.metadata.AbstractMetadata;
import org.modeshape.sequencer.javafile.metadata.AnnotationMetadata;
import org.modeshape.sequencer.javafile.metadata.EnumMetadata;
import org.modeshape.sequencer.javafile.metadata.FieldMetadata;
import org.modeshape.sequencer.javafile.metadata.ImportMetadata;
import org.modeshape.sequencer.javafile.metadata.JavaMetadata;
import org.modeshape.sequencer.javafile.metadata.MethodMetadata;
import org.modeshape.sequencer.javafile.metadata.TypeMetadata;

/**
* A source file recorder that writes the Java metadata from the source file to the repository, using the same structure as the
* default mode of the Java Class File sequencer.
*/
public class ClassSourceFileRecorder implements SourceFileRecorder {

    /**
     * {@inheritDoc}
     *
     * @see org.modeshape.sequencer.javafile.SourceFileRecorder#record(org.modeshape.jcr.api.sequencer.Sequencer.Context, java.io.InputStream, long, java.lang.String, javax.jcr.Node)
     */
    @Override
    public void record( final Context context,
                        final InputStream inputStream,
                        final long length,
                        final String encoding,
                        final Node outputNode ) throws Exception {
            JavaMetadata javaMetadata = JavaMetadata.instance(inputStream, length, encoding);
            record(context, outputNode, javaMetadata);
    }

    private void record( Sequencer.Context context,
                        Node outputNode,
                        JavaMetadata javaMetadata ) throws RepositoryException {
        String packageName = javaMetadata.getPackageMetadata().getName();
        for (TypeMetadata typeMetadata : javaMetadata.getTypeMetadata()) {
            Node typeNode = getTypeNode(packageName, typeMetadata, outputNode);
            writeClassMetadata(context, typeNode, typeMetadata);
            writeImports(typeNode, javaMetadata.getImports());
        }
    }

    private Node getTypeNode( String packageName,
                              TypeMetadata typeMetadata,
                              Node outputNode ) throws RepositoryException {
        final String[] packagePath = packageName.split("\\.");

        if (packageName.length() > 0) {
            for (final String pkg : packagePath) {
                outputNode = outputNode.addNode(pkg);
                outputNode.addMixin(PACKAGE);
            }
        }

        final Node classNode = outputNode.addNode(typeMetadata.getName());
        final String actualType = typeMetadata.getType().equals(TypeMetadata.Type.ENUM) ? ENUM : CLASS;
        classNode.setPrimaryType(actualType);

        return classNode;
    }

    private void writeClassMetadata( Sequencer.Context context,
                                     Node typeNode,
                                     TypeMetadata typeMetadata ) throws RepositoryException {
        setTypeMetaInformation(context, typeNode, typeMetadata);

        List<MethodMetadata> methods = new ArrayList<MethodMetadata>();
        List<MethodMetadata> ctors = new ArrayList<MethodMetadata>();

        for (MethodMetadata method : typeMetadata.getMethods()) {
            if (method.getType() == MethodMetadata.Type.CONSTRUCTOR) {
                ctors.add(method);
            } else {
                methods.add(method);
            }
        }

        Node constructorsNode = typeNode.addNode(CONSTRUCTORS, CONSTRUCTORS);
        writeMethods(constructorsNode, ctors);

        Node methodsNode = typeNode.addNode(METHODS, METHODS);
        writeMethods(methodsNode, methods);

        Node fieldsNode = typeNode.addNode(FIELDS, FIELDS);
        writeFieldsNode(fieldsNode, typeMetadata.getFields());

        writeAnnotationsNode(typeNode, typeMetadata.getAnnotations());
    }

    private void setTypeMetaInformation( Sequencer.Context context,
                                         Node typeNode,
                                         TypeMetadata typeMetadata ) throws RepositoryException {
        /*
        - class:name (string) mandatory
        - class:superTypeName (string)
        - class:visibility (string) mandatory < 'public', 'protected', 'package', 'private'
        - class:abstract (boolean) mandatory
        - class:interface (boolean) mandatory
        - class:final (boolean) mandatory
        - class:strictFp (boolean) mandatory
        - class:interfaces (string) multiple
        + class:annotations (class:annotations) = class:annotations
        + class:constructors (class:constructors) = class:constructors
        + class:methods (class:methods) = class:methods
        + class:fields (class:fields) = class:fields
        */
        typeNode.setProperty(NAME, typeMetadata.getName());
        typeNode.setProperty(SEQUENCED_DATE, context.getTimestamp());

        String superTypeName = typeMetadata.getSuperTypeName();
        if (StringUtil.isBlank(superTypeName)) {
            superTypeName = Object.class.getCanonicalName();
        }
        typeNode.setProperty(SUPER_CLASS_NAME, superTypeName);
        typeNode.setProperty(VISIBILITY, visibilityFor(typeMetadata).getDescription());
        typeNode.setProperty(ABSTRACT, typeMetadata.hasAbstractModifier());
        typeNode.setProperty(INTERFACE, typeMetadata.getType() == TypeMetadata.Type.INTERFACE);
        typeNode.setProperty(FINAL, typeMetadata.hasFinalModifier());
        typeNode.setProperty(STRICT_FP, typeMetadata.hasStrictFPModifier());
        typeNode.setProperty(INTERFACES, typeMetadata.getInterfaceNames().toArray(new String[0]));

        if (typeMetadata instanceof EnumMetadata) {
            typeNode.setProperty(ENUM_VALUES, ((EnumMetadata)typeMetadata).getValues().toArray(new String[0]));
        }
    }

    private Visibility visibilityFor( AbstractMetadata typeMetadata ) {
        if (typeMetadata.hasPublicVisibility()) {
            return Visibility.PUBLIC;
        }
        if (typeMetadata.hasProtectedVisibility()) {
            return Visibility.PROTECTED;
        }
        if (typeMetadata.hasPrivateVisibility()) {
            return Visibility.PRIVATE;
        }

        return Visibility.PACKAGE;
    }

    private void writeAnnotationsNode( Node rootNode,
                                       List<AnnotationMetadata> annotations ) throws RepositoryException {

        /*
        [class:annotationMember]
        - class:name (string) mandatory
        - class:value (string)

        [class:annotation]
        - class:name (string) mandatory
        + * (class:annotationMember) = class:annotationMember

        [class:annotations]
        + * (class:annotation) = class:annotation
         */
        if (annotations.isEmpty()) {
            return;
        }

        Node annotationsContainer = rootNode.addNode(ANNOTATIONS, ANNOTATIONS);
        for (AnnotationMetadata annotationMetadata : annotations) {
            Node annotation = annotationsContainer.addNode(ANNOTATION, ANNOTATION);
            annotation.setProperty(NAME, annotationMetadata.getName());

            for (Map.Entry<String, String> entry : annotationMetadata.getMemberValues().entrySet()) {
                String key = entry.getKey();
                if (key == null) {
                    key = "default";
                }
                Node annotationMember = annotation.addNode(key, ANNOTATION_MEMBER);
                annotationMember.setProperty(NAME, key);
                annotationMember.setProperty(VALUE, entry.getValue());

            }
        }
    }

    private void writeFieldsNode( Node fields,
                                  List<FieldMetadata> fieldsMetadata ) throws RepositoryException {

        /*
            [class:field]
            - class:name (string) mandatory
            - class:typeClassName (string) mandatory
            - class:visibility (string) mandatory < 'public', 'protected', 'package', 'private'
            - class:static (boolean) mandatory
            - class:final (boolean) mandatory
            - class:transient (boolean) mandatory
            - class:volatile (boolean) mandatory
            + class:annotations (class:annotations) = class:annotations

            [class:fields]
            + * (class:field) = class:field
         */
        for (FieldMetadata fieldMetadata : fieldsMetadata) {
            Node field = fields.addNode(fieldMetadata.getName(), FIELD);
            field.setProperty(NAME, fieldMetadata.getName());
            field.setProperty(TYPE_CLASS_NAME, fieldMetadata.getType());
            field.setProperty(VISIBILITY, visibilityFor(fieldMetadata).getDescription());
            field.setProperty(STATIC, fieldMetadata.hasStaticModifier());
            field.setProperty(FINAL, fieldMetadata.hasFinalModifier());
            field.setProperty(TRANSIENT, fieldMetadata.hasTransientModifier());
            field.setProperty(VOLATILE, fieldMetadata.hasVolatileModifier());

            writeAnnotationsNode(field, fieldMetadata.getAnnotations());
        }
    }

    private void writeMethods( Node rootNode,
                               List<MethodMetadata> methods ) throws RepositoryException {

        /*
            [class:method]
            - class:name (string) mandatory
            - class:returnTypeClassName (string) mandatory
            - class:visibility (string) mandatory < 'public', 'protected', 'package', 'private'
            - class:static (boolean) mandatory
            - class:final (boolean) mandatory
            - class:abstract (boolean) mandatory
            - class:strictFp (boolean) mandatory
            - class:native (boolean) mandatory
            - class:synchronized (boolean) mandatory
            - class:parameters (string) multiple // NO LONGER USED!
            + class:annotations (class:annotations) = class:annotations
            + class:methodParameters (class:parameters) = class:parameters
         */

        for (MethodMetadata methodMetadata : methods) {
            Node method = rootNode.addNode(methodMetadata.getId(), METHOD);

            method.setProperty(NAME, methodMetadata.getName());
            method.setProperty(RETURN_TYPE_CLASS_NAME, methodMetadata.getReturnTypeName());
            method.setProperty(VISIBILITY, visibilityFor(methodMetadata).getDescription());
            method.setProperty(STATIC, methodMetadata.hasStaticModifier());
            method.setProperty(FINAL, methodMetadata.hasFinalModifier());
            method.setProperty(ABSTRACT, methodMetadata.hasAbstractModifier());
            method.setProperty(STRICT_FP, methodMetadata.hasStrictFPModifier());
            method.setProperty(NATIVE, methodMetadata.hasNativeModifier());
            method.setProperty(SYNCHRONIZED, methodMetadata.hasSynchronizedModifier());
            writeParameters(method, methodMetadata.getParameters());
            writeAnnotationsNode(method, methodMetadata.getAnnotations());
        }

    }

    private void writeParameters( Node method,
                                  List<FieldMetadata> fieldsMetadata ) throws RepositoryException {
        // Always create the container node ...
        Node parametersContainer = method.addNode(METHOD_PARAMETERS, PARAMETERS);
        if (!fieldsMetadata.isEmpty()) {
            /*
                [class:parameters]
                + * (class:parameter) = class:parameter

                [class:parameter]
                - class:name (string) mandatory
                - class:typeClassName (string) mandatory
                - class:final (boolean) mandatory
                + class:annotations (class:annotations) = class:annotations
             */
            for (FieldMetadata fieldMetadata : fieldsMetadata) {
                Node field = parametersContainer.addNode(fieldMetadata.getName(), PARAMETER);
                field.setProperty(NAME, fieldMetadata.getName());
                field.setProperty(TYPE_CLASS_NAME, fieldMetadata.getType());
                field.setProperty(FINAL, fieldMetadata.hasFinalModifier());
                writeAnnotationsNode(field, fieldMetadata.getAnnotations());
            }
        }
    }

    private void writeImports( final Node typeNode,
                               final List<ImportMetadata> imports ) throws RepositoryException {
        if ((imports != null) && !imports.isEmpty()) {
            final String[] values = new String[imports.size()];
            int i = 0;

            for (final ImportMetadata importMetadata : imports) {
                values[i++] = importMetadata.getName();
            }

            typeNode.setProperty(IMPORTS, values);
        }
    }

}
TOP

Related Classes of org.modeshape.sequencer.javafile.ClassSourceFileRecorder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.