org.nuiton.i18n.plugin.parser.AbstractI18nParserMojo Maven / Gradle / Ivy
/*
* *##%
* I18n :: Maven Plugin
* Copyright (C) 2007 - 2010 CodeLutin
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* ##%*
*/
package org.nuiton.i18n.plugin.parser;
import org.nuiton.i18n.plugin.AbstractI18nMojo;
import org.nuiton.io.FileUpdater;
import org.nuiton.io.SortedProperties;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Abstract implementation for parsing goal.
*
* @author tony
*/
public abstract class AbstractI18nParserMojo extends AbstractI18nMojo implements Parser {
/** @return the outGetter to use for the instance (java.getter,...) */
protected abstract String getOutGetter();
/** @return the starting regex expression to catch keys in key modifier */
protected abstract String getKeyModifierStart();
/** @return the ending regex expression to catch keys in key modifier */
protected abstract String getKeyModifierEnd();
/** @return the default includes to add to directory scanner */
protected abstract String[] getDefaultIncludes();
/** @return the default excludes to add to directory scanner */
protected abstract String[] getDefaultExcludes();
/** @return the default src directory to use in directory scanner */
protected abstract File getDefaultBasedir();
public abstract FileUpdater newFileUpdater(SourceEntry entry);
/**
* Active la modification de cle.
*
* Note: par defaut, on ne l'active pas (build sur serveur non ui).
*
* @parameter expression="${i18n.keysModifier}" default-value="false"
*/
protected boolean keysModifier;
/**
* treate default entry
*
* @parameter expression="${i18n.treateDefaultEntry}" default-value="true"
*/
protected boolean treateDefaultEntry;
/**
* Source entries (src+includes+excludes) .
*
* @parameter expression="${i18n.entries}"
*/
protected I18nSourceEntry[] entries;
/**
* flag to display touched files while parsing.
*
* Note: the value will be always true if {@link #verbose} is
* set at true.
*
* @parameter expression="${i18n.showTouchedFiles}" default-value="${maven.verbose}"
* @since 0.9
*/
protected boolean showTouchedFiles;
/**
* flag to save at eachfile treated the getter file
*
* @parameter expression="${i18n.safeMode}" default-value="false"
* @since 0.9
*/
protected boolean safeMode;
/**
* flag to save previous getter in a backup before doing parsing.
*
* Note: by default, do not perform backup (but it was here originaly so let
* it possible...)
*
* @parameter expression="${i18n.backupGetter}" default-value="false"
* @since 1.0.2
*/
protected boolean backupGetter;
/** Liste des évènements */
protected List events = new ArrayList();
protected SortedProperties result;
protected SortedProperties oldParser;
protected SortedProperties oldLanguage;
protected int fileTreated;
protected long t0;
protected boolean touchFile;
protected List treadedFiles;
/** logger verbeux */
protected I18nLogger verboseLog;
public boolean isStrictMode() {
return strictMode;
}
protected I18nLogger getVerboseLog() {
return verboseLog;
}
@Override
public void init() throws Exception {
verboseLog = new I18nLogger(this);
super.init();
t0 = System.nanoTime();
result = new SortedProperties(encoding);
oldParser = new SortedProperties(encoding);
oldLanguage = new SortedProperties(encoding);
createDirectoryIfNecessary(out);
// evenements
if (keysModifier) {
addParserEvent(KeysModifier.getInstance(
getKeyModifierStart(), getKeyModifierEnd(), encoding));
}
// check there is something to treate
if ((entries == null || entries.length == 0) && !treateDefaultEntry) {
// nothing to do
throw new IllegalStateException(
"No entry defined and treateDefaultEntry is false, " +
"will skip the goal.");
}
if (verbose && entries != null && entries.length > 0) {
if (getLog().isInfoEnabled()) {
getLog().info("detected entries : " + entries.length);
for (SourceEntry e : entries) {
getLog().info(e.toString() + ", specific goal ? " +
e.getSpecificGoal());
}
}
}
treadedFiles = new ArrayList();
// if (!silent && verbose) {
// showTouchedFiles = true;
// }
}
@Override
protected void doAction() throws Exception {
if (!silent && safeMode) {
getLog().info("config - safeMode is on (could be slower).");
}
if (!silent && strictMode) {
getLog().info("config - strictMode is on (all files will be" +
" parsed).");
}
// Reprise sur un ancien parsing
File oldParserFile = getGetterFile(out, getOutGetter(), true);
File saveFile = getBackupFile(oldParserFile);
oldParser.load(oldParserFile);
if (backupGetter) {
backupFile(oldParserFile);
}
// Anciennes cles disponnibles
//fixme : pourquoi on utilise un bundle precis ? le premier ici,
// je ne comprends pas
File oldLanguageFile = getI18nFile(src, artifactId, locales[0], true);
oldLanguage.load(oldLanguageFile);
// Parsing
parse();
// Suppression du fichier sauvegarder
if (!backupGetter) {
deleteFile(saveFile);
}
int i = treadedFiles.size();
if (fileTreated == 0) {
if (!silent) {
getLog().info("Nothing was parsed - all files are up to date.");
}
} else {
if (!silent) {
getLog().info(getVerboseLog().getLogEntry(
"Parsing is done. [treated file(s) : " + i + '/' +
fileTreated + "]", fileTreated, 0, t0));
}
addGetter();
}
}
@Override
public void parse() throws IOException {
if (treateDefaultEntry) {
addDefaultEntry();
}
long t00 = System.nanoTime();
for (I18nSourceEntry entry : entries) {
I18nLogger vLog = getVerboseLog();
vLog.setEntry(entry);
boolean skip = entry.init(this);
if (skip) {
if (!silent && verbose) {
getLog().info("skip - " + entry.getSkipMessage());
}
continue;
}
long t000 = System.nanoTime();
int nbFiles = entry.getFiles().length;
if (!silent) {
// if (!silent && verbose) {
vLog.infoEntry("start", vLog.getLogEntry(
"[incoming file(s) : " + entry.getFoudFiles() + "]",
0, 0, 0));
}
int nbTreatedFilesBefore = treadedFiles.size();
// launch parser for found files
parseEntry(entry);
if (!silent && verbose) {
// log skipped files
for (String skipFile : entry.getSkipFiles()) {
vLog.setFile(new File(entry.getBasedir(), skipFile));
vLog.infoFile("skip", null);
}
}
fileTreated += nbFiles;
if (!silent) {
// if (!silent && verbose) {
int nbTreatedFilesAfter = treadedFiles.size() -
nbTreatedFilesBefore;
vLog.infoEntry(
"end",
vLog.getLogEntry(
"[treated file(s) : " + nbTreatedFilesAfter +
"/" + nbFiles + "]", nbFiles, t000,
t00));
}
t00 = System.nanoTime();
}
}
/**
* Add the default entry to entries given in configuration.
*
* This is a convinient method to simplify the configuration of the plugin.
*/
protected void addDefaultEntry() {
if (verbose) {
getLog().info("add default entry");
}
boolean hasEntries = entries != null && entries.length > 0;
I18nSourceEntry[] tmp =
new I18nSourceEntry[hasEntries ? entries.length + 1 : 1];
if (hasEntries) {
System.arraycopy(entries, 0, tmp, 0, entries.length);
}
tmp[tmp.length - 1] = new I18nSourceEntry();
entries = tmp;
}
/**
* launch parsing on a given entry.
*
* @param entry currentEntry to treate
* @throws IOException if any io pb.
*/
protected final void parseEntry(SourceEntry entry) throws IOException {
long t00 = System.nanoTime();
String[] files = entry.getFiles();
int beforeEntryResultSize = result.size();
for (int i = 0, max = files.length; i < max; i++) {
String file1 = files[i];
long t000 = System.nanoTime();
String fileName = entry.getBasedir().getAbsolutePath() +
File.separator + file1;
File file = new File(fileName);
for (ParserEvent event : events) {
event.eventChangeFile(file);
}
I18nLogger vLog = getVerboseLog();
vLog.setFile(file);
touchFile = false;
int size = result.size();
if (!silent && verbose) {
vLog.infoFile("parse", null);
}
parseFile(file);
//TC-20090214 pour des questions de performance, on ne sauvegarde
// pas a chaque traitement de fichier, les clefs mais une fois pour
// chaque source entry
// Detection de nouvelles cles, sauvegarde du fichier pour pouvoir
// le restaurer en cas de plantage
if (safeMode) {
if (size != result.size()) {
saveGetterFile();
}
}
if (touchFile) {
if (showTouchedFiles) {
vLog.infoFile("touch", null);
}
treadedFiles.add(file);
if (getLog().isDebugEnabled()) {
vLog.debug(vLog.getLogEntry(fileName, i, t000, t00));
}
}
for (ParserEvent event : events) {
event.eventNextFile(file);
}
}
if (!safeMode && beforeEntryResultSize < result.size()) {
// Detection de nouvelles cles, sauvegarde du fichier
saveGetterFile();
}
}
/**
* Save the result in the getter file.
*
* @throws IOException if any io pb
*/
protected void saveGetterFile() throws IOException {
File getterFile = getGetterFile(out, getOutGetter(), false);
result.store(getterFile);
}
/**
* Ajoute un évènement
*
* @param parserEvent l'évènement d'ajout
*/
protected void addParserEvent(ParserEvent parserEvent) {
events.add(parserEvent);
}
/**
* Supprime un évènement
*
* @param parserEvent l'évènement de suppression
*/
protected void removeParserEvent(ParserEvent parserEvent) {
events.remove(parserEvent);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy