/*
* Copyright 2012 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.drools.workbench.screens.guided.rule.backend.server;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.inject.Named;
import org.drools.workbench.models.commons.backend.rule.RuleModelDRLPersistenceImpl;
import org.drools.workbench.models.commons.backend.rule.RuleModelIActionPersistenceExtension;
import org.drools.workbench.models.datamodel.imports.Import;
import org.drools.workbench.models.datamodel.oracle.PackageDataModelOracle;
import org.drools.workbench.models.datamodel.rule.RuleModel;
import org.drools.workbench.screens.guided.rule.model.GuidedEditorContent;
import org.drools.workbench.screens.guided.rule.service.GuidedRuleEditorService;
import org.drools.workbench.screens.guided.rule.type.GuidedRuleDRLResourceTypeDefinition;
import org.drools.workbench.screens.guided.rule.type.GuidedRuleDSLRResourceTypeDefinition;
import org.guvnor.common.services.backend.config.SafeSessionInfo;
import org.guvnor.common.services.backend.exceptions.ExceptionUtilities;
import org.guvnor.common.services.backend.util.CommentedOptionFactory;
import org.guvnor.common.services.backend.validation.GenericValidator;
import org.guvnor.common.services.project.model.Package;
import org.guvnor.common.services.shared.metadata.model.Metadata;
import org.guvnor.common.services.shared.metadata.model.Overview;
import org.guvnor.common.services.shared.validation.model.ValidationMessage;
import org.jboss.errai.bus.server.annotations.Service;
import org.kie.workbench.common.services.backend.service.KieService;
import org.kie.workbench.common.services.datamodel.backend.server.DataModelOracleUtilities;
import org.kie.workbench.common.services.datamodel.backend.server.service.DataModelService;
import org.kie.workbench.common.services.datamodel.model.PackageDataModelOracleBaselinePayload;
import org.uberfire.backend.server.util.Paths;
import org.uberfire.backend.vfs.Path;
import org.uberfire.ext.editor.commons.service.CopyService;
import org.uberfire.ext.editor.commons.service.DeleteService;
import org.uberfire.ext.editor.commons.service.RenameService;
import org.uberfire.io.IOService;
import org.uberfire.java.nio.file.FileAlreadyExistsException;
import org.uberfire.rpc.SessionInfo;
import org.uberfire.workbench.events.ResourceOpenedEvent;
@Service
@ApplicationScoped
public class GuidedRuleEditorServiceImpl
extends KieService<GuidedEditorContent>
implements GuidedRuleEditorService {
@Inject
@Named("ioStrategy")
private IOService ioService;
@Inject
private CopyService copyService;
@Inject
private DeleteService deleteService;
@Inject
private RenameService renameService;
@Inject
private Event<ResourceOpenedEvent> resourceOpenedEvent;
@Inject
private DataModelService dataModelService;
@Inject
private GuidedRuleEditorServiceUtilities utilities;
@Inject
private GuidedRuleDRLResourceTypeDefinition drlResourceType;
@Inject
private GuidedRuleDSLRResourceTypeDefinition dslrResourceType;
@Inject
private GenericValidator genericValidator;
@Inject
private CommentedOptionFactory commentedOptionFactory;
private SafeSessionInfo safeSessionInfo;
private Collection<RuleModelIActionPersistenceExtension> persistenceExtensions = new ArrayList<>();
public GuidedRuleEditorServiceImpl() {
}
@Inject
public GuidedRuleEditorServiceImpl(final SessionInfo sessionInfo,
final Instance<RuleModelIActionPersistenceExtension> persistenceExtensionInstance) {
this.safeSessionInfo = new SafeSessionInfo(sessionInfo);
persistenceExtensionInstance.forEach(persistenceExtensions::add);
}
@Override
public Path create(final Path context,
final String fileName,
final RuleModel model,
final String comment) {
try {
final Package pkg = projectService.resolvePackage(context);
final String packageName = (pkg == null ? null : pkg.getPackageName());
model.setPackageName(packageName);
// Temporal fix for https://bugzilla.redhat.com/show_bug.cgi?id=998922
model.getImports().addImport(new Import("java.lang.Number"));
final org.uberfire.java.nio.file.Path nioPath = Paths.convert(context).resolve(fileName);
final Path newPath = Paths.convert(nioPath);
if (ioService.exists(nioPath)) {
throw new FileAlreadyExistsException(nioPath.toString());
}
ioService.write(nioPath,
toSource(newPath,
model),
commentedOptionFactory.makeCommentedOption(comment));
return newPath;
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public RuleModel load(final Path path) {
try {
final String drl = ioService.readAllString(Paths.convert(path));
final List<String> globals = utilities.loadGlobalsForPackage(path);
final PackageDataModelOracle oracle = dataModelService.getDataModel(path);
RuleModel ruleModel = null;
if (dslrResourceType.accept(path)) {
final String[] dsls = utilities.loadDslsForPackage(path);
ruleModel = RuleModelDRLPersistenceImpl.getInstance().unmarshalUsingDSL(drl,
globals,
oracle,
persistenceExtensions,
dsls);
} else {
ruleModel = RuleModelDRLPersistenceImpl.getInstance().unmarshal(drl,
globals,
oracle,
persistenceExtensions);
}
return ruleModel;
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public GuidedEditorContent loadContent(final Path path) {
return super.loadContent(path);
}
@Override
protected GuidedEditorContent constructContent(Path path,
Overview overview) {
final RuleModel model = load(path);
final PackageDataModelOracle oracle = dataModelService.getDataModel(path);
final PackageDataModelOracleBaselinePayload dataModel = new PackageDataModelOracleBaselinePayload();
//Get FQCN's used by model
final GuidedRuleModelVisitor visitor = new GuidedRuleModelVisitor(model);
final Set<String> consumedFQCNs = visitor.getConsumedModelClasses();
//Get FQCN's used by Globals
consumedFQCNs.addAll(oracle.getPackageGlobals().values());
DataModelOracleUtilities.populateDataModel(oracle,
dataModel,
consumedFQCNs);
//Signal opening to interested parties
resourceOpenedEvent.fire(new ResourceOpenedEvent(path,
safeSessionInfo));
return new GuidedEditorContent(model,
overview,
dataModel);
}
@Override
public Path save(final Path resource,
final RuleModel model,
final Metadata metadata,
final String comment) {
try {
final Package pkg = projectService.resolvePackage(resource);
final String packageName = (pkg == null ? null : pkg.getPackageName());
model.setPackageName(packageName);
Metadata currentMetadata = metadataService.getMetadata(resource);
ioService.write(Paths.convert(resource),
toSourceUnexpanded(resource,
model),
metadataService.setUpAttributes(resource,
metadata),
commentedOptionFactory.makeCommentedOption(comment));
fireMetadataSocialEvents(resource,
currentMetadata,
metadata);
return resource;
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public void delete(final Path path,
final String comment) {
try {
deleteService.delete(path,
comment);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public Path rename(final Path path,
final String newName,
final String comment) {
try {
return renameService.rename(path,
newName,
comment);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public Path copy(final Path path,
final String newName,
final String comment) {
try {
return copyService.copy(path,
newName,
comment);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public Path copy(final Path path,
final String newName,
final Path targetDirectory,
final String comment) {
try {
return copyService.copy(path,
newName,
targetDirectory,
comment);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public String toSource(final Path path,
final RuleModel model) {
try {
return toSourceExpanded(path,
model);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
@Override
public List<ValidationMessage> validate(final Path path,
final RuleModel content) {
try {
final String source = toSourceUnexpanded(path,
content);
return genericValidator.validate(path,
source);
} catch (Exception e) {
throw ExceptionUtilities.handleException(e);
}
}
private String toSourceExpanded(final Path path,
final RuleModel model) {
//This returns the expanded Source as used in "View Source" within the UI.
return sourceServices.getServiceFor(Paths.convert(path)).getSource(Paths.convert(path),
model);
}
private String toSourceUnexpanded(final Path path,
final RuleModel content) {
//Wrap RuleModel as we need to control whether the DSLs are expanded. Both DRL and DSLR files should not have
//DSLs expanded. In the case of DSLRs we need to explicitly control escaping plain-DRL to prevent attempts
//by drools to expand it, by forcing the Model->DRL persistence into believing the model has DSLs.
final RuleModelWrapper model = new RuleModelWrapper(content,
dslrResourceType.accept(path));
final String source = RuleModelDRLPersistenceImpl.getInstance().marshal(model,
persistenceExtensions);
return source;
}
}