parent
91e1e5640b
commit
1afefebd0f
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,207 @@
|
||||
// CreateTranslationMasters.java
|
||||
// -------------------------------------
|
||||
// part of YACY
|
||||
// (C) by Michael Peter Christen; mc@yacy.net
|
||||
// first published on http://www.anomic.de
|
||||
// Frankfurt, Germany, 2004
|
||||
//
|
||||
// This file ist contributed by Burkhard Buelte
|
||||
// last major change: 2016-04-05
|
||||
//
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
// $LastChangedBy$
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 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 Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package net.yacy.utils.translation;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import net.yacy.cora.util.ConcurrentLog;
|
||||
import net.yacy.data.Translator;
|
||||
|
||||
/**
|
||||
* Utility to create a translation master file from all existing translation
|
||||
* with check file.exists and translation text exists.
|
||||
* Also can join existing translation with master (currently ristrictive,
|
||||
* means only translation text exist in master are included in resultin Map
|
||||
*/
|
||||
public class CreateTranslationMasters extends TranslatorXliff {
|
||||
|
||||
/**
|
||||
* Helper to add a translation text to the map
|
||||
*
|
||||
* @param translation to add the text to
|
||||
* @param relFileName relative filename the translation belongs to
|
||||
* @param sourceLngTxt the english source text
|
||||
* @param targetLngTxt the translated text
|
||||
* @return true = if map was modified, otherwise false
|
||||
*/
|
||||
protected boolean addTranslation(Map<String, Map<String, String>> translation, final String relFileName, final String sourceLngTxt, final String targetLngTxt) {
|
||||
boolean modified = false;
|
||||
|
||||
Map<String, String> transFile;
|
||||
if (translation.containsKey(relFileName)) {
|
||||
transFile = translation.get(relFileName);
|
||||
} else {
|
||||
transFile = new LinkedHashMap<String, String>();
|
||||
translation.put(relFileName, transFile);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
String oldLngTxt = transFile.put(sourceLngTxt, targetLngTxt);
|
||||
if (oldLngTxt == null) {
|
||||
modified = targetLngTxt != null;
|
||||
} else if (!oldLngTxt.equals(targetLngTxt)) {
|
||||
modified = true;
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a master translation list by reading all translation files
|
||||
* If a masterOutputFile exists, content is preserved (loaded first)
|
||||
*
|
||||
* @param masterOutpuFile output file (xliff format)
|
||||
* @throws IOException
|
||||
*/
|
||||
public void createMasterTranslationLists(File masterOutputFile) throws IOException {
|
||||
Map<String, Map<String, String>> xliffTrans;
|
||||
if (masterOutputFile.exists()) // if file exists, conserve existing master content (may be updated by external tool)
|
||||
xliffTrans = TranslatorXliff.loadTranslationsListsFromXliff(masterOutputFile);
|
||||
else
|
||||
xliffTrans = new TreeMap<String, Map<String, String>>();
|
||||
|
||||
List<String> lngFiles = Translator.langFiles(new File("locales"));
|
||||
for (String filename : lngFiles) {
|
||||
// load translation list
|
||||
ConcurrentLog.info("TRANSLATOR", "include translation file " + filename);
|
||||
Map<String, Map<String, String>> origTrans = Translator.loadTranslationsLists(new File("locales", filename));
|
||||
|
||||
for (String transfilename : origTrans.keySet()) { // get translation filename
|
||||
File checkfile = new File("htroot", transfilename);
|
||||
if (checkfile.exists()) { // include in master only if file exists
|
||||
// load content to compare translation text is included
|
||||
StringBuilder content = new StringBuilder();
|
||||
BufferedReader br = null;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(new FileInputStream(checkfile), StandardCharsets.UTF_8));
|
||||
String line = null;
|
||||
while ((line = br.readLine()) != null) {
|
||||
content.append(line).append(net.yacy.server.serverCore.CRLF_STRING);
|
||||
}
|
||||
br.close();
|
||||
} catch (final IOException e) {
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (final Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// compare translation list
|
||||
Map<String, String> origList = origTrans.get(transfilename);
|
||||
for (String sourcetxt : origList.keySet()) {
|
||||
if (content.indexOf(sourcetxt) >= 0) {
|
||||
String origVal = origList.get(sourcetxt);
|
||||
// it is possible that intentionally empty translation is given
|
||||
// in this case xliff target is missing (=null)
|
||||
if (origVal != null && !origVal.isEmpty()) { // if translation exists
|
||||
addTranslation(xliffTrans, transfilename, sourcetxt, null); // add to master, set target text null
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ConcurrentLog.fine("TRANSLATOR", "skip file for translation " + transfilename + " (from " + filename + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
// save as xliff file w/o language code
|
||||
saveAsXliff(null, masterOutputFile, xliffTrans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins translation master (xliff) and existing translation (lng)
|
||||
*
|
||||
* @param xlifmaster master (with en text to be translated)
|
||||
* @param lngfile existing translation
|
||||
* @return resulting map with all entries from master and translation from lngfile
|
||||
* @throws IOException
|
||||
*/
|
||||
public Map<String, Map<String, String>> joinMasterTranslationLists(File xlifmaster, File lngfile) throws IOException {
|
||||
|
||||
final String filename = lngfile.getName();
|
||||
Map<String, Map<String, String>> xliffTrans = TranslatorXliff.loadTranslationsListsFromXliff(xlifmaster);
|
||||
// load translation list
|
||||
System.out.println("join into master translation file " + filename);
|
||||
Map<String, Map<String, String>> origTrans = Translator.loadTranslationsLists(lngfile);
|
||||
|
||||
for (String transfilename : origTrans.keySet()) { // get translation filename
|
||||
// compare translation list
|
||||
Map<String, String> origList = origTrans.get(transfilename);
|
||||
Map<String, String> masterList = xliffTrans.get(transfilename);
|
||||
for (String sourcetxt : origList.keySet()) {
|
||||
if ((masterList != null) && (masterList.isEmpty() || masterList.containsKey(sourcetxt))) { // only if included in master (as all languages are in there but checked for occuance
|
||||
String origVal = origList.get(sourcetxt);
|
||||
// it is possible that intentionally empty translation is given
|
||||
// in this case xliff target is missing (=null)
|
||||
if (origVal != null && !origVal.isEmpty()) {
|
||||
addTranslation(xliffTrans, transfilename, sourcetxt, origVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return xliffTrans;
|
||||
}
|
||||
|
||||
/**
|
||||
* for testing to create on master and joined translation results for all lang's
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
File outputdirectory = new File ("test/DATA");
|
||||
|
||||
CreateTranslationMasters ctm = new CreateTranslationMasters();
|
||||
try {
|
||||
if (!outputdirectory.exists()) outputdirectory.mkdir();
|
||||
File xlfmaster = new File(outputdirectory, "master.lng.xlf");
|
||||
ctm.createMasterTranslationLists(xlfmaster); // write the language neutral translation master as xliff
|
||||
|
||||
List<String> lngFiles = Translator.langFiles(new File("locales"));
|
||||
for (String filename : lngFiles) {
|
||||
Map<String, Map<String, String>> lngmaster = ctm.joinMasterTranslationLists(xlfmaster, new File("locales", filename)); // create individual language translation files from master
|
||||
File xlftmp = new File(outputdirectory, filename + ".xlf");
|
||||
System.out.println("output new master translation file " + xlftmp.toString() + " and " + filename);
|
||||
ctm.saveAsXliff(filename.substring(0, 2), xlftmp, lngmaster);
|
||||
ctm.saveAsLngFile(filename.substring(0, 2), new File(outputdirectory, filename), lngmaster);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ConcurrentLog.logException(ex);
|
||||
}
|
||||
ConcurrentLog.shutdown();
|
||||
}
|
||||
}
|
@ -0,0 +1,319 @@
|
||||
// TranslatorXliff.java
|
||||
// -------------------------------------
|
||||
// part of YACY
|
||||
// (C) by Michael Peter Christen; mc@yacy.net
|
||||
// first published on http://www.anomic.de
|
||||
// Frankfurt, Germany, 2004
|
||||
//
|
||||
// This file ist contributed by Burkhard Buelte
|
||||
// last major change: 2016-03-28
|
||||
//
|
||||
// $LastChangedDate$
|
||||
// $LastChangedRevision$
|
||||
// $LastChangedBy$
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation; either version 2 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 Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
package net.yacy.utils.translation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
|
||||
import net.yacy.cora.util.ConcurrentLog;
|
||||
import net.yacy.data.Translator;
|
||||
|
||||
import org.oasis.xliff.core_12.Body;
|
||||
import org.oasis.xliff.core_12.Target;
|
||||
import org.oasis.xliff.core_12.TransUnit;
|
||||
import org.oasis.xliff.core_12.Xliff;
|
||||
|
||||
/**
|
||||
* Wordlist based translator
|
||||
*
|
||||
* Translator which can read and write translation lists from a
|
||||
* <a href="http://docs.oasis-open.org/xliff/v1.2/os/xliff-core.html">XLIFF
|
||||
* 1.2</a> file with phrases or single words to translate a string or a file
|
||||
*/
|
||||
public class TranslatorXliff extends Translator {
|
||||
|
||||
/**
|
||||
* Load translationLists for one language from a Xliff File.
|
||||
*
|
||||
* @param translationFile the File, which contains the Lists
|
||||
* @return a HashMap, which contains for each File a HashMap with
|
||||
* translations.
|
||||
*/
|
||||
public static Map<String, Map<String, String>> loadTranslationsListsFromXliff(final File xliffFile) {
|
||||
|
||||
final Map<String, Map<String, String>> lngLists = new TreeMap<String, Map<String, String>>(); //list of translationLists for different files.
|
||||
/**
|
||||
* read xliff xml file into a xliff object
|
||||
* <xliff>
|
||||
* <file original="filename">
|
||||
* <body>
|
||||
* <trans-unit>
|
||||
* <source>text</source>
|
||||
* <target>text</target>
|
||||
* </trans-unit>
|
||||
* <trans-unit>....
|
||||
* </body>
|
||||
* </file>
|
||||
* <file>.....
|
||||
* </xliff>
|
||||
*/
|
||||
Xliff xliffTranslation;
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(xliffFile);
|
||||
JAXBContext ctx = JAXBContext.newInstance(org.oasis.xliff.core_12.Xliff.class);
|
||||
Unmarshaller un = ctx.createUnmarshaller();
|
||||
Object obj = un.unmarshal(fis);
|
||||
if (obj instanceof org.oasis.xliff.core_12.Xliff) {
|
||||
xliffTranslation = (org.oasis.xliff.core_12.Xliff) obj;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Object> xlfFileList = xliffTranslation.getAnyAndFile();
|
||||
for (Object xlfobj : xlfFileList) {
|
||||
org.oasis.xliff.core_12.File xlfFileNode = (org.oasis.xliff.core_12.File) xlfobj;
|
||||
Map<String, String> translationList; //current Translation Table (maintaining input order)
|
||||
String forFile = xlfFileNode.getOriginal();
|
||||
if (lngLists.containsKey(forFile)) {
|
||||
translationList = lngLists.get(forFile);
|
||||
} else {
|
||||
translationList = new LinkedHashMap<String, String>(); //current Translation Table (maintaining input order)
|
||||
lngLists.put(forFile, translationList);
|
||||
}
|
||||
|
||||
Body xlfBody = xlfFileNode.getBody();
|
||||
List<Object> xlfTransunitList = xlfBody.getGroupOrTransUnitOrBinUnit();
|
||||
for (Object xlfTransunit : xlfTransunitList) {
|
||||
if (xlfTransunit instanceof TransUnit) {
|
||||
String source = ((TransUnit) xlfTransunit).getSource().getContent().get(0).toString();
|
||||
Target target = ((TransUnit) xlfTransunit).getTarget();
|
||||
if (target != null) {
|
||||
if ("translated".equals(target.getState())) {
|
||||
List<Object> targetContentList = target.getContent();
|
||||
String targetContent = targetContentList.get(0).toString();
|
||||
translationList.put(source, targetContent);
|
||||
} else {
|
||||
translationList.put(source, null);
|
||||
}
|
||||
} else {
|
||||
translationList.put(source, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (JAXBException je) {
|
||||
ConcurrentLog.warn("TRANSLATOR", je.getMessage());
|
||||
} catch (FileNotFoundException ex) {
|
||||
ConcurrentLog.warn("TRANSLATOR", "File not found: " + xliffFile.getAbsolutePath());
|
||||
}
|
||||
return lngLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps (overrides) Translator.loadTranslationsLists to read from xliff file
|
||||
* if file extension is .xlf or .xliff (otherwise load xx.lng file)
|
||||
*
|
||||
* @param xliffFile
|
||||
* @return translatio map
|
||||
*/
|
||||
public static Map<String, Map<String, String>> loadTranslationsLists(final File xliffFile) {
|
||||
if (xliffFile.getName().toLowerCase().endsWith(".xlf") || xliffFile.getName().toLowerCase().endsWith(".xliff")) {
|
||||
return loadTranslationsListsFromXliff(xliffFile);
|
||||
} else {
|
||||
return Translator.loadTranslationsLists(xliffFile);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the internal translation map as XLIFF 1.2 file
|
||||
*
|
||||
* @param targetLanguage the target language code, if null target is omitted
|
||||
* in output file and only source text stored
|
||||
* @param xliffFile name of the output XLIFF file (typically with .xlf
|
||||
* extension)
|
||||
* @param lng the YaCy translation for one language
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
public boolean saveAsXliff(final String targetLanguageCode, File xliffFile, Map<String, Map<String, String>> lng) {
|
||||
|
||||
final String sourceLanguage = "en"; // source language is always English
|
||||
OutputStreamWriter output;
|
||||
|
||||
try {
|
||||
output = new OutputStreamWriter(new FileOutputStream(xliffFile), StandardCharsets.UTF_8.name());
|
||||
output.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
output.write("<xliff version='1.2' xmlns='urn:oasis:names:tc:xliff:document:1.2'> \n");
|
||||
for (String afilemap : lng.keySet()) {
|
||||
output.write("<file original=\"" + afilemap + "\" " // original required in xliff 1.2
|
||||
+ " source-language=\"" + sourceLanguage + "\" "); // required in xliff 1.2
|
||||
if (targetLanguageCode != null && !targetLanguageCode.isEmpty()) {
|
||||
output.write(" target-language=\"" + targetLanguageCode + "\" "); // required in xliff 1.2
|
||||
}
|
||||
output.write(" datatype=\"html\">\n"); // required in xliff 1.2
|
||||
|
||||
output.write(" <body>\n");
|
||||
Map<String, String> txtmap = lng.get(afilemap);
|
||||
for (String source : txtmap.keySet()) {
|
||||
String target = txtmap.get(source);
|
||||
// we use hashCode of source string to get same id in different xliff files for same translation text
|
||||
output.write(" <trans-unit id=\"" + Integer.toHexString(source.hashCode()) + "\" xml:space=\"preserve\" approved=\"no\"");
|
||||
if (target == null || target.isEmpty()) { // omitt target text if not available
|
||||
output.write(" translate=\"yes\">\n");
|
||||
output.write(" <source>" + toXmlStr(source) + "</source>\n");
|
||||
} else {
|
||||
output.write(">\n");
|
||||
output.write(" <source>" + toXmlStr(source) + "</source>\n");
|
||||
output.write(" <target" + (target.equals(source) ? "" : " state='translated'") + ">" + toXmlStr(target) + "</target>\n");
|
||||
}
|
||||
output.write(" </trans-unit>\n");
|
||||
}
|
||||
output.write(" </body>\n");
|
||||
output.write("</file>\n\n");
|
||||
}
|
||||
|
||||
output.write("</xliff>\n");
|
||||
output.close();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to write translation entries for one file
|
||||
*
|
||||
* @param filename relative path file name
|
||||
* @param textlist the translation list for filename
|
||||
* @param output output file
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeFileSection(final String filename, final Map<String, String> textlist, OutputStreamWriter output) throws IOException {
|
||||
output.write("#File: " + filename + "\n"
|
||||
+ "#---------------------------\n"); // required in 1.2
|
||||
|
||||
for (String source : textlist.keySet()) {
|
||||
String target = textlist.get(source);
|
||||
// we use hashCode of source string to get same id in different xliff files for same translation text
|
||||
if (target != null && !target.isEmpty()) { // omitt target text if not available
|
||||
if (source.equals(target)) {
|
||||
output.write("#" + source + "==" + target + "\n"); // no translation needed (mark #)
|
||||
} else {
|
||||
output.write(source + "==" + target + "\n");
|
||||
}
|
||||
} else {
|
||||
output.write("#"+source + "==" + source + "\n"); // no translation available (mark #)
|
||||
}
|
||||
}
|
||||
output.write("#-----------------------------\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the internal translation map as XLIFF 1.2 file
|
||||
*
|
||||
* @param targetLanguage the target language code, if null target is omitted
|
||||
* in output file and only source text stored
|
||||
* @param xliffFile name of the output XLIFF file (typically with .xlf
|
||||
* extension)
|
||||
* @param lng the YaCy translation for one language
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
public boolean saveAsLngFile(final String targetLanguageCode, File lngFile, Map<String, Map<String, String>> lng) {
|
||||
|
||||
OutputStreamWriter output;
|
||||
|
||||
try {
|
||||
output = new OutputStreamWriter(new FileOutputStream(lngFile), StandardCharsets.UTF_8.name());
|
||||
output.write("# " + (targetLanguageCode == null ? "master" : targetLanguageCode) + ".lng\n");
|
||||
output.write("# -----------------------\n");
|
||||
output.write("# This is a part of YaCy, a peer-to-peer based web search engine\n\n");
|
||||
output.write("# Each translation list starts with #File: relative/path/to/file\n");
|
||||
output.write("# followed by the translations OriginalText==TranslatedText (in one line)\n");
|
||||
output.write("# Comment lines or not translated lines start with #\n\n");
|
||||
|
||||
// special handling of "ConfigLanguage_p.html" to list on top of all other
|
||||
// because of some important identifier
|
||||
Map<String, String> txtmap = lng.get("ConfigLanguage_p.html");
|
||||
writeFileSection("ConfigLanguage_p.html", txtmap, output);
|
||||
|
||||
for (String afilemap : lng.keySet()) {
|
||||
txtmap = lng.get(afilemap);
|
||||
if (!"ConfigLanguage_p.html".equals(afilemap)) {
|
||||
writeFileSection(afilemap, txtmap, output);
|
||||
}
|
||||
}
|
||||
output.write("# EOF");
|
||||
output.close();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to make valid xml content text as text may contain html markup
|
||||
* (the reverse on read is done automatically)
|
||||
* @param html input string
|
||||
* @return xml string
|
||||
*/
|
||||
private String toXmlStr(String s) {
|
||||
|
||||
int control = s.indexOf("&");
|
||||
while (control >= 0) {
|
||||
s = s.substring(0, control) + "&" + s.substring(control + 1);
|
||||
if (control < s.length()) {
|
||||
control++;
|
||||
}
|
||||
control = s.indexOf("&", control);
|
||||
}
|
||||
|
||||
control = s.indexOf("<");
|
||||
while (control >= 0) {
|
||||
s = s.substring(0, control) + "<" + s.substring(control + 1);
|
||||
if (control < s.length()) {
|
||||
control++;
|
||||
}
|
||||
control = s.indexOf("<", control);
|
||||
}
|
||||
|
||||
control = s.indexOf(">");
|
||||
while (control >= 0) {
|
||||
s = s.substring(0, control) + ">" + s.substring(control + 1);
|
||||
if (control < s.length()) {
|
||||
control++;
|
||||
}
|
||||
control = s.indexOf(">", control);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
@ -1,214 +1,214 @@
|
||||
/**
|
||||
* ChartPlotter
|
||||
* Copyright 2005 by Michael Christen
|
||||
* First released 26.10.2005 at http://yacy.net
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program in the file lgpl21.txt
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.yacy.visualization;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.yacy.cora.util.ConcurrentLog;
|
||||
|
||||
|
||||
public class ChartPlotter extends RasterPlotter {
|
||||
|
||||
public static final int DIMENSION_RIGHT = 0;
|
||||
public static final int DIMENSION_TOP = 1;
|
||||
public static final int DIMENSION_LEFT = 2;
|
||||
public static final int DIMENSION_BOTTOM = 3;
|
||||
public static final int DIMENSION_ANOT0 = 4;
|
||||
public static final int DIMENSION_ANOT1 = 5;
|
||||
public static final int DIMENSION_ANOT2 = 6;
|
||||
public static final int DIMENSION_ANOT3 = 7;
|
||||
|
||||
private final int leftborder;
|
||||
private final int rightborder;
|
||||
private final int topborder;
|
||||
private final int bottomborder;
|
||||
private final int[] scales = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final int[] pixels = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final int[] offsets = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final Long[] colnames = new Long[]{0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl};
|
||||
private final Long[] colscale = new Long[]{null,null,null,null,null,null,null,null};
|
||||
private final String[] tablenames = new String[]{"","","","","","","",""};
|
||||
|
||||
public ChartPlotter(final int width, final int height, final Long backgroundColor, final Long foregroundColor, final Long lightColor,
|
||||
final int leftborder, final int rightborder, final int topborder, final int bottomborder,
|
||||
final String name, final String subline) {
|
||||
super(width, height, RasterPlotter.DrawMode.MODE_REPLACE, backgroundColor);
|
||||
this.leftborder = leftborder;
|
||||
this.rightborder = rightborder;
|
||||
this.topborder = topborder;
|
||||
this.bottomborder = bottomborder;
|
||||
//this.name = name;
|
||||
//this.backgroundColor = backgroundColor;
|
||||
//this.foregroundColor = foregroundColor;
|
||||
if (name != null) {
|
||||
if (foregroundColor != null) this.setColor(foregroundColor);
|
||||
PrintTool.print(this, width / 2 - name.length() * 3, 6, 0, name, -1, 100);
|
||||
}
|
||||
if (subline != null) {
|
||||
if (lightColor != null) this.setColor(lightColor);
|
||||
PrintTool.print(this, width / 2 - subline.length() * 3, 14, 0, subline, -1, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* assign a metric to a graph. The dimension can be left or right (the measure at the side-border of the graph)
|
||||
* @param dimensionType
|
||||
* @param scale is the measure (the number) to be printed on the border per pixelscale
|
||||
* @param pixelperscale is the number of pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
public void declareDimension(final int dimensionType, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
this.scales[dimensionType] = Math.max(1, scale);
|
||||
this.pixels[dimensionType] = pixelperscale;
|
||||
this.offsets[dimensionType] = offset;
|
||||
this.colnames[dimensionType] = colorNaming;
|
||||
this.colscale[dimensionType] = colorScale;
|
||||
this.tablenames[dimensionType] = name;
|
||||
if ((dimensionType == DIMENSION_LEFT) || (dimensionType == DIMENSION_RIGHT)) {
|
||||
drawVerticalScale((dimensionType == DIMENSION_LEFT), scale, pixelperscale, offset, colorNaming, colorScale, name);
|
||||
}
|
||||
if ((dimensionType == DIMENSION_TOP) || (dimensionType == DIMENSION_BOTTOM)) {
|
||||
drawHorizontalScale((dimensionType == DIMENSION_TOP), scale, pixelperscale, offset, colorNaming, colorScale, name);
|
||||
}
|
||||
}
|
||||
|
||||
public void chartDot(final int dimension_x, final int dimension_y, final float coord_x, final int coord_y, final int dotsize, final String anot, final int anotAngle) {
|
||||
final int x = (int) ((coord_x - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
assert this.scales[dimension_y] != 0;
|
||||
final int y = (coord_y - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
if (dotsize == 1) plot(this.leftborder + x, this.height - this.bottomborder - y, 100);
|
||||
else dot(this.leftborder + x, this.height - this.bottomborder - y, dotsize, true, 100);
|
||||
if (anot != null) PrintTool.print(this, this.leftborder + x + dotsize + 2 + ((anotAngle == 315) ? -9 : 0), this.height - this.bottomborder - y + ((anotAngle == 315) ? -3 : 0), anotAngle, anot, (anotAngle == 0) ? (anot.length() * 6 + x > this.width ? 1 : -1) : ((anotAngle == 315) ? 1 : 0), 100);
|
||||
}
|
||||
|
||||
public void chartLine(final int dimension_x, final int dimension_y, final float coord_x1, final int coord_y1, final float coord_x2, final int coord_y2) {
|
||||
final int x1 = (int) ((coord_x1 - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
final int y1 = (coord_y1 - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
final int x2 = (int) ((coord_x2 - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
final int y2 = (coord_y2 - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
line(this.leftborder + x1, this.height - this.bottomborder - y1, this.leftborder + x2, this.height - this.bottomborder - y2, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw a horizontal scale border
|
||||
* @param top - if true, this the top-horizontal scale, otherwise it is at the bottom
|
||||
* @param scale is the measure (the number) to be printed on the vertical border per pixelscale
|
||||
* @param pixelperscale is the number of vertical pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
private void drawHorizontalScale(final boolean top, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
final int y = (top) ? this.topborder : this.height - this.bottomborder;
|
||||
int x = this.leftborder;
|
||||
int s = offset;
|
||||
while (x < this.width - this.rightborder) {
|
||||
if ((colorScale != null) && (x > this.leftborder) && (x < (this.width - this.rightborder))) {
|
||||
setColor(colorScale);
|
||||
line(x, this.topborder, x, this.height - this.bottomborder, 100);
|
||||
}
|
||||
setColor(colorNaming);
|
||||
line(x, y - 3, x, y + 3, 100);
|
||||
PrintTool.print(this, x, (top) ? y - 3 : y + 9, 0, Integer.toString(s), -1, 80);
|
||||
x += pixelperscale;
|
||||
s += scale;
|
||||
}
|
||||
setColor(colorNaming);
|
||||
PrintTool.print(this, this.width - this.rightborder, (top) ? y - 9 : y + 15, 0, name, 1, 80);
|
||||
line(this.leftborder - 4, y, this.width - this.rightborder + 4, y, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw the vertical scale of the graph
|
||||
* @param left if true this is the vertical bar on the left, otherwise it is the one on the right
|
||||
* @param scale is the measure (the number) to be printed on the vertical border per pixelscale
|
||||
* @param pixelperscale is the number of vertical pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
private void drawVerticalScale(final boolean left, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
assert pixelperscale > 0;
|
||||
assert scale > 0;
|
||||
if (pixelperscale <= 0) return; // this would not meet the termination condition in the while loop
|
||||
final int x = (left) ? this.leftborder : this.width - this.rightborder;
|
||||
int y = this.height - this.bottomborder;
|
||||
int s = offset;
|
||||
String s1;
|
||||
int s1max = 0;
|
||||
while (y > this.topborder) {
|
||||
if ((colorScale != null) && (y > this.topborder) && (y < (this.height - this.bottomborder))) {
|
||||
setColor(colorScale);
|
||||
line(this.leftborder, y, this.width - this.rightborder, y, 100);
|
||||
}
|
||||
setColor(colorNaming);
|
||||
line(x - 3, y, x + 3, y, 100);
|
||||
s1 = (s >= 1000000 && s % 1000000 == 0) ? Integer.toString(s / 1000000) + "M" : (s >= 1000 && s % 1000 == 0) ? Integer.toString(s / 1000) + "K" : Integer.toString(s);
|
||||
if (s1.length() > s1max) s1max = s1.length();
|
||||
PrintTool.print(this, (left) ? this.leftborder - 4 : this.width - this.rightborder + 4, y, 0, s1, (left) ? 1 : -1, 80);
|
||||
y -= pixelperscale;
|
||||
s += scale;
|
||||
}
|
||||
setColor(colorNaming);
|
||||
PrintTool.print(this, (left) ? Math.max(6, x - s1max * 6 - 6) : x + s1max * 6 + 9, this.height - this.bottomborder, 90, name, -1, 80);
|
||||
line(x, this.topborder - 4, x, this.height - this.bottomborder + 4, 100);
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
final long bg = 0xFFFFFF;
|
||||
final long fg = 0x000000;
|
||||
final long scale = 0xCCCCCC;
|
||||
final long green = 0x008800;
|
||||
final long blue = 0x0000FF;
|
||||
final ChartPlotter ip = new ChartPlotter(660, 240, bg, fg, fg, 30, 30, 20, 20, "PEER PERFORMANCE GRAPH: PAGES/MINUTE and USED MEMORY", "");
|
||||
ip.declareDimension(DIMENSION_BOTTOM, 60, 60, -600, fg, scale, "TIME/SECONDS");
|
||||
//ip.declareDimension(DIMENSION_TOP, 10, 40, "000000", null, "count");
|
||||
ip.declareDimension(DIMENSION_LEFT, 50, 40, 0, green, scale , "PPM [PAGES/MINUTE]");
|
||||
ip.declareDimension(DIMENSION_RIGHT, 100, 20, 0, blue, scale, "MEMORY/MEGABYTE");
|
||||
ip.setColor(green);
|
||||
ip.chartDot(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, 5, null, 0);
|
||||
ip.chartLine(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, -130, 200);
|
||||
ip.setColor(blue);
|
||||
ip.chartDot(DIMENSION_BOTTOM, DIMENSION_RIGHT, -50, 300, 2, null, 0);
|
||||
ip.chartLine(DIMENSION_BOTTOM, DIMENSION_RIGHT, -80, 100, -50, 300);
|
||||
//ip.print(100, 100, 0, "TEXT", true);
|
||||
//ip.print(100, 100, 0, "1234", false);
|
||||
//ip.print(100, 100, 90, "TEXT", true);
|
||||
//ip.print(100, 100, 90, "1234", false);
|
||||
final File file = new File("/Users/admin/Desktop/testimage.png");
|
||||
try {
|
||||
final FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(RasterPlotter.exportImage(ip.getImage(), "png").getBytes());
|
||||
//ImageIO.write(ip.getImage(), "png", fos);
|
||||
fos.close();
|
||||
} catch (final IOException e) {}
|
||||
ConcurrentLog.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* ChartPlotter
|
||||
* Copyright 2005 by Michael Christen
|
||||
* First released 26.10.2005 at http://yacy.net
|
||||
*
|
||||
* This library 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 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program in the file lgpl21.txt
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package net.yacy.visualization;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.yacy.cora.util.ConcurrentLog;
|
||||
|
||||
|
||||
public class ChartPlotter extends RasterPlotter {
|
||||
|
||||
public static final int DIMENSION_RIGHT = 0;
|
||||
public static final int DIMENSION_TOP = 1;
|
||||
public static final int DIMENSION_LEFT = 2;
|
||||
public static final int DIMENSION_BOTTOM = 3;
|
||||
public static final int DIMENSION_ANOT0 = 4;
|
||||
public static final int DIMENSION_ANOT1 = 5;
|
||||
public static final int DIMENSION_ANOT2 = 6;
|
||||
public static final int DIMENSION_ANOT3 = 7;
|
||||
|
||||
private final int leftborder;
|
||||
private final int rightborder;
|
||||
private final int topborder;
|
||||
private final int bottomborder;
|
||||
private final int[] scales = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final int[] pixels = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final int[] offsets = new int[]{0,0,0,0,0,0,0,0};
|
||||
private final Long[] colnames = new Long[]{0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl,0xFFFFFFl};
|
||||
private final Long[] colscale = new Long[]{null,null,null,null,null,null,null,null};
|
||||
private final String[] tablenames = new String[]{"","","","","","","",""};
|
||||
|
||||
public ChartPlotter(final int width, final int height, final Long backgroundColor, final Long foregroundColor, final Long lightColor,
|
||||
final int leftborder, final int rightborder, final int topborder, final int bottomborder,
|
||||
final String name, final String subline) {
|
||||
super(width, height, RasterPlotter.DrawMode.MODE_REPLACE, backgroundColor);
|
||||
this.leftborder = leftborder;
|
||||
this.rightborder = rightborder;
|
||||
this.topborder = topborder;
|
||||
this.bottomborder = bottomborder;
|
||||
//this.name = name;
|
||||
//this.backgroundColor = backgroundColor;
|
||||
//this.foregroundColor = foregroundColor;
|
||||
if (name != null) {
|
||||
if (foregroundColor != null) this.setColor(foregroundColor);
|
||||
PrintTool.print(this, width / 2 - name.length() * 3, 6, 0, name, -1, 100);
|
||||
}
|
||||
if (subline != null) {
|
||||
if (lightColor != null) this.setColor(lightColor);
|
||||
PrintTool.print(this, width / 2 - subline.length() * 3, 14, 0, subline, -1, 100);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* assign a metric to a graph. The dimension can be left or right (the measure at the side-border of the graph)
|
||||
* @param dimensionType
|
||||
* @param scale is the measure (the number) to be printed on the border per pixelscale
|
||||
* @param pixelperscale is the number of pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
public void declareDimension(final int dimensionType, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
this.scales[dimensionType] = Math.max(1, scale);
|
||||
this.pixels[dimensionType] = pixelperscale;
|
||||
this.offsets[dimensionType] = offset;
|
||||
this.colnames[dimensionType] = colorNaming;
|
||||
this.colscale[dimensionType] = colorScale;
|
||||
this.tablenames[dimensionType] = name;
|
||||
if ((dimensionType == DIMENSION_LEFT) || (dimensionType == DIMENSION_RIGHT)) {
|
||||
drawVerticalScale((dimensionType == DIMENSION_LEFT), scale, pixelperscale, offset, colorNaming, colorScale, name);
|
||||
}
|
||||
if ((dimensionType == DIMENSION_TOP) || (dimensionType == DIMENSION_BOTTOM)) {
|
||||
drawHorizontalScale((dimensionType == DIMENSION_TOP), scale, pixelperscale, offset, colorNaming, colorScale, name);
|
||||
}
|
||||
}
|
||||
|
||||
public void chartDot(final int dimension_x, final int dimension_y, final float coord_x, final int coord_y, final int dotsize, final String anot, final int anotAngle) {
|
||||
final int x = (int) ((coord_x - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
assert this.scales[dimension_y] != 0;
|
||||
final int y = (coord_y - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
if (dotsize == 1) plot(this.leftborder + x, this.height - this.bottomborder - y, 100);
|
||||
else dot(this.leftborder + x, this.height - this.bottomborder - y, dotsize, true, 100);
|
||||
if (anot != null) PrintTool.print(this, this.leftborder + x + dotsize + 2 + ((anotAngle == 315) ? -9 : 0), this.height - this.bottomborder - y + ((anotAngle == 315) ? -3 : 0), anotAngle, anot, (anotAngle == 0) ? (anot.length() * 6 + x > this.width ? 1 : -1) : ((anotAngle == 315) ? 1 : 0), 100);
|
||||
}
|
||||
|
||||
public void chartLine(final int dimension_x, final int dimension_y, final float coord_x1, final int coord_y1, final float coord_x2, final int coord_y2) {
|
||||
final int x1 = (int) ((coord_x1 - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
final int y1 = (coord_y1 - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
final int x2 = (int) ((coord_x2 - this.offsets[dimension_x]) * this.pixels[dimension_x] / this.scales[dimension_x]);
|
||||
final int y2 = (coord_y2 - this.offsets[dimension_y]) * this.pixels[dimension_y] / this.scales[dimension_y];
|
||||
line(this.leftborder + x1, this.height - this.bottomborder - y1, this.leftborder + x2, this.height - this.bottomborder - y2, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw a horizontal scale border
|
||||
* @param top - if true, this the top-horizontal scale, otherwise it is at the bottom
|
||||
* @param scale is the measure (the number) to be printed on the vertical border per pixelscale
|
||||
* @param pixelperscale is the number of vertical pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
private void drawHorizontalScale(final boolean top, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
final int y = (top) ? this.topborder : this.height - this.bottomborder;
|
||||
int x = this.leftborder;
|
||||
int s = offset;
|
||||
while (x < this.width - this.rightborder) {
|
||||
if ((colorScale != null) && (x > this.leftborder) && (x < (this.width - this.rightborder))) {
|
||||
setColor(colorScale);
|
||||
line(x, this.topborder, x, this.height - this.bottomborder, 100);
|
||||
}
|
||||
setColor(colorNaming);
|
||||
line(x, y - 3, x, y + 3, 100);
|
||||
PrintTool.print(this, x, (top) ? y - 3 : y + 9, 0, Integer.toString(s), -1, 80);
|
||||
x += pixelperscale;
|
||||
s += scale;
|
||||
}
|
||||
setColor(colorNaming);
|
||||
PrintTool.print(this, this.width - this.rightborder, (top) ? y - 9 : y + 15, 0, name, 1, 80);
|
||||
line(this.leftborder - 4, y, this.width - this.rightborder + 4, y, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* draw the vertical scale of the graph
|
||||
* @param left if true this is the vertical bar on the left, otherwise it is the one on the right
|
||||
* @param scale is the measure (the number) to be printed on the vertical border per pixelscale
|
||||
* @param pixelperscale is the number of vertical pixel points per scale
|
||||
* @param offset is an offset on the 'scale' number
|
||||
* @param colorNaming the colour of the legend for the scale
|
||||
* @param colorScale the colour of the line drawing for the vertical scale
|
||||
* @param name printed on the vertical bar
|
||||
*/
|
||||
private void drawVerticalScale(final boolean left, final int scale, final int pixelperscale, final int offset, final Long colorNaming, final Long colorScale, final String name) {
|
||||
assert pixelperscale > 0;
|
||||
assert scale > 0;
|
||||
if (pixelperscale <= 0) return; // this would not meet the termination condition in the while loop
|
||||
final int x = (left) ? this.leftborder : this.width - this.rightborder;
|
||||
int y = this.height - this.bottomborder;
|
||||
int s = offset;
|
||||
String s1;
|
||||
int s1max = 0;
|
||||
while (y > this.topborder) {
|
||||
if ((colorScale != null) && (y > this.topborder) && (y < (this.height - this.bottomborder))) {
|
||||
setColor(colorScale);
|
||||
line(this.leftborder, y, this.width - this.rightborder, y, 100);
|
||||
}
|
||||
setColor(colorNaming);
|
||||
line(x - 3, y, x + 3, y, 100);
|
||||
s1 = (s >= 1000000 && s % 1000000 == 0) ? Integer.toString(s / 1000000) + "M" : (s >= 1000 && s % 1000 == 0) ? Integer.toString(s / 1000) + "K" : Integer.toString(s);
|
||||
if (s1.length() > s1max) s1max = s1.length();
|
||||
PrintTool.print(this, (left) ? this.leftborder - 4 : this.width - this.rightborder + 4, y, 0, s1, (left) ? 1 : -1, 80);
|
||||
y -= pixelperscale;
|
||||
s += scale;
|
||||
}
|
||||
setColor(colorNaming);
|
||||
PrintTool.print(this, (left) ? Math.max(6, x - s1max * 6 - 6) : x + s1max * 6 + 9, this.height - this.bottomborder, 90, name, -1, 80);
|
||||
line(x, this.topborder - 4, x, this.height - this.bottomborder + 4, 100);
|
||||
}
|
||||
|
||||
public static void main(final String[] args) {
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
final long bg = 0xFFFFFF;
|
||||
final long fg = 0x000000;
|
||||
final long scale = 0xCCCCCC;
|
||||
final long green = 0x008800;
|
||||
final long blue = 0x0000FF;
|
||||
final ChartPlotter ip = new ChartPlotter(660, 240, bg, fg, fg, 30, 30, 20, 20, "PEER PERFORMANCE GRAPH: PAGES/MINUTE and USED MEMORY", "");
|
||||
ip.declareDimension(DIMENSION_BOTTOM, 60, 60, -600, fg, scale, "TIME/SECONDS");
|
||||
//ip.declareDimension(DIMENSION_TOP, 10, 40, "000000", null, "count");
|
||||
ip.declareDimension(DIMENSION_LEFT, 50, 40, 0, green, scale , "PPM [PAGES/MINUTE]");
|
||||
ip.declareDimension(DIMENSION_RIGHT, 100, 20, 0, blue, scale, "MEMORY/MEGABYTE");
|
||||
ip.setColor(green);
|
||||
ip.chartDot(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, 5, null, 0);
|
||||
ip.chartLine(DIMENSION_BOTTOM, DIMENSION_LEFT, -160, 100, -130, 200);
|
||||
ip.setColor(blue);
|
||||
ip.chartDot(DIMENSION_BOTTOM, DIMENSION_RIGHT, -50, 300, 2, null, 0);
|
||||
ip.chartLine(DIMENSION_BOTTOM, DIMENSION_RIGHT, -80, 100, -50, 300);
|
||||
//ip.print(100, 100, 0, "TEXT", true);
|
||||
//ip.print(100, 100, 0, "1234", false);
|
||||
//ip.print(100, 100, 90, "TEXT", true);
|
||||
//ip.print(100, 100, 90, "1234", false);
|
||||
final File file = new File("/Users/admin/Desktop/testimage.png");
|
||||
try {
|
||||
final FileOutputStream fos = new FileOutputStream(file);
|
||||
fos.write(RasterPlotter.exportImage(ip.getImage(), "png").getBytes());
|
||||
//ImageIO.write(ip.getImage(), "png", fos);
|
||||
fos.close();
|
||||
} catch (final IOException e) {}
|
||||
ConcurrentLog.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
package net.yacy.utils.translation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import net.yacy.data.Translator;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TranslatorXliffTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
// asure data directory exists for temp test files
|
||||
File testDataDir = new File("test/DATA");
|
||||
if (!testDataDir.exists()) {
|
||||
testDataDir.mkdir();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of loadTranslationsListsFromXliff method, of class TranslatorXliff.
|
||||
* load all translation lists from default locales directory writes temp
|
||||
* test files to test/DATA and compares translation text
|
||||
*/
|
||||
@Test
|
||||
public void testLoadTranslationsListsFromXliff() throws IOException {
|
||||
List<String> lngFiles = Translator.langFiles(new File("locales"));
|
||||
for (String filename : lngFiles) {
|
||||
// load translation list
|
||||
System.out.println("Test translation file " + filename);
|
||||
Map<String, Map<String, String>> origTrans = Translator.loadTranslationsLists(new File("locales", filename));
|
||||
TranslatorXliff txlif = new TranslatorXliff();
|
||||
|
||||
// save as xliff file
|
||||
File xlftmp = new File("test/Data", filename + ".xlf");
|
||||
txlif.saveAsXliff(filename.substring(0, 2), xlftmp, origTrans);
|
||||
|
||||
// load created xliff file
|
||||
Map<String, Map<String, String>> xliffTrans = txlif.loadTranslationsListsFromXliff(xlftmp);
|
||||
|
||||
// compare content
|
||||
assertEquals(origTrans.size(), xliffTrans.size());
|
||||
for (String s : origTrans.keySet()) { // get translation filename
|
||||
assertTrue(xliffTrans.containsKey(s));
|
||||
|
||||
// compare translation list
|
||||
Map<String, String> origList = origTrans.get(s);
|
||||
Map<String, String> xliffList = xliffTrans.get(s);
|
||||
assertEquals(origList.size(), xliffList.size());
|
||||
for (String ss : origList.keySet()) {
|
||||
assertTrue("translation key", xliffList.containsKey(ss));
|
||||
String origVal = origList.get(ss);
|
||||
// it is possible that intentionally empty translation is given
|
||||
// in this case xliff target is missing (=null)
|
||||
if (origVal != null && !origVal.isEmpty()) {
|
||||
String xliffVal = xliffList.get(ss);
|
||||
if (!origVal.equals(xliffVal)) {
|
||||
assertEquals("translation value", origVal, xliffVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue