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

org.drools.compiler.builder.impl.DeclaredClassBuilder Maven / Gradle / Ivy

There is a newer version: 10.0.0
Show newest version
/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      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.drools.compiler.builder.impl;

import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.compiler.TypeDeclarationError;
import org.drools.compiler.lang.descr.AbstractClassTypeDeclarationDescr;
import org.drools.compiler.lang.descr.TypeDeclarationDescr;
import org.drools.core.common.ProjectClassLoader;
import org.drools.core.factmodel.ClassBuilder;
import org.drools.core.factmodel.ClassDefinition;
import org.drools.core.rule.JavaDialectRuntimeData;
import org.drools.core.rule.TypeDeclaration;
import org.kie.soup.project.datamodel.commons.types.TypeResolver;

import static org.drools.core.util.ClassUtils.convertClassToResourcePath;

import org.kie.soup.project.datamodel.commons.types.TypeResolver;

public class DeclaredClassBuilder {

    protected final KnowledgeBuilderImpl kbuilder;

    public DeclaredClassBuilder(KnowledgeBuilderImpl kbuilder) {
        this.kbuilder = kbuilder;
    }

    public void generateBeanFromDefinition(AbstractClassTypeDeclarationDescr typeDescr,
                                           TypeDeclaration type,
                                           PackageRegistry pkgRegistry,
                                           ClassDefinition def) {

        if (type.isNovel()) {
            String fullName = typeDescr.getType().getFullName();
            JavaDialectRuntimeData dialect = (JavaDialectRuntimeData) pkgRegistry.getDialectRuntimeRegistry().getDialectData("java");
            if (ensureJavaTypeConsistency(typeDescr, def, pkgRegistry.getTypeResolver())) {
                switch (type.getKind()) {
                    case TRAIT:
                        try {
                            buildClass(def, fullName, dialect, this.kbuilder.getBuilderConfiguration().getClassBuilderFactory().getTraitBuilder(), pkgRegistry);
                        } catch (Exception e) {
                            e.printStackTrace();
                            this.kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr,
                                                                                    "Unable to compile declared trait " + fullName +
                                                                                            ": " + e.getMessage() + ";"));
                        }
                        break;
                    case ENUM:
                        try {
                            buildClass(def, fullName, dialect, this.kbuilder.getBuilderConfiguration().getClassBuilderFactory().getEnumClassBuilder(), pkgRegistry);
                        } catch (Exception e) {
                            e.printStackTrace();
                            this.kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr,
                                                                                    "Unable to compile declared enum " + fullName +
                                                                                            ": " + e.getMessage() + ";"));
                        }
                        break;
                    case CLASS:
                    default:
                        try {
                            buildClass(def, fullName, dialect, this.kbuilder.getBuilderConfiguration().getClassBuilderFactory().getBeanClassBuilder(), pkgRegistry);
                        } catch (Exception e) {
                            e.printStackTrace();
                            this.kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr,
                                                                                    "Unable to create a class for declared type " + fullName +
                                                                                            ": " + e.getMessage() + ";"));
                        }
                        break;
                }
            }
        }
    }

    private boolean ensureJavaTypeConsistency(AbstractClassTypeDeclarationDescr typeDescr, ClassDefinition def, TypeResolver typeResolver) {
        try {
            if (typeDescr instanceof TypeDeclarationDescr && !((TypeDeclarationDescr) typeDescr).isTrait()
                    && typeResolver.resolveType(def.getSuperClass()).isInterface()) {
                kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Interfaces cannot be used as super types of normal classes: " + def.getSuperClass()));
                return false;
            }
            for (String sup : def.getInterfaces()) {
                if (!typeResolver.resolveType(sup).isInterface()) {
                    kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Non-interface type used as super interface : " + sup));
                    return false;
                }
            }
        } catch (ClassNotFoundException cnfe) {
            kbuilder.addBuilderResult(new TypeDeclarationError(typeDescr, "Unable to resolve parent type :" + cnfe.getMessage()));
            return false;
        }
        return true;
    }

    protected void buildClass(ClassDefinition def, String fullName, JavaDialectRuntimeData dialect, ClassBuilder cb, PackageRegistry pkgRegistry) throws Exception {
        byte[] bytecode = cb.buildClass(def, kbuilder.getRootClassLoader());
        String resourceName = convertClassToResourcePath(fullName);
        dialect.putClassDefinition(resourceName, bytecode);
        if (kbuilder.getKnowledgeBase() != null) {
            Class clazz = kbuilder.getKnowledgeBase().registerAndLoadTypeDefinition(fullName, bytecode);
            pkgRegistry.getTypeResolver().registerClass(fullName, clazz);
        } else {
            if (kbuilder.getRootClassLoader() instanceof ProjectClassLoader) {
                Class clazz = ((ProjectClassLoader) kbuilder.getRootClassLoader()).defineClass(fullName, resourceName, bytecode);
                pkgRegistry.getTypeResolver().registerClass(fullName, clazz);
            } else {
                dialect.write(resourceName, bytecode);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy