Search in sources :

Example 16 with Template

use of com.devonfw.cobigen.impl.config.entity.Template in project cobigen by devonfw.

the class GenerationProcessorImpl method generate.

/**
 * Generates code for the given input with the given template and the given {@link TriggerInterpreter} to the
 * destination specified by the templates configuration.
 *
 * @param template to be processed for generation
 * @param triggerInterpreter {@link TriggerInterpreter} to be used for reading the input and creating the model
 * @param origToTmpFileTrace the mapping of temporary generated files to their original target destination to
 *        eventually finalizing the generation process
 * @param progressCallback to track progress
 * @throws InvalidConfigurationException if the inputs do not fit to the configuration or there are some configuration
 *         failures
 */
private void generate(TemplateTo template, TriggerInterpreter triggerInterpreter, Map<File, File> origToTmpFileTrace, BiConsumer<String, Integer> progressCallback) {
    Trigger trigger = this.configurationHolder.readContextConfiguration().getTrigger(template.getTriggerId());
    InputReader inputReader = triggerInterpreter.getInputReader();
    if (!inputReader.isValidInput(this.input)) {
        throw new CobiGenRuntimeException("An invalid input of type " + this.input.getClass() + " has been passed to " + inputReader.getClass() + " (derived from trigger '" + trigger.getId() + "')");
    }
    List<Object> inputObjects = this.inputResolver.resolveContainerElements(this.input, trigger);
    TemplatesConfiguration tConfig = this.configurationHolder.readTemplatesConfiguration(trigger);
    String templateEngineName = tConfig.getTemplateEngine();
    TextTemplateEngine templateEngine = TemplateEngineRegistry.getEngine(templateEngineName);
    templateEngine.setTemplateFolder(this.configurationHolder.readContextConfiguration().getConfigurationPath().resolve(trigger.getTemplateFolder()));
    Template templateEty = tConfig.getTemplate(template.getId());
    if (templateEty == null) {
        throw new UnknownTemplateException(template.getId());
    }
    for (Object generatorInput : inputObjects) {
        progressCallback.accept("Building template model for input " + generatorInput, 1);
        Map<String, Object> model = buildModel(triggerInterpreter, trigger, generatorInput, templateEty);
        String targetCharset = templateEty.getTargetCharset();
        // resolve temporary file paths
        @SuppressWarnings("unchecked") PathExpressionResolver pathExpressionResolver = new PathExpressionResolver(Variables.fromMap((Map<String, String>) model.get(ModelBuilderImpl.NS_VARIABLES)));
        String resolvedTargetDestinationPath = pathExpressionResolver.evaluateExpressions(templateEty.getUnresolvedTargetPath());
        String resolvedTmpDestinationPath = pathExpressionResolver.evaluateExpressions(templateEty.getUnresolvedTemplatePath());
        File originalFile = this.targetRootPath.resolve(resolvedTargetDestinationPath).toFile();
        File tmpOriginalFile;
        if (origToTmpFileTrace.containsKey(originalFile)) {
            // use the available temporary file
            tmpOriginalFile = origToTmpFileTrace.get(originalFile);
        } else {
            tmpOriginalFile = this.tmpTargetRootPath.resolve(resolvedTmpDestinationPath).toFile();
            // remember mapping to later on copy the generated resources to its target destinations
            origToTmpFileTrace.put(originalFile, tmpOriginalFile);
        }
        if (originalFile.exists() || tmpOriginalFile.exists()) {
            if (!tmpOriginalFile.exists()) {
                try {
                    FileUtils.copyFile(originalFile, tmpOriginalFile);
                } catch (IOException e) {
                    throw new CobiGenRuntimeException("Could not copy file " + originalFile.getPath() + " to tmp generation directory! Generation skipped.", e);
                }
            }
            if ((this.forceOverride || template.isForceOverride()) && templateEty.getMergeStrategy() == null || ConfigurationConstants.MERGE_STRATEGY_OVERRIDE.equals(templateEty.getMergeStrategy())) {
                try (Formatter formatter = new Formatter()) {
                    formatter.format("Overriding %1$-40s FROM %2$-50s TO %3$s ...", originalFile.getName(), templateEty.getName(), resolvedTargetDestinationPath);
                    LOG.info(formatter.out().toString());
                    progressCallback.accept(formatter.out().toString(), 1);
                }
                progressCallback.accept("Generating " + template.getId() + " for " + generatorInput, 1);
                generateTemplateAndWriteFile(tmpOriginalFile, templateEty, templateEngine, model, targetCharset);
            } else if (templateEty.getMergeStrategy() != null) {
                try (Formatter formatter = new Formatter()) {
                    formatter.format("Merging    %1$-40s FROM %2$-50s TO %3$s ...", originalFile.getName(), templateEty.getName(), resolvedTargetDestinationPath);
                    LOG.info(formatter.out().toString());
                    progressCallback.accept(formatter.out().toString(), 1);
                }
                String patch = null;
                try (Writer out = new StringWriter()) {
                    templateEngine.process(templateEty, model, out, targetCharset);
                    patch = out.toString();
                    String mergeResult = null;
                    Merger merger = PluginRegistry.getMerger(templateEty.getMergeStrategy());
                    if (merger != null) {
                        mergeResult = merger.merge(tmpOriginalFile, patch, targetCharset);
                    } else {
                        throw new PluginNotAvailableException("merge strategy '" + templateEty.getMergeStrategy() + "'", null);
                    }
                    if (mergeResult != null) {
                        LOG.debug("Merge {} with char set {}.", tmpOriginalFile.getName(), targetCharset);
                        FileUtils.writeStringToFile(tmpOriginalFile, mergeResult, targetCharset);
                    } else {
                        throw new PluginProcessingException("Merger " + merger.getType() + " returned null on merge(...), which is not allowed.");
                    }
                } catch (MergeException e) {
                    writeBrokenPatchFile(targetCharset, tmpOriginalFile, patch);
                    // enrich merge exception to provide template ID
                    throw new MergeException(e, templateEty.getAbsoluteTemplatePath());
                } catch (IOException e) {
                    throw new CobiGenRuntimeException("Could not write file " + tmpOriginalFile.toPath() + " after merge.", e);
                }
            }
        } else {
            try (Formatter formatter = new Formatter()) {
                formatter.format("Generating %1$-40s FROM %2$-50s TO %3$s ...", originalFile.getName(), templateEty.getName(), resolvedTargetDestinationPath);
                LOG.info(formatter.out().toString());
                progressCallback.accept(formatter.out().toString(), 1);
            }
            generateTemplateAndWriteFile(tmpOriginalFile, templateEty, templateEngine, model, targetCharset);
        }
    }
}
Also used : CobiGenRuntimeException(com.devonfw.cobigen.api.exception.CobiGenRuntimeException) Formatter(java.util.Formatter) IOException(java.io.IOException) PluginNotAvailableException(com.devonfw.cobigen.api.exception.PluginNotAvailableException) PluginProcessingException(com.devonfw.cobigen.impl.exceptions.PluginProcessingException) TemplatesConfiguration(com.devonfw.cobigen.impl.config.TemplatesConfiguration) Template(com.devonfw.cobigen.impl.config.entity.Template) InputReader(com.devonfw.cobigen.api.extension.InputReader) Trigger(com.devonfw.cobigen.impl.config.entity.Trigger) Merger(com.devonfw.cobigen.api.extension.Merger) StringWriter(java.io.StringWriter) TextTemplateEngine(com.devonfw.cobigen.api.extension.TextTemplateEngine) MergeException(com.devonfw.cobigen.api.exception.MergeException) UnknownTemplateException(com.devonfw.cobigen.impl.exceptions.UnknownTemplateException) Map(java.util.Map) File(java.io.File) PathExpressionResolver(com.devonfw.cobigen.impl.config.resolver.PathExpressionResolver) Writer(java.io.Writer) StringWriter(java.io.StringWriter)

Example 17 with Template

use of com.devonfw.cobigen.impl.config.entity.Template in project cobigen by devonfw.

the class ConfigurationInterpreterImpl method getMatchingTemplates.

@Cached
@Override
public List<TemplateTo> getMatchingTemplates(Object matcherInput) throws InvalidConfigurationException {
    LOG.debug("Matching templates requested.");
    List<TemplateTo> templates = Lists.newLinkedList();
    for (TemplatesConfiguration templatesConfiguration : getMatchingTemplatesConfigurations(matcherInput)) {
        for (Template template : templatesConfiguration.getAllTemplates()) {
            templates.add(new TemplateTo(template.getName(), template.getMergeStrategy(), templatesConfiguration.getTrigger().getId()));
        }
    }
    LOG.debug("{} matching templates found.", templates.size());
    return templates;
}
Also used : TemplateTo(com.devonfw.cobigen.api.to.TemplateTo) TemplatesConfiguration(com.devonfw.cobigen.impl.config.TemplatesConfiguration) Template(com.devonfw.cobigen.impl.config.entity.Template) Cached(com.devonfw.cobigen.api.annotation.Cached)

Example 18 with Template

use of com.devonfw.cobigen.impl.config.entity.Template in project cobigen by devonfw.

the class ConfigurationInterpreterImpl method convertIncrements.

/**
 * Converts a {@link List} of {@link Increment}s with their parent {@link Trigger} to a {@link List} of
 * {@link IncrementTo}s
 *
 * @param increments the {@link List} of {@link Increment}s
 * @param trigger the parent {@link Trigger}
 * @param matchingTriggerIds the {@link List} of matching trigger Id
 * @return the {@link List} of {@link IncrementTo}s
 */
// TODO create ToConverter
private List<IncrementTo> convertIncrements(List<Increment> increments, Trigger trigger, List<String> matchingTriggerIds) {
    List<IncrementTo> incrementTos = Lists.newLinkedList();
    for (Increment increment : increments) {
        String triggerId = increment.getTrigger().getId();
        if (!triggerId.equals(trigger.getId())) {
            // Check if the external trigger also matches
            if (!matchingTriggerIds.contains(triggerId)) {
                // Abort generation
                throw new InvalidConfigurationException("An external incrementRef to " + increment.getTrigger().getId() + "::" + increment.getName() + " is referenced from " + trigger.getId() + " but its trigger does not match");
            }
        }
        List<TemplateTo> templates = Lists.newLinkedList();
        for (Template template : increment.getTemplates()) {
            templates.add(new TemplateTo(template.getName(), template.getMergeStrategy(), triggerId));
        }
        incrementTos.add(new IncrementTo(increment.getName(), increment.getDescription(), triggerId, templates, convertIncrements(increment.getDependentIncrements(), trigger, matchingTriggerIds)));
    }
    return incrementTos;
}
Also used : IncrementTo(com.devonfw.cobigen.api.to.IncrementTo) Increment(com.devonfw.cobigen.impl.config.entity.Increment) TemplateTo(com.devonfw.cobigen.api.to.TemplateTo) InvalidConfigurationException(com.devonfw.cobigen.api.exception.InvalidConfigurationException) Template(com.devonfw.cobigen.impl.config.entity.Template)

Example 19 with Template

use of com.devonfw.cobigen.impl.config.entity.Template in project cobigen by devonfw.

the class ConfigurationInterpreterImpl method resolveTemplateDestinationPath.

@Override
public Path resolveTemplateDestinationPath(Path targetRootPath, TemplateTo template, Object input) {
    Trigger trigger = this.configurationHolder.readContextConfiguration().getTrigger(template.getTriggerId());
    InputValidator.validateTrigger(trigger);
    TriggerInterpreter triggerInterpreter = PluginRegistry.getTriggerInterpreter(trigger.getType());
    // the GenerationReportTo won't be further processed
    Variables variables = new ContextVariableResolver(input, trigger).resolveVariables(triggerInterpreter, new GenerationReportTo());
    Template templateEty = this.configurationHolder.readTemplatesConfiguration(trigger).getTemplate(template.getId());
    try {
        String resolvedDestinationPath = new PathExpressionResolver(variables).evaluateExpressions(templateEty.getUnresolvedTargetPath());
        return targetRootPath.resolve(resolvedDestinationPath).normalize();
    } catch (UnknownContextVariableException e) {
        throw new CobiGenRuntimeException("Could not resolve path '" + templateEty.getUnresolvedTargetPath() + "' for input '" + (input instanceof Object[] ? Arrays.toString((Object[]) input) : input.toString()) + "' and template '" + templateEty.getAbsoluteTemplatePath() + "'. Available variables: " + variables.toString());
    }
}
Also used : TriggerInterpreter(com.devonfw.cobigen.api.extension.TriggerInterpreter) Variables(com.devonfw.cobigen.impl.config.entity.Variables) Trigger(com.devonfw.cobigen.impl.config.entity.Trigger) GenerationReportTo(com.devonfw.cobigen.api.to.GenerationReportTo) CobiGenRuntimeException(com.devonfw.cobigen.api.exception.CobiGenRuntimeException) ContextVariableResolver(com.devonfw.cobigen.impl.model.ContextVariableResolver) PathExpressionResolver(com.devonfw.cobigen.impl.config.resolver.PathExpressionResolver) UnknownContextVariableException(com.devonfw.cobigen.impl.exceptions.UnknownContextVariableException) Template(com.devonfw.cobigen.impl.config.entity.Template)

Example 20 with Template

use of com.devonfw.cobigen.impl.config.entity.Template in project cobigen by devonfw.

the class TemplatesConfigurationReaderTest method testRelocate_overlappingTemplateExtensionAndScan.

/**
 * Tests the rewriting of the destination path of a scanned template by using the {@link TemplateExtension}
 * configuration element. The explicitly configured destination path from the configuration should have precedence
 * over the relocated path of the template scan.
 */
@Test
public void testRelocate_overlappingTemplateExtensionAndScan() {
    // given
    String templateScanDestinationPath = "src/main/java/";
    String templatesConfigurationRoot = testFileRootPath + "valid_relocate_templateExt_vs_scan/";
    TemplatesConfigurationReader target = new TemplatesConfigurationReader(new File(testFileRootPath).toPath(), "valid_relocate_templateExt_vs_scan/");
    Trigger trigger = new Trigger("id", "type", "valid_relocate", Charset.forName("UTF-8"), new LinkedList<Matcher>(), new LinkedList<ContainerMatcher>());
    // when
    Map<String, Template> templates = target.loadTemplates(trigger);
    assertThat(templates).hasSize(2);
    // validation
    String staticRelocationPrefix = "../api/";
    String scanRelTemplatePath = "$_rootpackage_$/$_component_$/common/api/";
    Template template = verifyScannedTemplate(templates, "$_EntityName_$.java", scanRelTemplatePath, templatesConfigurationRoot, staticRelocationPrefix, templateScanDestinationPath);
    String templateName = "$_EntityName_$2.java";
    template = templates.get(templateName);
    assertThat(template).isNotNull();
    String pathWithName = scanRelTemplatePath + templateName;
    assertThat(template.getRelativeTemplatePath()).isEqualTo("templates/" + pathWithName);
    assertThat(template.getAbsoluteTemplatePath().toString().replace('\\', '/')).isEqualTo(templatesConfigurationRoot + "templates/" + pathWithName);
    assertThat(template.getUnresolvedTemplatePath()).isEqualTo(templateScanDestinationPath + scanRelTemplatePath + templateName);
    assertThat(template.getUnresolvedTargetPath()).isEqualTo(templateName);
}
Also used : Trigger(com.devonfw.cobigen.impl.config.entity.Trigger) ContainerMatcher(com.devonfw.cobigen.impl.config.entity.ContainerMatcher) Matcher(com.devonfw.cobigen.impl.config.entity.Matcher) ContainerMatcher(com.devonfw.cobigen.impl.config.entity.ContainerMatcher) TemplatesConfigurationReader(com.devonfw.cobigen.impl.config.reader.TemplatesConfigurationReader) File(java.io.File) Template(com.devonfw.cobigen.impl.config.entity.Template) AbstractUnitTest(com.devonfw.cobigen.unittest.config.common.AbstractUnitTest) Test(org.junit.Test)

Aggregations

Template (com.devonfw.cobigen.impl.config.entity.Template)26 Trigger (com.devonfw.cobigen.impl.config.entity.Trigger)19 File (java.io.File)17 ContainerMatcher (com.devonfw.cobigen.impl.config.entity.ContainerMatcher)16 Matcher (com.devonfw.cobigen.impl.config.entity.Matcher)16 AbstractUnitTest (com.devonfw.cobigen.unittest.config.common.AbstractUnitTest)16 Test (org.junit.Test)16 TemplatesConfigurationReader (com.devonfw.cobigen.impl.config.reader.TemplatesConfigurationReader)15 InvalidConfigurationException (com.devonfw.cobigen.api.exception.InvalidConfigurationException)5 Increment (com.devonfw.cobigen.impl.config.entity.Increment)5 Path (java.nio.file.Path)5 ConfigurationHolder (com.devonfw.cobigen.impl.config.ConfigurationHolder)4 TemplatePath (com.devonfw.cobigen.impl.config.entity.TemplatePath)4 TextTemplateEngine (com.devonfw.cobigen.api.extension.TextTemplateEngine)3 TemplatesConfiguration (com.devonfw.cobigen.impl.config.TemplatesConfiguration)3 HashMap (java.util.HashMap)3 CobiGenRuntimeException (com.devonfw.cobigen.api.exception.CobiGenRuntimeException)2 TemplateTo (com.devonfw.cobigen.api.to.TemplateTo)2 TemplateFolder (com.devonfw.cobigen.impl.config.entity.TemplateFolder)2 TemplateExtension (com.devonfw.cobigen.impl.config.entity.io.TemplateExtension)2