| /** |
| * |
| * Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation |
| * |
| * |
| * This copyright notice shows up in the generated Java code |
| * |
| */ |
| |
| package org.eclipse.osbp.xtext.basic.generator |
| |
| import java.io.File |
| import java.io.FileInputStream |
| import java.io.FileOutputStream |
| import java.io.IOException |
| import java.util.Collections |
| import java.util.Enumeration |
| import java.util.Properties |
| import java.util.TreeSet |
| import org.apache.commons.lang.ClassUtils |
| import org.eclipse.xpand2.XpandExecutionContext |
| import org.eclipse.xtext.Grammar |
| import org.eclipse.xtext.GrammarUtil |
| import org.eclipse.xtext.generator.Generator |
| import org.eclipse.xtext.generator.grammarAccess.GrammarAccessFragment |
| import org.eclipse.xtext.generator.grammarAccess.ResourceSaveIndicator |
| import org.slf4j.LoggerFactory |
| |
| /** |
| * <b>For the complete to-do-list support keyword information DSL editors <code>org.eclipse.osbp.xtext.basic.ui.BasicDSLUiModuleHelper</code></b> |
| * <hr> |
| * <ul> |
| * <li>Generate {your}DSLGrammarI18nGenerator: |
| * <pre> |
| * public class {your}DSLGrammarI18nGenerator extends BasicDSLGrammarI18nGenerator { |
| * } |
| * </pre> |
| * </li> |
| * <li>Append Grammar I18n generator at the end of the MWE2 workflow: |
| * <pre> |
| * // parse grammar and generate i18n grammar |
| * fragment = org.eclipse.osbp.xtext.{your}.generator.{your}DSLGrammarI18nGenerator auto-inject {} |
| * </pre> |
| * </li> |
| * </ul> |
| */ |
| class BasicDslGrammarI18nGenerator extends GrammarAccessFragment { |
| |
| private val LOGGER = LoggerFactory.getLogger(this.class); |
| |
| /** |
| * generate a i18n property if it doesn't exist yet |
| * @param i18nProperties the properties to generate into |
| * @param i18nKey the key to generate |
| * @return 1 if generated, 0 otherwise |
| */ |
| protected def int generateI18nProperty(Properties i18nProperties, String i18nKey) { |
| var modified = 0 |
| if (!i18nProperties.containsKey(i18nKey)) { |
| i18nProperties.put(i18nKey, "") // '''@TODO - describe «i18nKey»'''.toString) |
| modified = 1 |
| LOGGER.info('''«i18nKey» created: «i18nProperties.get(i18nKey)»''') |
| } |
| else { |
| LOGGER.debug('''«i18nKey» already exists: «i18nProperties.get(i18nKey)»''') |
| } |
| return modified |
| } |
| |
| /** |
| * traverse the given grammar for rules and keywords and generate non-existing i18n properies |
| */ |
| override void generate(Grammar grammar, XpandExecutionContext ctx) { |
| |
| // --- the package for the grammar rules --- |
| val grammarPackage = ClassUtils.getPackageCanonicalName(grammar.name) |
| |
| LOGGER.debug('''start extraction of rules and keywords from «grammarPackage» for generation of i18n descriptions''') |
| |
| // --- the file path containing the i18n properties |
| val i18nFilePath = ctx.getOutput().getOutlet(Generator.PLUGIN_UI).getPath() + "/i18n" |
| val i18nFullPath = i18nFilePath + "/I18N.properties" |
| var modifications = 0 |
| val isSaving = new ResourceSaveIndicator() as ResourceSaveIndicator |
| |
| // --- use a sorted-by-key properties object --- |
| var i18nProperties = new Properties { |
| override synchronized Enumeration<Object> keys() { |
| return Collections.enumeration(new TreeSet<Object>(super.keySet())); |
| } |
| } |
| |
| // --- try to load any existing i18n properties --- |
| try { |
| i18nProperties.load(new FileInputStream(i18nFullPath)) |
| } |
| catch (Exception e) { |
| } |
| |
| isSaving?.set(Boolean.TRUE); |
| |
| try { |
| // --- traverse any rules of this grammar --- |
| for (rule : grammar.rules) { |
| val i18nKey = '''«grammarPackage».«rule.name»'''.toString |
| modifications += i18nProperties.generateI18nProperty(i18nKey) |
| // --- traverse any keywords of this rule --- |
| for (keyword : GrammarUtil.containedKeywords(rule)) { |
| val i18nEnumKey = '''«i18nKey».«keyword.value»'''.toString |
| // --- but ignore any single-character keywords, for example (){}.,: etc. --- |
| if (keyword.value.length > 1) { |
| modifications += i18nProperties.generateI18nProperty(i18nEnumKey) |
| } |
| else { |
| LOGGER.info('''«i18nKey» ignored due to single character keyword length»''') |
| } |
| } |
| } |
| } catch (Exception e) { |
| LOGGER.error(e.getMessage(), e); |
| } |
| |
| try { |
| // --- only if any modifications founds, try to save them --- |
| if (modifications > 0) { |
| val i18nDirectory = new File(i18nFilePath) |
| if (!i18nDirectory.exists) { |
| i18nDirectory.mkdirs |
| } |
| i18nProperties.store(new FileOutputStream(i18nFullPath), "") |
| } |
| } catch (IOException e) { |
| LOGGER.error(e.getMessage(), e); |
| } finally { |
| isSaving?.set(Boolean.FALSE); |
| } |
| |
| LOGGER.debug('''ended extraction of rules and keywords from «grammarPackage» for generation of i18n descriptions: «modifications» modification(s) found''') |
| } |
| } |