blob: f38895039f6bad5b13fa985f7d056617a14c337b [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*
*************************************************************/
import java.util.*;
import java.io.*;
public class JPropEx
{
private String inputFileArg = "";
private String outputFileArg = "";
private String pathPrefixArg = "";
private String pathPostfixArg = "";
private String projectArg = "";
private String rootArg = "";
private Vector forcedLangsArg;
private Vector langsArg;
private String inputSdfFileArg = "";
private boolean isQuiet = false;
private final String resourceType = "javaproperties";
private final String sourceLanguage = "en-US";
static final int JAVA_TYPE = 0;
static final int JAVA_ENUS_TYPE = 1;
static final int EXTENSION_TYPE = 2;
public JPropEx()
{
//data = new SdfData();
}
public JPropEx( String args[] )
{
super();
parseArguments( args );
testCL();
//testArguments();
if( inputSdfFileArg != null && inputSdfFileArg.length() > 0 )
merge();
else
extract();
}
private String getSimpleArg( String[] args , int x )
{
if( x < args.length ) x++;
else
{
System.err.println("ERROR: Missing arg for "+args[ x ]+"\n");
help();
}
return args[ x ];
}
private Vector getComplexArg( String[] args , int x )
{
if( x < args.length ) x++;
else
{
System.err.println("ERROR: Missing arg for "+args[ x ]+"\n");
help();
}
String value = args[ x ];
Vector values = new Vector( Arrays.asList( value.split(",") ) );
return values;
}
private void testCL()
{
if( inputFileArg.length()>0 && ( ( pathPrefixArg.length()>0 && pathPostfixArg.length()>0 ) || outputFileArg.length()>0 ) && projectArg.length()>0 && rootArg.length()>0 && langsArg.size()>0 )
if( ( inputSdfFileArg.length()>0 && ( outputFileArg.length()>0 || ( pathPrefixArg.length()>0 && pathPostfixArg.length()>0 ) ) ) || ( inputFileArg.length()>0 && outputFileArg.length()>0 ) )
return;
System.out.println("ERROR: Strange parameters!");
help();
System.exit( -1 );
}
private void help()
{
System.out.println("jpropex -> extract / merge java properties files");
System.out.println("-p <project> -r <project_root> -i <input>|@<input> -o <output> -x <path1> -y <path2> -m <sdf_file> -l <lang>\n");
System.out.println("Example:\ncd /data/cws/l10ntooling17/DEV300/ooo/reportbuilder/java/com/sun/star/report/function/metadata");
System.out.println("Extract:\njpropex -p reportbuilder -r ../../../../../../.. -i Title-Function.properties -o new.sdf -l en-US");
System.out.println("Merge: use either ( -x path -y more_path ) or ( -o ) and ( -i filename ) or ( -i @filename ). @filename contains a list with files");
System.out.println("jpropex -p reportbuilder -r ../../../../../../.. -x ../../../../../../../unxlngx6.pro/class/com/sun/star/report/function/metadata -y ivo -i @abc -l all -lf en-US,de,fr,pt -m ../../../../../../../common.pro/misc/reportbuilder/java/com/sun/star/report/function/metadata/localize.sdf");
System.out.println("jpropex -p reportbuilder -r ../../../../../../.. -x ../../../../../../../unxlngx6.pro/class/com/sun/star/report/function/metadata -y ivo -i @abc -l all -lf en-US,de,fr,pt -m ../../../../../../../common.pro/misc/reportbuilder/java/com/sun/star/report/function/metadata/localize.sdf");
System.out.println("jpropex -p reportbuilder -r ../../../../../../.. -o ../../../../../../../unxlngx6.pro/class/com/sun/star/report/function/metadata/ -i Title-Function.properties -l all -lf en-US,de,fr,pt -m ../../../../../../../common.pro/misc/reportbuilder/java/com/sun/star/report/function/metadata/localize.sdf");
System.out.println("jpropex -p reportbuilder -r ../../../../../../.. -x ../../../../../../../unxlngx6.pro/class/com/sun/star/report/function/metadata -y ivooo -i Title-Function.properties -l all -lf en-US,de,fr,pt -m ../../../../../../../common.pro/misc/reportbuilder/java/com/sun/star/report/function/metadata/localize.sdf");
System.exit( -1 );
}
private void extract()
{
SdfData data = new SdfData();
java.util.Properties prop = loadProp( inputFileArg );
// Get a prototype that already contains the most common settings
SdfEntity dolly = prepareSdfObj( inputFileArg );
String key;
SdfEntity currentStr;
String value;
String str;
for( Enumeration e = prop.propertyNames() ; e.hasMoreElements() ; )
{
key = (String) e.nextElement();
currentStr = (SdfEntity) dolly.clone();
// Set the new GID and the string text
currentStr.setGid( key );
value = prop.getProperty( key , "" );
//if( value.equals("") ) System.err.println("Warning: in file "+inputFileArg+" the string with the key "+key+" has a empty string!");
str = (prop.getProperty( key )).replaceAll("\t" , " " ); // remove tab
str = str.replaceAll("\n"," "); // remove return
currentStr.setText( str );
if( str.length() > 0 )
data.add( currentStr );
}
data.write( outputFileArg );
}
private SdfEntity prepareSdfObj( String filename )
{
String path = makeAbs( filename ).trim();
String myRootArg = makeAbs( rootArg ).trim();
myRootArg = myRootArg.replace( "\\","/");
myRootArg += "/";
path = path.replace("\\","/");
path = path.replace( myRootArg, "" );
path = path.replace("/","\\");
// TODO: Make this static
java.text.SimpleDateFormat dateformat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = dateformat.format( new Date() );
return new SdfEntity( projectArg , path , "0" /* dummy1 */ , resourceType , "", "" , "" , "" , "0" /* dummy2 */ ,
sourceLanguage , "", "" , "" , "" , date );
}
private void merge()
{
SdfData data = getSdfData();
if( inputFileArg.startsWith("@") )
{
// Read files
Vector fileList = readFileList( inputFileArg );
for( Enumeration e = fileList.elements(); e.hasMoreElements(); )
mergeFile( (String) e.nextElement() , data , false );
}
else
{
// Single file
mergeFile( inputFileArg , data , true );
}
}
private Vector readFileList( String filename )
{
Vector lines = new Vector();
try
{
BufferedReader in = new BufferedReader( new FileReader( filename.substring( 1 ) ) );
while( in.ready() )
lines.add( in.readLine().trim() );
}
catch( IOException e )
{
System.out.println("ERROR: Can't open file '"+filename.substring( 1 )+"'");
System.exit( -1 );
}
return lines;
}
private void mergeFile( String filename , SdfData data , boolean isSingleFile )
{
int type = detectFormat( filename );
java.util.Properties sourceProp = loadProp( filename );
Vector langs = getLanguages( data );
HashMap props = new HashMap();
// Create a properties object for every language
for( Enumeration e = langs.elements(); e.hasMoreElements();)
{
props.put( (String)e.nextElement() , new java.util.Properties() );
}
// Get a prototype that already contains the most common settings
SdfEntity dolly = prepareSdfObj( filename );
String key;
String sourceString;
SdfEntity curStr;
SdfEntity curEntity;
SdfEntity mergedEntity;
String curLang;
for( Enumeration e = sourceProp.propertyNames() ; e.hasMoreElements() ; ) // For all property keys
{
key = (String) e.nextElement();
sourceString = sourceProp.getProperty( key );
curStr = (SdfEntity) dolly.clone();
curStr.setGid( key );
for( Enumeration lang = langs.elements(); lang.hasMoreElements(); ) // merge in every language
{
curEntity = (SdfEntity) curStr.clone();
curLang = (String) lang.nextElement();
curEntity.setLangid( curLang );
mergedEntity = data.get( curEntity );
if( mergedEntity == null )
{
// in case there is no translation then fallback to the en-US source string
( (java.util.Properties) props.get( curLang )).setProperty( curEntity.getGid() , sourceString );
}
else
{
// Set the merged text from the sdf file
( (java.util.Properties) props.get( curLang )).setProperty( mergedEntity.getGid() , mergedEntity.getText() ); // TODO: Quoting ???
}
}
}
// Now write them out
String lang;
for( Iterator i = props.keySet().iterator() ; i.hasNext() ; )
{
lang = (String) i.next();
writeSinglePropertiesFile( filename , (java.util.Properties) props.get( lang ) , lang , isSingleFile , type );
}
}
private void writeSinglePropertiesFile( String filename , java.util.Properties prop , String lang , boolean isSingleFile , int type )
{
// Prepare path to file
int filenameIdx = filename.lastIndexOf( "/" ) > 0 ? filename.lastIndexOf( "/" )+1 : 0 ;
String path = new String();
String name = new String();
String lcLang = lang.toLowerCase();
// use of -x <path> -y <more_path>
// -> <path>/<lang>/<more_path>
if( pathPrefixArg != null && pathPrefixArg.length()>0 && pathPostfixArg != null && pathPostfixArg.length()>0 )
{
path = new StringBuffer().append( pathPrefixArg ).append( "/" ).append( lcLang ).append( "/" ).append( pathPostfixArg ).append( "/" ).toString();
name += formatFilename( filename , filenameIdx , lang , type );
}
//use of -i <one_filename>
else if( !isSingleFile && outputFileArg != null && outputFileArg.length()>0 )
{
//name = outputFileArg;
path = outputFileArg;
name += formatFilename( filename , filenameIdx , lang , type );
}
//use of -i @<file_containing_many_filenames>
else if( isSingleFile && outputFileArg != null && outputFileArg.length()>0 )
{
//name = outputFileArg;
path = outputFileArg;
name += formatFilename( filename , filenameIdx , lang , type );
}
else
{
System.err.println("ERROR: No outputfile specified .. either -o or -x -y !");
System.exit( -1 );
}
File dir = new File( path );
try
{
if( !dir.exists() && path.length()>0 )
{
if( !dir.mkdirs() )
{
System.out.println("ERROR: Can't create directory '"+path+"' !!!");
System.exit( -1 );
}
}
}
catch( SecurityException e )
{
System.out.println("ERROR: Can't create directory '"+path+"'!!!Wrong Permissions?");
System.exit( -1 );
}
path += name;
// Write the properties file
//System.out.println("DBG: Writing to "+path);
try{
BufferedOutputStream out = new BufferedOutputStream( new FileOutputStream( path ) );
if( prop == null )
System.out.println("DBG: prop == null!!!");
prop.store( out , "" ); // Legal headers?
}
catch( IOException e )
{
System.out.println("ERROR: Can't write file '"+path+"' !!!!");
System.exit( -1 );
}
}
// we have different types of properties in the source code
// each needs a different file nameing scheme
private int detectFormat( String filename )
{
if( filename.endsWith( "_en_US.properties" ) )
return EXTENSION_TYPE;
else if( filename.endsWith("_en_us.properties" ) )
return JAVA_ENUS_TYPE;
else if( filename.endsWith( ".properties" ) )
return JAVA_TYPE;
// Can not detect, exit
System.err.println("ERROR: Invalid file name. Only allowed (case sensitive!) *_en_US.properties , *_en_us.properties or *.properties\n");
System.exit(-1);
return JAVA_TYPE; // dummy
}
private String formatFilename( String filename , int filenameIdx , String lang , int type )
{
if( !lang.equals( "en-US" ) )
{
// Parse iso code
int pos = lang.indexOf("-");
String langpart1 = new String();
String langpart2 = new String();
if( pos == -1 )
{
langpart1 = lang;
}
else if( pos > 0 )
{
langpart1 = lang.substring( 0 , pos );
langpart2 = lang.substring( pos+1 , lang.length() );
}
// change filename according to the type
switch( type )
{
// -> de_DE
case EXTENSION_TYPE:
lang = langpart1.toLowerCase();
if( langpart2.length() > 0 ) // -> en_US
lang += "_" + langpart2.toUpperCase();
else // -> de_DE
lang += "_" + langpart1.toUpperCase();
return new StringBuffer().append( filename.substring( filenameIdx , filename.lastIndexOf( "_en_US.properties" ) ) )
.append( "_" ).append( lang.replaceAll("-","_") ).append( ".properties" ).toString();
// -> de
case JAVA_ENUS_TYPE:
lang = langpart1.toLowerCase();
if( langpart2.length() > 0 )
lang += "_" + langpart2.toLowerCase();
return new StringBuffer().append( filename.substring( filenameIdx , filename.lastIndexOf( "_en_us.properties" ) ) )
.append( "_" ).append( lang.replaceAll("-","_") ).append( ".properties" ).toString();
// -> de
case JAVA_TYPE:
lang = langpart1.toLowerCase();
if( langpart2.length() > 0 )
lang += "_" + langpart2.toLowerCase();
return new StringBuffer().append( filename.substring( filenameIdx , filename.lastIndexOf( ".properties" ) ) )
.append( "_" ).append( lang.replaceAll("-","_") ).append( ".properties" ).toString();
default:
System.err.println("ERROR: Something is really broken here, l10ntools/java/jprop/java/JPropEx.java :: formatFilename()");
System.exit( -1 );
break;
}
}
return filename; // don't change en-US source file name
}
private SdfData getSdfData()
{
SdfData data = new SdfData( inputSdfFileArg );
data.read();
return data;
}
private Vector getLanguages( SdfData data )
{
Vector langs = new Vector();
if( ((String)langsArg.get( 0 )).equalsIgnoreCase( "all" ) ) // for "-l all" use all languages found in the -m sdf file
langs.addAll( data.getLanguages() );
else
langs.addAll( langsArg ); // use the langs giving by -l
if( forcedLangsArg != null )
langs.addAll( forcedLangsArg );
return removeDupes( langs );
}
private Vector removeDupes( Vector vec )
{
Collection coll = new LinkedHashSet( vec );
return new Vector( coll );
}
private java.util.Properties loadProp( String filename )
{
java.util.Properties prop = new java.util.Properties();
try
{
prop.load( new BufferedInputStream( new NoLocalizeFilter( new FileInputStream( filename ) ) ) );
}
catch( IOException e )
{
System.err.println("ERROR: Can't read file '"+filename+"'!!!");
}
return prop;
}
private void parseArguments( String[] args )
{
if( args.length == 0 )
{
System.out.println("ERROR: No args???");
help();
System.exit( -1 );
}
for( int x = 0; x < args.length ; x++ )
{
if( args[ x ].equalsIgnoreCase("-i") )
{
// Input resource file
inputFileArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-o") )
{
// Output sdf file
outputFileArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-x") )
{
// path prefix
pathPrefixArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-y") )
{
// path postfix
pathPostfixArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-p") )
{
// project
projectArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-r") )
{
// root
rootArg = getSimpleArg( args , x );
rootArg = makeAbs( rootArg );
}
else if( args[ x ].equalsIgnoreCase("-lf") )
{
// forced langs
forcedLangsArg = getComplexArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-l") )
{
// langs
langsArg = getComplexArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-m") )
{
// input sdf file
inputSdfFileArg = getSimpleArg( args , x );
}
else if( args[ x ].equalsIgnoreCase("-qq") )
{
isQuiet = true;
}
}
}
private String makeAbs( String path )
{
File file;
try
{
file = new File( path );
return file.getCanonicalPath();
}catch( IOException e )
{
e.printStackTrace();
System.exit( -1 );
}
return null;
}
/* private boolean testArguments()
{
// nice merge
if( inputSdfFileArg != null && inputSdfFileArg.length()>0 )
// nice merge
return projectArg != null && rootArg != null && inputFileArg != null && pathPrefixArg != null && pathPostfixArg != null && langsArg != null &&
projectArg.length()>0 && rootArg.length()>0 && inputFileArg.length()>0 && pathPrefixArg.length()>0 && pathPostfixArg.length()>0 && langsArg.size()>0 ;
else
// nice extract
return projectArg != null && rootArg != null && inputFileArg != null && outputFileArg != null && langsArg != null &&
projectArg.length()>0 && rootArg.length()>0 && inputFileArg.length()>0 && outputFileArg.length()>0 && langsArg.size()>0;
}
*/
}