Search in sources :

Example 26 with ClassData

use of org.motechproject.mds.domain.ClassData in project motech by motech.

the class MDSConstructorImpl method constructEntities.

@Override
public synchronized boolean constructEntities(SchemaHolder schemaHolder) {
    // To be able to register updated class, we need to reload class loader
    // and therefore add all the classes again
    MotechClassPool.clearEnhancedData();
    MDSClassLoader.reloadClassLoader();
    // we need an jdo enhancer and a temporary classLoader
    // to define classes in before enhancement
    MDSClassLoader tmpClassLoader = MDSClassLoader.getStandaloneInstance();
    MdsJDOEnhancer enhancer = createEnhancer(tmpClassLoader);
    JavassistLoader loader = new JavassistLoader(tmpClassLoader);
    // process only entities that are not drafts
    List<EntityDto> entities = schemaHolder.getAllEntities();
    filterEntities(entities);
    sortEntities(entities, schemaHolder);
    // create enum for appropriate combobox fields
    for (EntityDto entity : entities) {
        buildEnum(loader, enhancer, entity, schemaHolder);
    }
    // load entities interfaces
    for (EntityDto entity : entities) {
        buildInterfaces(loader, enhancer, entity);
    }
    // generate jdo metadata from scratch for our entities
    JDOMetadata jdoMetadata = metadataHolder.reloadMetadata();
    // since we just fetch fields from existing definition
    for (EntityDto entity : entities) {
        if (entity.isRecordHistory()) {
            entityBuilder.prepareHistoryClass(entity);
        }
        entityBuilder.prepareTrashClass(entity);
    }
    // Build classes
    Map<String, ClassData> classDataMap = buildClasses(entities, schemaHolder);
    List<Class> classes = new ArrayList<>();
    // the temporary ClassLoader and enhancer
    for (EntityDto entity : entities) {
        String className = entity.getClassName();
        Class<?> definition = addClassData(loader, enhancer, classDataMap.get(className));
        if (entity.isRecordHistory()) {
            addClassData(loader, enhancer, classDataMap.get(ClassName.getHistoryClassName(className)));
        }
        addClassData(loader, enhancer, classDataMap.get(ClassName.getTrashClassName(className)));
        classes.add(definition);
        LOGGER.debug("Generated classes for {}", entity.getClassName());
    }
    for (Class<?> definition : classes) {
        loader.loadFieldsAndMethodsOfClass(definition);
    }
    // Prepare metadata
    buildMetadata(entities, jdoMetadata, classDataMap, classes, schemaHolder);
    // after the classes are defined, we register their metadata
    enhancer.registerMetadata(jdoMetadata);
    // then, we commence with enhancement
    enhancer.enhance();
    // we register the enhanced class bytes
    // and build the infrastructure classes
    registerEnhancedClassBytes(entities, enhancer, schemaHolder);
    metadataBuilder.fixEnhancerIssuesInMetadata(jdoMetadata, schemaHolder);
    return CollectionUtils.isNotEmpty(entities);
}
Also used : MDSClassLoader(org.motechproject.mds.util.MDSClassLoader) JDOMetadata(javax.jdo.metadata.JDOMetadata) ArrayList(java.util.ArrayList) JavassistLoader(org.motechproject.mds.javassist.JavassistLoader) EntityDto(org.motechproject.mds.dto.EntityDto) MdsJDOEnhancer(org.motechproject.mds.enhancer.MdsJDOEnhancer) ClassData(org.motechproject.mds.domain.ClassData) CtClass(javassist.CtClass)

Example 27 with ClassData

use of org.motechproject.mds.domain.ClassData in project motech by motech.

the class MDSConstructorImpl method buildEnum.

private void buildEnum(JavassistLoader loader, MdsJDOEnhancer enhancer, EntityDto entity, SchemaHolder schemaHolder) {
    for (FieldDto field : schemaHolder.getFields(entity.getClassName())) {
        TypeDto type = field.getType();
        if (!type.isCombobox()) {
            continue;
        }
        ComboboxHolder holder = new ComboboxHolder(entity, field);
        if (holder.isEnum() || holder.isEnumCollection()) {
            if (field.isReadOnly()) {
                String enumName = holder.getEnumName();
                Class<?> definition = loadClass(entity, enumName);
                if (null != definition) {
                    MotechClassPool.registerEnum(enumName);
                    CtClass ctClass = MotechClassPool.getDefault().getOrNull(enumName);
                    if (null != ctClass) {
                        try {
                            ctClass.defrost();
                            byte[] bytecode = ctClass.toBytecode();
                            ClassData data = new ClassData(enumName, bytecode);
                            // register with the classloader so that we avoid issues with the persistence manager
                            MDSClassLoader.getInstance().safeDefineClass(data.getClassName(), data.getBytecode());
                            addClassData(loader, enhancer, data);
                        } catch (IOException | CannotCompileException e) {
                            LOGGER.error("Could not load enum: {}", enumName);
                        }
                    }
                }
            } else {
                buildEnum(loader, enhancer, holder);
            }
        }
    }
}
Also used : CtClass(javassist.CtClass) ClassData(org.motechproject.mds.domain.ClassData) ComboboxHolder(org.motechproject.mds.domain.ComboboxHolder) TypeDto(org.motechproject.mds.dto.TypeDto) IOException(java.io.IOException) CannotCompileException(javassist.CannotCompileException) FieldDto(org.motechproject.mds.dto.FieldDto)

Example 28 with ClassData

use of org.motechproject.mds.domain.ClassData in project motech by motech.

the class MDSConstructorImpl method registerHistoryClass.

private void registerHistoryClass(MdsJDOEnhancer enhancer, String className) {
    String historyClassName = ClassName.getHistoryClassName(className);
    byte[] enhancedBytes = enhancer.getEnhancedBytes(historyClassName);
    ClassData classData = new ClassData(historyClassName, enhancedBytes);
    // register with the classloader so that we avoid issues with the persistence manager
    MDSClassLoader.getInstance().safeDefineClass(classData.getClassName(), classData.getBytecode());
    MotechClassPool.registerHistoryClassData(classData);
}
Also used : ClassData(org.motechproject.mds.domain.ClassData)

Aggregations

ClassData (org.motechproject.mds.domain.ClassData)28 Test (org.junit.Test)9 FieldDto (org.motechproject.mds.dto.FieldDto)7 CtClass (javassist.CtClass)6 ArrayList (java.util.ArrayList)5 EntityDto (org.motechproject.mds.dto.EntityDto)5 IOException (java.io.IOException)4 CannotCompileException (javassist.CannotCompileException)3 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)3 HashSet (java.util.HashSet)2 ByteArrayClassPath (javassist.ByteArrayClassPath)2 ComboboxHolder (org.motechproject.mds.domain.ComboboxHolder)2 MetadataDto (org.motechproject.mds.dto.MetadataDto)2 TypeDto (org.motechproject.mds.dto.TypeDto)2 EntityCreationException (org.motechproject.mds.exception.entity.EntityCreationException)2 EntBuilderTestClass (org.motechproject.mds.testutil.EntBuilderTestClass)2 MDSClassLoader (org.motechproject.mds.util.MDSClassLoader)2 Bundle (org.osgi.framework.Bundle)2 FileOutputStream (java.io.FileOutputStream)1 InputStream (java.io.InputStream)1