/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com * ******************************************************************************* * * 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.pentaho.di.ui.i18n; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Properties; import org.pentaho.di.core.Const; import org.pentaho.di.core.changed.ChangedFlag; import org.pentaho.di.core.exception.KettleException; /** * This class contains a messages store: for a certain Locale and for a certain messages package, it keeps all the keys * and values. This class can read and write messages files... * * @author matt * */ public class MessagesStore extends ChangedFlag { private String sourceFolder; private String locale; private String messagesPackage; private Map<String, String> messagesMap; private String filename; private Map<String, Map<String, List<KeyOccurrence>>> sourcePackageOccurrences; /** * Create a new messages store * * @param locale * The locale to read * @param sourceFolder * The source folder to read * @param messagesPackage * The messages package to consider * @param sourcePackageOccurrences * The occurrences map */ public MessagesStore( String locale, String sourceFolder, String messagesPackage, Map<String, Map<String, List<KeyOccurrence>>> sourcePackageOccurrences ) { messagesMap = new Hashtable<String, String>(); this.sourceFolder = sourceFolder; this.locale = locale; this.messagesPackage = messagesPackage; this.sourcePackageOccurrences = sourcePackageOccurrences; if ( sourceFolder == null ) { throw new RuntimeException( "Source folder can not be null, messages package : " + messagesPackage + ", locale: " + locale ); } } public void read( List<String> directories ) throws KettleException { try { filename = getLoadFilename( directories ); Properties properties = new Properties(); FileInputStream fileInputStream = new FileInputStream( new File( filename ) ); properties.load( fileInputStream ); fileInputStream.close(); // Put all the properties in our map... // for ( Object key : properties.keySet() ) { Object value = properties.get( key ); messagesMap.put( (String) key, (String) value ); } } catch ( Exception e ) { String keys = "["; Map<String, List<KeyOccurrence>> po = sourcePackageOccurrences.get( sourceFolder ); List<KeyOccurrence> keyList = po == null ? new ArrayList<KeyOccurrence>() : po.get( messagesPackage ); if ( keyList == null ) { keyList = new ArrayList<KeyOccurrence>(); } boolean first = true; for ( KeyOccurrence occ : keyList ) { if ( first ) { first = false; } else { keys += ", "; } keys += occ.getKey() + "/" + occ.getFileObject().toString(); } keys += "]"; throw new KettleException( "Unable to read messages file for locale : '" + locale + "' and package '" + messagesPackage + "', keys=" + keys, e ); } } public void write() throws KettleException { if ( filename == null ) { throw new KettleException( "Please specify a filename before saving messages store for package '" + messagesPackage + "' and locale '" + locale + "" ); } write( filename ); } public void write( String filename ) throws KettleException { try { File file = new File( filename ); if ( !file.exists() ) { File parent = file.getParentFile(); if ( !parent.exists() ) { parent.mkdirs(); // create the messages/ folder } } Properties properties = new Properties(); for ( String key : messagesMap.keySet() ) { properties.put( key, messagesMap.get( key ) ); } FileOutputStream fileOutputStream = new FileOutputStream( file ); String comment = "File generated by Pentaho Translator for package '" + messagesPackage + "' in locale '" + locale + "'" + Const.CR + Const.CR; properties.store( fileOutputStream, comment ); fileOutputStream.close(); setChanged( false ); } catch ( IOException e ) { throw new KettleException( "Unable to save messages properties file '" + filename + "'", e ); } } /** * Find a suitable filename for the specified locale and messages package. It tries to find the file in the specified * directories in the order that they are specified. * * @param alternativeSourceFolders * * @param directories * the source directories to try and map the messages files against. * @return the filename that was found. */ public String getLoadFilename( List<String> alternativeSourceFolders ) throws FileNotFoundException { String path = calcFolderName( sourceFolder ); // First try the source folder of the Java file // if ( new File( path ).exists() ) { return path; } // Then try the rest of the project source folders in order of occurrence .. // for ( String altSourceFolder : alternativeSourceFolders ) { path = calcFolderName( altSourceFolder ); if ( new File( path ).exists() ) { return path; } } throw new FileNotFoundException( "package file could not be found for file in folder " + sourceFolder + ", with messages package " + messagesPackage + " in locale " + locale ); } private String calcFolderName( String sourceFolderPath ) { String localeUpperLower = locale.substring( 0, 3 ).toLowerCase() + locale.substring( 3 ).toUpperCase(); String filename = "messages_" + localeUpperLower + ".properties"; String path = sourceFolderPath + File.separator + messagesPackage.replace( '.', '/' ) + File.separator + "messages" + File.separator + filename; return path; } public String getSourceDirectory( List<String> directories ) { String localeUpperLower = locale.substring( 0, 3 ).toLowerCase() + locale.substring( 3 ).toUpperCase(); String filename = "messages_" + localeUpperLower + ".properties"; String path = messagesPackage.replace( '.', '/' ); for ( String directory : directories ) { String attempt = directory + Const.FILE_SEPARATOR + path + Const.FILE_SEPARATOR + "messages" + Const.FILE_SEPARATOR + filename; if ( new File( attempt ).exists() ) { return directory; } } return null; } /** * Find a suitable filename to save this information in the specified locale and messages package. It needs a source * directory to save the package in * * @param directory * the source directory to save the messages file in. * @return the filename that was generated. */ public String getSaveFilename( String directory ) { String localeUpperLower = locale.substring( 0, 3 ).toLowerCase() + locale.substring( 3 ).toUpperCase(); String filename = "messages_" + localeUpperLower + ".properties"; String path = messagesPackage.replace( '.', '/' ); return directory + Const.FILE_SEPARATOR + path + Const.FILE_SEPARATOR + "messages" + Const.FILE_SEPARATOR + filename; } /** * @return the locale */ public String getLocale() { return locale; } /** * @param locale * the locale to set */ public void setLocale( String locale ) { this.locale = locale; } /** * @return the messagesPackage */ public String getMessagesPackage() { return messagesPackage; } /** * @param messagesPackage * the messagesPackage to set */ public void setMessagesPackage( String messagesPackage ) { this.messagesPackage = messagesPackage; } /** * @return the map */ public Map<String, String> getMessagesMap() { return messagesMap; } /** * @param messsagesMap * the map to set */ public void setMessagesMap( Map<String, String> messsagesMap ) { this.messagesMap = messsagesMap; } public String getFilename() { return filename; } public void setFilename( String filename ) { this.filename = filename; } public String getSourceFolder() { return sourceFolder; } public void setSourceFolder( String sourceFolder ) { this.sourceFolder = sourceFolder; } }