blob: b0edba1c8085c48c0549f2ba4a364046ddf69d3c [file] [log] [blame]
/**
*
* 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''')
}
}