/*
* 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.
* 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.kie.workbench.common.services.datamodel.backend.server.cache;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
import org.drools.workbench.models.datamodel.imports.Import;
import org.drools.workbench.models.datamodel.oracle.ProjectDataModelOracle;
import org.drools.workbench.models.datamodel.oracle.TypeSource;
import org.kie.scanner.KieModuleMetaData;
import org.kie.workbench.common.services.backend.builder.service.BuildInfo;
import org.kie.workbench.common.services.backend.builder.core.TypeSourceResolver;
import org.kie.workbench.common.services.datamodel.backend.server.builder.projects.ProjectDataModelOracleBuilder;
import org.kie.workbench.common.services.shared.project.KieProject;
import org.kie.workbench.common.services.shared.project.ProjectImportsService;
import org.kie.workbench.common.services.shared.whitelist.PackageNameWhiteListService;
import org.kie.workbench.common.services.shared.whitelist.WhiteList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.uberfire.backend.server.util.Paths;
import org.uberfire.java.nio.file.Files;
public class ProjectDataModelOracleBuilderProvider {
private static final Logger log = LoggerFactory.getLogger(ProjectDataModelOracleBuilderProvider.class);
private ProjectImportsService importsService;
private PackageNameWhiteListService packageNameWhiteListService;
public ProjectDataModelOracleBuilderProvider() {
//CDI proxy
}
@Inject
public ProjectDataModelOracleBuilderProvider(final PackageNameWhiteListService packageNameWhiteListService,
final ProjectImportsService importsService) {
this.packageNameWhiteListService = packageNameWhiteListService;
this.importsService = importsService;
}
public InnerBuilder newBuilder( final KieProject project,
final BuildInfo buildInfo ) {
final KieModuleMetaData kieModuleMetaData = buildInfo.getKieModuleMetaDataIgnoringErrors();
final TypeSourceResolver typeSourceResolver = buildInfo.getTypeSourceResolver(kieModuleMetaData);
return new InnerBuilder(project,
kieModuleMetaData,
typeSourceResolver);
}
class InnerBuilder {
private final ProjectDataModelOracleBuilder pdBuilder = ProjectDataModelOracleBuilder.newProjectOracleBuilder();
private final KieProject project;
private final KieModuleMetaData kieModuleMetaData;
private final TypeSourceResolver typeSourceResolver;
private InnerBuilder(final KieProject project,
final KieModuleMetaData kieModuleMetaData,
final TypeSourceResolver typeSourceResolver) {
this.project = project;
this.kieModuleMetaData = kieModuleMetaData;
this.typeSourceResolver = typeSourceResolver;
}
public ProjectDataModelOracle build() {
addFromKieModuleMetadata();
addExternalImports();
return pdBuilder.build();
}
/**
* The availability of these classes is checked in Builder and failed fast. Here we load them into the DMO
*/
private void addExternalImports() {
if (Files.exists(Paths.convert(project.getImportsPath()))) {
for (final Import item : getImports()) {
addClass(item);
}
}
}
private void addFromKieModuleMetadata() {
for (final String packageName : getFilteredPackageNames()) {
pdBuilder.addPackage(packageName);
addClasses(packageName,
kieModuleMetaData.getClasses(packageName));
}
}
/**
* @return A "white list" of package names that are available for authoring
*/
private WhiteList getFilteredPackageNames() {
return packageNameWhiteListService.filterPackageNames(project,
kieModuleMetaData.getPackages());
}
private void addClasses(final String packageName,
final Collection<String> classes) {
for (final String className : classes) {
addClass(packageName,
className);
}
}
private void addClass(final Import item) {
try {
Class clazz = this.getClass().getClassLoader().loadClass(item.getType());
pdBuilder.addClass(clazz,
false,
TypeSource.JAVA_DEPENDENCY);
} catch (ClassNotFoundException cnfe) {
//Class resolution would have happened in Builder and reported as warnings so log error here at debug level to avoid flooding logs
log.debug(cnfe.getMessage());
} catch (IOException ioe) {
log.debug(ioe.getMessage());
}
}
private void addClass(final String packageName,
final String className) {
try {
final Class clazz = kieModuleMetaData.getClass(packageName,
className);
pdBuilder.addClass(clazz,
kieModuleMetaData.getTypeMetaInfo(clazz).isEvent(),
typeSourceResolver.getTypeSource(clazz));
} catch (Throwable e) {
//Class resolution would have happened in Builder and reported as warnings so log error here at debug level to avoid flooding logs
log.debug(e.getMessage());
}
}
private List<Import> getImports() {
return importsService.load(project.getImportsPath()).getImports().getImports();
}
}
}