[FEATURE] Add stat packages

This commit is contained in:
Arnaud 2013-12-17 19:21:22 +01:00
parent 8799670f1d
commit 0cfaaf9bbc
43 changed files with 3989 additions and 0 deletions

View File

@ -0,0 +1,39 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat;
import javax.servlet.http.HttpServletRequest;
public interface LogCallback {
public void logHtmlCreate(String token, long date0, long date1, String encoded, HttpServletRequest request);
public void logHtmlLoadPage(HttpServletRequest request, long date0, String start, String end, String token,
String width, String height);
public void logHtmlLoadImage(HttpServletRequest request, long date0, String start, String end, String token,
String width, String height);
public void logImageGeneration(HttpServletRequest request, long date0, long date1, String type);
}

View File

@ -0,0 +1,66 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
public class StatSxServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String token = request.getParameter("t");
String start = request.getParameter("s");
String page = request.getParameter("p");
String image = request.getParameter("i");
String width = request.getParameter("w");
String height = request.getParameter("h");
if (page != null) {
Stats.getInstance().logHtmlLoadPage(request, System.currentTimeMillis(), start, page, token, width, height);
}
if (image != null) {
Stats.getInstance().logHtmlLoadImage(request, System.currentTimeMillis(), start, image, token, width,
height);
}
// System.err.println("get sx1 " + token + " start=" + start + " page=" + page + " image=" + image);
}
@Override
public void destroy() {
super.destroy();
Stats.getInstance().destroy();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
}
}

View File

@ -0,0 +1,312 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Locale;
import java.util.Random;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.servlet.http.HttpServletRequest;
import net.sourceforge.plantuml.pstat.event.StatEvent;
import net.sourceforge.plantuml.pstat.event.StatEventAdminStart;
import net.sourceforge.plantuml.pstat.event.StatEventAdminStop;
import net.sourceforge.plantuml.pstat.event.StatEventFileIterator;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
import net.sourceforge.plantuml.pstat.graph.Curve;
import net.sourceforge.plantuml.pstat.tick.GraphData;
import net.sourceforge.plantuml.pstat.tick.GraphDataLongTerm;
import net.sourceforge.plantuml.pstat.tick.TickDatabase;
public class Stats implements LogCallback {
public static final boolean USE_STATS = true;
static class Mem {
public Mem(StatEvent ev) {
totalMemory = (int) (ev.getTotalMemory() / 1024L / 1024L);
freeMemory = (int) (ev.getFreeMemory() / 1024L / 1024L);
activeCount = ev.getActiveCount();
time = ev.getStartServerTime();
}
final private long time;
final private int freeMemory;
final private int totalMemory;
final private int activeCount;
}
private final static Stats singleton = new Stats();
private final LinkedBlockingDeque<StatEvent> events = new LinkedBlockingDeque<StatEvent>();
private final LinkedBlockingDeque<Mem> memories = new LinkedBlockingDeque<Mem>();
private final TickDatabase tickDatabase = USE_STATS ? new TickDatabase() : null;
public GraphData getGraphData() {
return tickDatabase == null ? new GraphData() : tickDatabase.getGraphData();
}
public GraphDataLongTerm getGraphDataLongTerm() {
return tickDatabase == null ? new GraphDataLongTerm() : tickDatabase.getGraphDataLongTerm();
}
private static final Random rnd = new Random();
public String getNewToken(long now) {
final String t = Integer.toString((int) (now / 1000L), 36)
+ Long.toString(Math.abs(rnd.nextLong()), 36).substring(1);
return t;
}
public static File getSavedFile() {
return new File(getSavedFileName() + ".pat");
}
public static String getSavedFileName() {
final DateFormat df = new SimpleDateFormat("yyyy_MM", Locale.US);
return "pdata" + df.format(new Date());
}
public static String getPreviousFileName() {
final DateFormat df = new SimpleDateFormat("yyyy_MM", Locale.US);
final String cname = df.format(new Date());
int y = Integer.parseInt(cname.substring(0, 4));
int m = Integer.parseInt(cname.substring(5, 7));
m--;
if (m == 0) {
y--;
m = 12;
}
return "pdata" + String.format("%04d", y) + "_" + String.format("%02d", m);
}
private Stats() {
final Thread th = new Thread() {
public void run() {
fileAccess.lock();
try {
reload();
} catch (IOException e) {
e.printStackTrace();
} finally {
fileAccess.unlock();
}
}
};
addEvent(new StatEventAdminStart());
th.start();
}
private final Lock fileAccess = new ReentrantLock();
private void reload() throws IOException {
reload(getSavedFile());
final String cur = getSavedFileName();
for (char c = 'a'; c < 'z'; c++) {
reload(cur + c);
}
final String prev = getPreviousFileName();
reload(prev);
for (char c = 'a'; c < 'z'; c++) {
reload(prev + c);
}
reload("legacy2000");
}
private void reload(final String name) throws IOException {
File file = new File(name + ".pat");
if (file.exists() == false) {
file = new File(name + ".pat.gz");
}
if (file.exists() == false) {
file = new File(name + ".zip");
}
reload(file);
}
private void reload(final File file) throws IOException {
if (file.exists() == false) {
return;
}
StatEventFileIterator it = null;
try {
it = StatEventFileIterator.fromFile(file);
reload(it);
} finally {
if (it != null) {
it.close();
}
}
}
private void reload(StatEventFileIterator it) {
while (it.hasNext()) {
final StatEvent ev = it.next();
updateStats(ev);
Thread.yield();
}
}
public static Stats getInstance() {
return singleton;
}
private void addEvent(final StatEvent ev) {
updateStats(ev);
events.add(ev);
memories.add(new Mem(ev));
while (memories.size() > 100) {
final Iterator<Mem> it = memories.iterator();
it.next();
it.remove();
}
if (fileAccess.tryLock()) {
try {
saveEvents();
} catch (IOException e) {
e.printStackTrace();
} finally {
fileAccess.unlock();
}
}
}
public void destroy() {
System.err.println("CALLING DESTROY");
addEvent(new StatEventAdminStop());
if (fileAccess.tryLock()) {
try {
saveEvents();
} catch (IOException e) {
e.printStackTrace();
} finally {
fileAccess.unlock();
}
}
}
private void saveEvents() throws IOException {
final File saveFile = getSavedFile();
// final long startSave = System.currentTimeMillis();
DataOutputStream oos = null;
try {
oos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile, true), 1024 * 50));
for (Iterator<StatEvent> it = events.iterator(); it.hasNext();) {
final StatEvent event = it.next();
event.save(oos);
it.remove();
// nbSave++;
}
} finally {
if (oos != null) {
oos.close();
}
}
}
public void logHtmlCreate(String token, long date0, long date1, String encoded, HttpServletRequest request) {
final StatEvent event = new StatEventHtmlCreate(request, date0, date1, token, encoded);
addEvent(event);
}
public void logHtmlLoadPage(HttpServletRequest request, long date0, String start, String end, String token,
String width, String height) {
final long start_ = parseSecureLong(start);
final long end_ = parseSecureLong(end);
final int width_ = parseSecureInt(width);
final int height_ = parseSecureInt(height);
final StatEventHtmlLoadPage event = new StatEventHtmlLoadPage(request, date0, start_, end_, token, width_,
height_);
addEvent(event);
}
public void logHtmlLoadImage(HttpServletRequest request, long date0, String start, String end, String token,
String width, String height) {
final long start_ = parseSecureLong(start);
final long end_ = parseSecureLong(end);
final int width_ = parseSecureInt(width);
final int height_ = parseSecureInt(height);
final StatEventHtmlLoadImage event = new StatEventHtmlLoadImage(request, date0, start_, end_, token, width_,
height_);
addEvent(event);
}
public void logImageGeneration(HttpServletRequest request, long date0, long date1, String type) {
final StatEventImageGeneration event = new StatEventImageGeneration(request, date0, date1, type);
addEvent(event);
}
private int parseSecureInt(String s) {
if (s != null && s.matches("\\d+")) {
return Integer.parseInt(s);
}
return 0;
}
private long parseSecureLong(String s) {
if (s != null && s.matches("\\d+")) {
return Long.parseLong(s);
}
return 0;
}
private void updateStats(final StatEvent ev) {
if (USE_STATS) {
tickDatabase.updateStats(ev);
}
}
public Curve memories(double height, double singleBarWidth, int fontSize) {
final Curve result = new Curve(height, singleBarWidth, fontSize);
for (Mem mem : memories) {
result.addData(new Date(mem.time).toString(), mem.totalMemory, mem.freeMemory);
}
return result;
}
public Curve threads(double height, double singleBarWidth, int fontSize) {
final Curve result = new Curve(height, singleBarWidth, fontSize);
for (Mem mem : memories) {
result.addData(new Date(mem.time).toString(), mem.activeCount);
}
return result;
}
}

View File

@ -0,0 +1,50 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
public class WriterOutputStream extends OutputStream {
final Writer pw;
public WriterOutputStream(Writer pw) {
this.pw = pw;
}
@Override
public void write(int data) throws IOException {
pw.write(data);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
final String s = new String(b, off, len);
pw.write(s);
}
}

View File

@ -0,0 +1,318 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.maxmind.geoip.LookupService;
public abstract class StatEvent {
private final int byteHeader;
private final long serverTime;
private final Map<String, String> header = new HashMap<String, String>();
private final String ipClient;
private final int activeCount;
private final long freeMemory;
private final long totalMemory;
private static final UAParser uaParser = new UAParser();
private static final LookupService countryService = initCountryService();
private static LookupService initCountryService() {
try {
return new LookupService("GeoIP.dat", LookupService.GEOIP_MEMORY_CACHE);
} catch (FileNotFoundException e) {
System.err.println("path=" + new File("GeoIP.dat").getAbsolutePath() + " not found");
return null;
} catch (IOException e) {
System.err.println("path=" + new File("GeoIP.dat").getAbsolutePath());
e.printStackTrace();
return null;
}
}
synchronized public void save(DataOutputStream os) throws IOException {
os.write(0x43);
os.writeInt(activeCount);
os.writeLong(freeMemory);
os.writeLong(totalMemory);
os.write(byteHeader);
os.writeLong(serverTime);
writeStringSecure(os, ipClient);
for (Map.Entry<String, String> ent : header.entrySet()) {
writeStringSecure(os, ent.getKey());
writeStringSecure(os, ent.getValue());
}
writeStringSecure(os, "");
saveSuppData(os);
}
public static StatEvent read(DataInputStream is) throws IOException {
final int sign = is.read();
if (sign == -1) {
return null;
}
final int activeCount;
final long freeMemory;
final long totalMemory;
if (sign == 0x42) {
activeCount = 0;
freeMemory = 0;
totalMemory = 0;
} else if (sign == 0x43) {
activeCount = is.readInt();
freeMemory = is.readLong();
totalMemory = is.readLong();
} else {
throw new IOException("No 0x42 header found");
}
final int byteHeader = is.read();
final long serverTime = is.readLong();
final String ipClient = is.readUTF();
final Map<String, String> header = new HashMap<String, String>();
while (true) {
final String key = is.readUTF();
if (key.length() == 0) {
break;
}
final String value = is.readUTF();
header.put(key.toLowerCase(), value);
}
switch (byteHeader) {
case 0x51:
return new StatEventAdminStart(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x52:
return new StatEventAdminStop(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x53:
return new StatEventAdminSaveLog(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x43:
return new StatEventHtmlCreate(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x44:
return new StatEventHtmlLoadPage(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x45:
return new StatEventHtmlLoadImage(is, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
case 0x46:
case 0x47:
return new StatEventImageGeneration(byteHeader, is, serverTime, ipClient, header, activeCount, freeMemory,
totalMemory);
}
throw new IOException("Unknown header " + byteHeader);
}
protected abstract void saveSuppData(DataOutputStream os) throws IOException;
public StatEvent(int byteHeader, long serverTime, HttpServletRequest request) {
this.byteHeader = byteHeader;
this.serverTime = serverTime;
this.activeCount = Thread.activeCount();
this.freeMemory = Runtime.getRuntime().freeMemory();
this.totalMemory = Runtime.getRuntime().totalMemory();
if (request != null) {
for (Enumeration foo = request.getHeaderNames(); foo.hasMoreElements();) {
String h = foo.nextElement().toString().toLowerCase();
String v = request.getHeader(h);
header.put(h, v);
}
this.ipClient = request.getRemoteAddr();
} else {
this.ipClient = "";
}
}
public StatEvent(int byteHeader, long serverTime, String ipClient, Map<String, String> header, int activeCount,
long freeMemory, long totalMemory) {
this.byteHeader = byteHeader;
this.serverTime = serverTime;
this.ipClient = ipClient;
this.header.putAll(header);
this.activeCount = activeCount;
this.freeMemory = freeMemory;
this.totalMemory = totalMemory;
}
@Override
public String toString() {
// System.err.println(header.keySet());
// System.err.println(header);
final long f = freeMemory / 1024 / 1024;
final long t = totalMemory / 1024 / 1024;
return "{" + Integer.toHexString(byteHeader) + "} " + new Date(serverTime).toGMTString() + " " + f + "/" + t
+ " " + activeCount + " " + ipClient + " {" + getAcceptLanguage() + "} {" + getCountry() + "} ["
+ getRefererDetailed() + "] ";
}
public String getAcceptLanguage() {
final String lang = header.get("accept-language");
if (lang == null) {
return "??";
}
if (lang.length() < 2) {
return "??";
}
return lang.substring(0, 2);
}
public String getHost() {
final String host = header.get("host");
if (host == null) {
return "??";
}
return host;
}
public String getUserAgent() {
final String agent = header.get("user-agent");
if (agent == null) {
return "??";
}
return agent;
}
public String getReferer() {
String agent = header.get("referer");
if (agent == null) {
return "??";
}
final int x = agent.indexOf('/', 9);
if (x == -1) {
return "??";
}
agent = agent.substring(0, x);
if (agent.matches(".*\\.[a-z]{2,3}$")) {
return agent;
}
return "Other";
}
private String getRefererDetailed() {
String agent = header.get("referer");
if (agent == null) {
return "None";
}
final int x = agent.indexOf('/', 9);
if (x == -1) {
return "??";
}
agent = agent.substring(0, x);
if (agent.matches(".*\\.[a-z]{2,3}$")) {
return agent;
}
// return "Other";
return agent;
}
public String getOperatingSystem() {
final String user = getUserAgent();
if ("??".equals(user)) {
return "??";
}
final String result = uaParser.getOperatingSystem(user);
if (result.startsWith("OS X")) {
return "OS X";
}
if (result.startsWith("Android")) {
return "Android";
}
if (result.startsWith("iOS")) {
return "iOS";
}
return result;
}
public String getBrowser() {
final String user = getUserAgent();
if ("??".equals(user)) {
return "??";
}
final String result = uaParser.getBrowser(user);
return result;
}
public long getStartServerTime() {
return serverTime;
}
protected Map<String, String> getHeader() {
return Collections.unmodifiableMap(header);
}
public String getIpClient() {
return ipClient;
}
public String getCountry() {
if (countryService == null) {
return "Not loaded";
}
if (ipClient == null) {
return "??";
}
final String country = countryService.getCountry(ipClient).getName();
if ("N/A".equals(country)) {
return "??";
}
return country;
}
final protected void writeStringSecure(DataOutputStream oos, String s) throws IOException {
if (s == null) {
s = "";
}
oos.writeUTF(s);
}
final protected String shorten(String s) {
if (s.length() > 20) {
return s.substring(0, 20) + "...";
}
return s;
}
public final int getActiveCount() {
return activeCount;
}
public final long getFreeMemory() {
return freeMemory;
}
public final long getTotalMemory() {
return totalMemory;
}
}

View File

@ -0,0 +1,64 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
public class StatEventAdminSaveLog extends StatEvent {
private final int saveDuration;
private final int nbSaved;
private final int nbRemainingAfterSave;
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
os.writeInt(saveDuration);
os.writeInt(nbSaved);
os.writeInt(nbRemainingAfterSave);
}
public StatEventAdminSaveLog(int saveDuration, int nbSaved, int nbRemainingAfterSave) {
super(0x53, System.currentTimeMillis(), null);
this.saveDuration = saveDuration;
this.nbSaved = nbSaved;
this.nbRemainingAfterSave = nbRemainingAfterSave;
}
public StatEventAdminSaveLog(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
int activeCount, long freeMemory, long totalMemory) throws IOException {
super(0x53, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
this.saveDuration = is.readInt();
this.nbSaved = is.readInt();
this.nbRemainingAfterSave = is.readInt();
}
@Override
public String toString() {
return super.toString() + " SAVELOG " + saveDuration + " ms, nb=" + nbSaved + " remain=" + nbRemainingAfterSave;
}
}

View File

@ -0,0 +1,51 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
public class StatEventAdminStart extends StatEvent {
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
}
public StatEventAdminStart() {
super(0x51, System.currentTimeMillis(), null);
}
public StatEventAdminStart(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
int activeCount, long freeMemory, long totalMemory) {
super(0x51, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
}
@Override
public String toString() {
return super.toString() + " START";
}
}

View File

@ -0,0 +1,51 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
public class StatEventAdminStop extends StatEvent {
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
}
public StatEventAdminStop() {
super(0x52, System.currentTimeMillis(), null);
}
public StatEventAdminStop(DataInputStream is, long serverTime, String ipClient, Map<String, String> header, int activeCount,
long freeMemory, long totalMemory) {
super(0x52, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
}
@Override
public String toString() {
return super.toString() + " STOP";
}
}

View File

@ -0,0 +1,44 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
public abstract class StatEventFileIterator implements Closeable, Iterator<StatEvent> {
final public void remove() {
throw new UnsupportedOperationException();
}
public static StatEventFileIterator fromFile(File f) throws IOException {
if (f.getName().endsWith(".zip")) {
return new StatEventFileIteratorZip(f);
}
return new StatEventFileIteratorSimple(f);
}
}

View File

@ -0,0 +1,78 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
class StatEventFileIteratorSimple extends StatEventFileIterator {
private DataInputStream is;
private StatEvent potentialNext;
public StatEventFileIteratorSimple(File f) throws IOException {
if (f.getName().endsWith(".gz")) {
this.is = new DataInputStream(new GZIPInputStream(new BufferedInputStream(new FileInputStream(f))));
} else {
this.is = new DataInputStream(new BufferedInputStream(new FileInputStream(f)));
}
this.potentialNext = StatEvent.read(is);
}
public void close() throws IOException {
is.close();
is = null;
}
public boolean hasNext() {
return potentialNext != null;
}
public StatEvent next() {
final StatEvent result = potentialNext;
try {
potentialNext = StatEvent.read(is);
} catch (IOException e) {
e.printStackTrace();
throw new UnsupportedOperationException();
}
return result;
}
public static void main(String[] args) throws IOException {
final File f = new File("C:/eclipse/eclipse/pdata2013_11.pat");
final StatEventFileIteratorSimple it = new StatEventFileIteratorSimple(f);
while (it.hasNext()) {
final StatEvent ev = it.next();
System.out.println(ev);
}
it.close();
}
}

View File

@ -0,0 +1,89 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
class StatEventFileIteratorZip extends StatEventFileIterator {
private StatEvent potentialNext;
private ZipInputStream zip;
private ZipEntry current;
private DataInputStream is;
public StatEventFileIteratorZip(File f) throws IOException {
this.zip = new ZipInputStream(new BufferedInputStream(new FileInputStream(f)));
current = zip.getNextEntry();
is = new DataInputStream(zip);
this.potentialNext = StatEvent.read(is);
}
public void close() throws IOException {
is.close();
is = null;
}
public boolean hasNext() {
return potentialNext != null;
}
public StatEvent next() {
final StatEvent result = potentialNext;
try {
potentialNext = StatEvent.read(is);
if (potentialNext == null) {
current = zip.getNextEntry();
if (current != null) {
// is = new DataInputStream(zip);
this.potentialNext = StatEvent.read(is);
}
}
} catch (IOException e) {
e.printStackTrace();
throw new UnsupportedOperationException();
}
return result;
}
public static void main(String[] args) throws IOException {
final File f = new File("G:/log2/pdata2013_11.zip");
final StatEventFileIteratorZip it = new StatEventFileIteratorZip(f);
int nb = 0;
while (it.hasNext()) {
final StatEvent ev = it.next();
nb++;
// System.out.println(ev);
}
System.err.println("nb=" + nb);
it.close();
}
}

View File

@ -0,0 +1,71 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public class StatEventHtmlCreate extends StatEvent {
private final long date1;
private final String token;
private final String encoded;
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
os.writeLong(date1);
writeStringSecure(os, token);
writeStringSecure(os, encoded);
}
public StatEventHtmlCreate(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
int activeCount, long freeMemory, long totalMemory) throws IOException {
super(0x43, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
this.date1 = is.readLong();
this.token = is.readUTF();
this.encoded = is.readUTF();
}
public StatEventHtmlCreate(HttpServletRequest request, long date0, long date1, String token, String encoded) {
super(0x43, date0, request);
this.date1 = date1;
this.token = token;
this.encoded = encoded;
}
@Override
public String toString() {
final long duration = date1 - getStartServerTime();
return super.toString() + " " + token + " (ht=" + duration + "ms) " + shorten(encoded);
}
public String getToken() {
return token;
}
}

View File

@ -0,0 +1,85 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public class StatEventHtmlLoadImage extends StatEvent {
private final long start;
private final long end;
private final int width;
private final int height;
private final String token;
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
os.writeLong(start);
os.writeLong(end);
os.writeInt(width);
os.writeInt(height);
writeStringSecure(os, token);
}
public StatEventHtmlLoadImage(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
int activeCount, long freeMemory, long totalMemory) throws IOException {
super(0x45, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
this.start = is.readLong();
this.end = is.readLong();
this.width = is.readInt();
this.height = is.readInt();
this.token = is.readUTF();
}
public StatEventHtmlLoadImage(HttpServletRequest request, long date0, long start, long end, String token,
int width, int height) {
super(0x45, date0, request);
this.start = start;
this.end = end;
this.width = width;
this.height = height;
this.token = token;
}
@Override
public String toString() {
final long duration = end - start;
return super.toString() + " " + token + " (im=" + duration + "ms) " + width + "x" + height;
}
public int getImageLoad() {
final long duration = end - start;
return (int) duration;
}
public String getToken() {
return token;
}
}

View File

@ -0,0 +1,86 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public class StatEventHtmlLoadPage extends StatEvent {
private final long start;
private final long end;
private final int width;
private final int height;
private final String token;
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
os.writeLong(start);
os.writeLong(end);
os.writeInt(width);
os.writeInt(height);
writeStringSecure(os, token);
}
public StatEventHtmlLoadPage(DataInputStream is, long serverTime, String ipClient, Map<String, String> header,
int activeCount, long freeMemory, long totalMemory) throws IOException {
super(0x44, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
this.start = is.readLong();
this.end = is.readLong();
this.width = is.readInt();
this.height = is.readInt();
this.token = is.readUTF();
}
public StatEventHtmlLoadPage(HttpServletRequest request, long date0, long start, long end, String token, int width,
int height) {
super(0x44, date0, request);
this.start = start;
this.end = end;
this.width = width;
this.height = height;
this.token = token;
}
@Override
public String toString() {
final long duration = end - start;
return super.toString() + " " + token + " (pa=" + duration + "ms) " + width + "x" + height;
}
public int getPageLoad() {
final long duration = end - start;
return (int) duration;
}
public String getToken() {
return token;
}
}

View File

@ -0,0 +1,100 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
public class StatEventImageGeneration extends StatEvent {
private final long date1;
private final String uri;
private String type = "??";
@Override
protected void saveSuppData(DataOutputStream os) throws IOException {
os.writeLong(date1);
writeStringSecure(os, uri);
writeStringSecure(os, type);
}
public StatEventImageGeneration(int byteHeader, DataInputStream is, long serverTime, String ipClient,
Map<String, String> header, int activeCount, long freeMemory, long totalMemory) throws IOException {
super(byteHeader, serverTime, ipClient, header, activeCount, freeMemory, totalMemory);
this.date1 = is.readLong();
this.uri = is.readUTF();
if (byteHeader == 0x47) {
this.type = is.readUTF();
}
}
public StatEventImageGeneration(HttpServletRequest request, long date0, long date1, String type) {
super(0x47, date0, request);
this.date1 = date1;
this.uri = request.getRequestURI();
this.type = type;
}
public StatEventImageGeneration(long date0, String uri, String type) {
super(0x47, date0, null);
this.date1 = 0;
this.uri = uri;
this.type = type;
}
@Override
public String toString() {
// final long duration = date1 == 0 ? -1 : date1 - getStartServerTime();
return super.toString() + "(" + type + ") [" + getDuration() + "ms] " + shorten(uri);
}
public int getDuration() {
final long duration = date1 == 0 ? -1 : date1 - getStartServerTime();
return (int) duration;
}
public String getUri() {
return uri;
}
public String getType() {
return type;
}
public String getIncomming() {
final String refererer = getReferer();
if (refererer.startsWith("http://www.plantuml.com")) {
return "www.plantuml.com";
}
if (refererer.startsWith("http://plantuml.com")) {
return "plantuml.com";
}
return "Other website";
}
}

View File

@ -0,0 +1,65 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.event;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.sf.uadetector.OperatingSystem;
import net.sf.uadetector.ReadableUserAgent;
import net.sf.uadetector.UserAgentFamily;
import net.sf.uadetector.UserAgentStringParser;
import net.sf.uadetector.service.UADetectorServiceFactory;
public class UAParser {
private static final UserAgentStringParser parser = UADetectorServiceFactory.getResourceModuleParser();
private static final Map<String, String> osMap = new ConcurrentHashMap<String, String>();
private static final Map<String, String> browserMap = new ConcurrentHashMap<String, String>();
public String getOperatingSystem(String userAgent) {
String result = osMap.get(userAgent);
if (result == null) {
final ReadableUserAgent agent = parser.parse(userAgent);
final OperatingSystem os = agent.getOperatingSystem();
result = os.getName();
osMap.put(userAgent, result);
// System.err.println("os=" + osMap.size());
}
return result;
}
public String getBrowser(String userAgent) {
String result = browserMap.get(userAgent);
if (result == null) {
final ReadableUserAgent agent = parser.parse(userAgent);
final UserAgentFamily family = agent.getFamily();
result = family.getName();
browserMap.put(userAgent, result);
// System.err.println("browser=" + browserMap.size());
}
return result;
}
}

View File

@ -0,0 +1,285 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.awt.Font;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.graphic.StringBounder;
import net.sourceforge.plantuml.pstat.WriterOutputStream;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UEllipse;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.UPolygon;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UText;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
public class Chart {
class Data {
final private String label;
final private int value;
Data(String label, int value) {
this.label = label;
this.value = value;
}
private double getAngle() {
return 360.0 * value / sum;
}
private String getFullLabel() {
final long pour = 100L * value / sum;
return label + " [" + pour + "%] [" + value + "/" + sum + "]";
}
public String getLabelShort() {
if (label.length() > 40) {
return "...";
}
return label;
}
}
private final List<Data> datas = new ArrayList<Data>();
private long sum;
private final UFont fontComment = new UFont("", Font.BOLD, 12);
public void compact() {
final List<Data> newList = new ArrayList<Data>();
final StringBuilder relicat = new StringBuilder();
int relicatValue = 0;
final int limit = (int) (sum / 100);
for (Data d : datas) {
if (d.value > limit) {
newList.add(d);
} else {
if (relicat.length() > 0) {
relicat.append(" - ");
}
relicat.append(d.label);
relicatValue += d.value;
}
}
if (relicatValue > 0) {
newList.add(new Data(relicat.toString(), relicatValue));
}
datas.clear();
datas.addAll(newList);
}
public void removeBig(double pour) {
final List<Data> newList = new ArrayList<Data>();
final int limit = (int) (sum * pour);
for (Data d : datas) {
if (d.value <= limit) {
newList.add(d);
} else {
sum -= d.value;
}
}
datas.clear();
datas.addAll(newList);
}
private final double heightGraph;
private final List<HtmlColor> colors = Arrays.asList(HtmlColorUtils.getColorIfValid("CadetBlue"),
HtmlColorUtils.getColorIfValid("Sienna"), HtmlColorUtils.getColorIfValid("Khaki"),
HtmlColorUtils.getColorIfValid("GreenYellow"), HtmlColorUtils.getColorIfValid("Olive"),
HtmlColorUtils.GRAY, HtmlColorUtils.getColorIfValid("HotPink"),
HtmlColorUtils.getColorIfValid("LightBlue"), HtmlColorUtils.getColorIfValid("Orange"),
HtmlColorUtils.getColorIfValid("OrangeRed"), HtmlColorUtils.getColorIfValid("Chocolate"),
HtmlColorUtils.getColorIfValid("Coral"));
public Chart(double height) {
this.heightGraph = height;
}
public void addData(String label, int value) {
datas.add(new Data(label, value));
this.sum += value;
}
private void drawPart(UGraphic ug, double v1, double v2, HtmlColor color, String title) {
if (v2 < 180) {
drawPartInternal(ug, v1, v2, color, title);
} else {
drawPartInternal(ug, v1, v2 / 2, color, title);
drawPartInternal(ug, v1 + v2 / 2, v2 / 2, color, title);
}
}
private void drawPartInternal(UGraphic ug, double v1, double v2, HtmlColor color, String title) {
// System.err.println("v1=" + v1 + " v2=" + v2 + " v1+v2=" + (v1 + v2));
ug = ug.apply(new UStroke(0));
ug = ug.apply(new UChangeBackColor(color)).apply(new UChangeColor(color));
ug.startUrl(new Url("", title));
ug.apply(new UStroke(2)).draw(new UEllipse(heightGraph, heightGraph, v1, v2));
final double cx = heightGraph / 2;
final double cy = heightGraph / 2;
final double start = v1 + 90;
final double extend = v2;
final double x1 = cx + Math.sin(start * Math.PI / 180.) * heightGraph / 2;
final double y1 = cy + Math.cos(start * Math.PI / 180.) * heightGraph / 2;
final double x2 = cx + Math.sin((start + extend) * Math.PI / 180.) * heightGraph / 2;
final double y2 = cy + Math.cos((start + extend) * Math.PI / 180.) * heightGraph / 2;
final UPolygon poly = new UPolygon();
poly.addPoint(heightGraph / 2, heightGraph / 2);
poly.addPoint(x1, y1);
poly.addPoint(x2, y2);
ug.apply(new UStroke(1.5)).draw(poly);
ug.closeAction();
}
private void drawPartComment(UGraphic ug, double v1, double v2, String title) {
final double cx = heightGraph / 2;
final double cy = heightGraph / 2;
final double start = v1 + 90;
final double extend = v2;
final double middle = (start + extend / 2) * Math.PI / 180.;
final double x3 = cx + Math.sin(middle) * (heightGraph / 2 * 4 / 5);
final double y3 = cy + Math.cos(middle) * (heightGraph / 2 * 4 / 5);
final double x4 = cx + Math.sin(middle) * (heightGraph / 2 + 20);
final double y4 = cy + Math.cos(middle) * (heightGraph / 2 + 20);
ug = ug.apply(new UStroke(2));
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
drawLine(ug, x3, y3, x4, y4);
final UText text = new UText(title, new FontConfiguration(fontComment, HtmlColorUtils.BLACK));
final double textWidth = ug.getStringBounder().calculateDimension(fontComment, title).getWidth();
final double xText;
if (x4 < cx) {
xText = x4 - textWidth - 3;
} else {
xText = x4 + 3;
}
ug.apply(new UTranslate(xText, y4)).draw(text);
}
private void drawPartLimit(UGraphic ug, double v1, double v2) {
ug = ug.apply(new UStroke(1.5));
final double cx = heightGraph / 2;
final double cy = heightGraph / 2;
final double start = v1 + 90;
final double extend = v2;
final double x1 = cx + Math.sin(start * Math.PI / 180.) * heightGraph / 2;
final double y1 = cy + Math.cos(start * Math.PI / 180.) * heightGraph / 2;
drawLine(ug, cx, cy, x1, y1);
}
private void drawLine(UGraphic ug, double x1, double y1, double x2, double y2) {
ug = ug.apply(new UTranslate(x1, y1));
ug.draw(new ULine(x2 - x1, y2 - y1));
}
private double getMaxTitleWidth(StringBounder stringBounder) {
double result = 0;
for (Data data : datas) {
if (data.value == 0) {
continue;
}
final double textWidth = stringBounder.calculateDimension(fontComment, data.getLabelShort()).getWidth();
result = Math.max(result, textWidth);
}
return result * 1.1 + 20;
}
public void printSvg(Writer writer) throws IOException {
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
double wmargin = getMaxTitleWidth(ug.getStringBounder());
ug = ug.apply(new UTranslate(wmargin, 40));
ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE));
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.WHITE));
ug.apply(new UTranslate(heightGraph + wmargin, 0)).draw(new URectangle(1, 1));
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.BLUE));
double s = 0;
ug = ug.apply(new UChangeBackColor(HtmlColorUtils.GREEN));
Iterator<HtmlColor> cols = colors.iterator();
for (Data data : datas) {
if (data.value == 0) {
continue;
}
if (cols.hasNext() == false) {
cols = colors.iterator();
}
drawPart(ug, s, data.getAngle(), cols.next(), data.getFullLabel());
s += data.getAngle();
}
s = 0;
for (Data data : datas) {
if (data.value == 0) {
continue;
}
drawPartLimit(ug, s, data.getAngle());
drawPartComment(ug, s, data.getAngle(), data.getLabelShort());
s += data.getAngle();
}
ug = ug.apply(new UStroke(2));
ug = ug.apply(new UChangeColor(HtmlColorUtils.BLACK));
ug = ug.apply(new UChangeBackColor(null));
ug.draw(new UEllipse(heightGraph, heightGraph));
OutputStream os = new WriterOutputStream(writer);
ug.writeImage(os, null, 96);
os.flush();
}
}

View File

@ -0,0 +1,135 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class ChartProducer {
private final Collection<Integer> datas;
public ChartProducer(Collection<Integer> all) {
datas = all;
}
public Chart getChart(double height) {
final Chart chart = new Chart(height);
final int nb = datas.size();
if (nb == 0) {
return chart;
}
long sum = 0;
int max = 0;
for (int v : datas) {
sum += v;
max = Math.max(max, v);
}
final int mean = NiceNumber.getNicer((int) (sum / nb));
final List<Step> steps = new ArrayList<Step>();
steps.add(new Step(0, NiceNumber.getNicer(mean / 3)));
steps.add(new Step(NiceNumber.getNicer(mean / 3), NiceNumber.getNicer(2 * mean / 3)));
steps.add(new Step(NiceNumber.getNicer(2 * mean / 3), mean));
final int delta = (max - mean) / 3;
steps.add(new Step(mean, NiceNumber.getNicer(mean + delta)));
steps.add(new Step(NiceNumber.getNicer(mean + delta), NiceNumber.getNicer(mean + 2 * delta)));
steps.add(new Step(NiceNumber.getNicer(mean + 2 * delta), max + 1));
for (int v : datas) {
count(steps, v);
}
final int lim = datas.size() / 50;
while (eventuallyMerge(steps, lim)) {
}
for (Step s : steps) {
chart.addData(s.getTitle(), s.count);
}
return chart;
}
static class Step {
final private int from;
final private int to;
private int count;
Step(int from, int to) {
this.from = from;
this.to = to;
}
Step mergeWith(Step other) {
if (this.to != other.from) {
throw new IllegalArgumentException();
}
final Step result = new Step(this.from, other.to);
result.count = this.count + other.count;
return result;
}
@Override
public String toString() {
return "" + from + "->" + to + " (" + count + ")";
}
boolean count(int v) {
if (v >= from && v < to) {
count++;
return true;
}
return false;
}
String getTitle() {
return "" + from + " ms to " + to + " ms";
}
}
private void count(final List<Step> steps, int v) {
for (Step s : steps) {
if (s.count(v)) {
return;
}
}
}
private boolean eventuallyMerge(final List<Step> steps, final int lim) {
for (int i = 0; i < steps.size() - 1; i++) {
final Step s1 = steps.get(i);
final Step s2 = steps.get(i + 1);
if (s1.count < lim && s2.count < lim) {
steps.set(i, s1.mergeWith(s2));
steps.remove(i + 1);
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,156 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.awt.Font;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.pstat.WriterOutputStream;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UEllipse;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UText;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
public class Curve {
static class Data {
final String label;
final int[] value;
Data(String label, int[] value) {
this.label = label;
this.value = value;
}
}
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
// private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
private final UFont fontLegend;
private final List<Data> datas = new ArrayList<Data>();
private int max;
private final double heightGraph;
private final double singleBarWidth;
public Curve(double height, double singleBarWidth, int fontSize) {
this.heightGraph = height;
this.singleBarWidth = singleBarWidth;
this.fontLegend = new UFont("", Font.BOLD, fontSize);
}
public void addData(String label, int... value) {
datas.add(new Data(label, value));
for (Data data : datas) {
for (int v : data.value) {
max = Math.max(max, v);
}
}
}
public void printSvg(Writer writer) throws IOException {
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
ug = ug.apply(new UChangeColor(backColor));
ug = ug.apply(new UChangeBackColor(backColor));
final double coef = heightGraph / max;
int step = getRound(max / 10.0);
if (step == 0) {
step = 1;
}
final double margeY1 = 10;
traceInfo(ug, coef, margeY1);
printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth + 30);
for (int i = 0; i < datas.get(0).value.length; i++) {
traceCurve(ug, coef, margeY1, i);
}
OutputStream os = new WriterOutputStream(writer);
ug.writeImage(os, null, 96);
os.flush();
}
private void traceInfo(UGraphic ug, final double coef, final double margeY1) {
ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE));
for (Data data : datas) {
ug.startUrl(new Url("", data.label));
ug.apply(new UTranslate(-3, -heightGraph - margeY1)).draw(
new URectangle(singleBarWidth, heightGraph + margeY1));
ug.closeAction();
ug = ug.apply(new UTranslate(singleBarWidth, 0));
}
}
private void traceCurve(UGraphic ug, final double coef, final double margeY1, int i) {
ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
Data lastData = null;
for (Data data : datas) {
ug.apply(new UTranslate(-3, -(data.value[i] * coef) - 3)).draw(new UEllipse(5, 5));
if (lastData != null) {
final ULine line = new ULine(-singleBarWidth, (data.value[i] - lastData.value[i]) * coef);
ug.apply(new UTranslate(0, -(data.value[i] * coef))).apply(new UStroke(2)).draw(line);
}
ug = ug.apply(new UTranslate(singleBarWidth, 0));
lastData = data;
}
}
private int getRound(double value) {
final int step = (int) Math.ceil(value / 5.0);
return step * 5;
}
private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
final ULine hline = new ULine(totalWidth, 0);
ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
for (int i = 0; i <= max; i += step) {
final double v = i * coef;
String label = "" + i;
final UText text = new UText(label, fontConfiguration);
ug.apply(new UTranslate(0, -v)).draw(text);
ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
}
}
}

View File

@ -0,0 +1,174 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.awt.Font;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.pstat.WriterOutputStream;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UText;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
public class HistoList {
static class Data implements Comparable<Data> {
final String label;
final int value;
Data(String label, int value) {
this.label = label;
this.value = value;
}
public int compareTo(Data other) {
return other.value - this.value;
}
}
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
// private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
private final UFont fontLegend;
private final List<Data> datas = new ArrayList<Data>();
private final double graphWidth;
private int max = 1;
private long sum;
private final double singleBarHeight;
public HistoList(double graphWidth, double singleBarHeight, int fontSize) {
this.graphWidth = graphWidth;
this.singleBarHeight = singleBarHeight;
this.fontLegend = new UFont("", Font.BOLD, fontSize);
}
public void addData(String label, int value) {
datas.add(new Data(label, value));
max = Math.max(max, value);
sum += value;
}
public void printSvg(Writer writer) throws IOException {
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
// ug = ug.apply(new UTranslate(0, 20));
ug = ug.apply(new UChangeColor(backColor));
ug = ug.apply(new UChangeBackColor(backColor));
Collections.sort(datas);
final double coef = graphWidth / max;
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
for (Data data : datas) {
final long pour = data.value * 100L / sum;
final String title = "[" + pour + "%] [" + data.value + "/" + sum + "]";
ug.startUrl(new Url("", title));
ug.draw(new URectangle(data.value * coef, singleBarHeight - 4));
ug.closeAction();
ug.apply(new UTranslate(0, fontLegend.getSize())).draw(new UText(data.label, fontConfiguration));
ug = ug.apply(new UTranslate(0, singleBarHeight));
}
// final double coef = heightGraph / maxValue();
// int step = getRound(maxValue() / 10.0);
// if (step == 0) {
// step = 1;
// }
// final double margeY1 = 10;
//
// traceInfo(ug, coef, margeY1);
// printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth +
// 30);
//
// for (int i = 0; i < datas.get(0).value.length; i++) {
// traceCurve(ug, coef, margeY1, i);
// }
OutputStream os = new WriterOutputStream(writer);
ug.writeImage(os, null, 96);
os.flush();
}
// private void traceInfo(UGraphic ug, final double coef, final double margeY1) {
// ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
// ug = ug.apply(new UChangeColor(HtmlColorUtils.WHITE)).apply(new UChangeBackColor(HtmlColorUtils.WHITE));
// for (Data data : datas) {
// ug.startUrl(new Url("", data.label));
// ug.apply(new UTranslate(-3, -heightGraph - margeY1)).draw(
// new URectangle(singleBarWidth, heightGraph + margeY1));
// ug.closeAction();
// ug = ug.apply(new UTranslate(singleBarWidth, 0));
// }
// }
// private void traceCurve(UGraphic ug, final double coef, final double margeY1, int i) {
// ug = ug.apply(new UTranslate(20, heightGraph + margeY1));
// Data lastData = null;
// for (Data data : datas) {
// ug.apply(new UTranslate(-3, -(data.value[i] * coef) - 3)).draw(new UEllipse(5, 5));
// if (lastData != null) {
// final ULine line = new ULine(-singleBarWidth, (data.value[i] - lastData.value[i]) * coef);
// ug.apply(new UTranslate(0, -(data.value[i] * coef))).apply(new UStroke(2)).draw(line);
// }
// ug = ug.apply(new UTranslate(singleBarWidth, 0));
// lastData = data;
// }
// }
//
// private int getRound(double value) {
// final int step = (int) Math.ceil(value / 5.0);
// return step * 5;
// }
// private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
// final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
// final ULine hline = new ULine(totalWidth, 0);
// ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
// for (int i = 0; i <= maxValue(); i += step) {
// final double v = i * coef;
// String label = "" + i;
// final UText text = new UText(label, fontConfiguration);
// ug.apply(new UTranslate(0, -v)).draw(text);
// ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
// }
//
// }
}

View File

@ -0,0 +1,153 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.awt.Font;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.Url;
import net.sourceforge.plantuml.graphic.FontConfiguration;
import net.sourceforge.plantuml.graphic.HtmlColor;
import net.sourceforge.plantuml.graphic.HtmlColorUtils;
import net.sourceforge.plantuml.pstat.WriterOutputStream;
import net.sourceforge.plantuml.ugraphic.ColorMapperIdentity;
import net.sourceforge.plantuml.ugraphic.UChangeBackColor;
import net.sourceforge.plantuml.ugraphic.UChangeColor;
import net.sourceforge.plantuml.ugraphic.UFont;
import net.sourceforge.plantuml.ugraphic.UGraphic;
import net.sourceforge.plantuml.ugraphic.ULine;
import net.sourceforge.plantuml.ugraphic.URectangle;
import net.sourceforge.plantuml.ugraphic.UStroke;
import net.sourceforge.plantuml.ugraphic.UText;
import net.sourceforge.plantuml.ugraphic.UTranslate;
import net.sourceforge.plantuml.ugraphic.svg.UGraphicSvg;
public class Histogram {
static class Data {
final String label;
final String title;
final int value;
Data(String label, String title, int value) {
this.label = label;
this.title = title;
this.value = value;
}
}
private final HtmlColor backColor = HtmlColorUtils.getColorIfValid("#AFE0D0");
private final HtmlColor lineColor = HtmlColorUtils.getColorIfValid("DimGray");
private final UFont fontLegend;
private final List<Data> datas = new ArrayList<Data>();
private int max = 1;
private final double heightGraph;
private final double singleBarWidth;
public Histogram(double height, double singleBarWidth, int fontSize) {
this.heightGraph = height;
this.singleBarWidth = singleBarWidth;
this.fontLegend = new UFont("", Font.BOLD, fontSize);
}
public void addData(String label, int value, String title) {
datas.add(new Data(label, title, value));
max = Math.max(max, value);
}
public void printSvg(Writer writer) throws IOException {
UGraphic ug = new UGraphicSvg(new ColorMapperIdentity(), false, 1.0);
ug = ug.apply(new UChangeColor(null));
ug = ug.apply(new UChangeBackColor(backColor));
final double coef = heightGraph / max;
int step = getRound(max / 10.0);
if (step == 0) {
step = 1;
}
final double margeY1 = 10;
printScale(ug.apply(new UTranslate(0, heightGraph + margeY1)), step, coef, datas.size() * singleBarWidth + 30);
final int marginX = 8 + ("" + max).length() * 8;
UGraphic ug2 = ug.apply(new UTranslate(marginX, heightGraph + margeY1));
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
for (Data data : datas) {
final double v = data.value * coef;
ug2.startUrl(new Url("", data.title));
ug2.apply(new UTranslate(0, -v)).draw(new URectangle(singleBarWidth, v));
ug2.closeAction();
final double textHeight = ug.getStringBounder().calculateDimension(fontLegend, data.label).getHeight();
final double textWidth = ug.getStringBounder().calculateDimension(fontLegend, data.label).getWidth();
final double xtext = (singleBarWidth - textWidth) / 2;
ug2.apply(new UTranslate(xtext, textHeight - 2)).draw(new UText(data.label, fontConfiguration));
ug2 = ug2.apply(new UTranslate(singleBarWidth, 0));
}
ug = ug.apply(new UChangeColor(lineColor)).apply(new UStroke(2)).apply(new UChangeBackColor(null));
ug2 = ug.apply(new UTranslate(marginX, heightGraph + margeY1));
double lastV = 0;
for (Data data : datas) {
final double v = data.value * coef;
drawLine(ug2, 0, -lastV, 0, -v);
drawLine(ug2, 0, -v, singleBarWidth, -v);
lastV = v;
ug2 = ug2.apply(new UTranslate(singleBarWidth, 0));
}
drawLine(ug2, 0, -lastV, 0, 0);
OutputStream os = new WriterOutputStream(writer);
ug.writeImage(os, null, 96);
os.flush();
}
private void drawLine(UGraphic ug, double x1, double y1, double x2, double y2) {
ug = ug.apply(new UTranslate(x1, y1));
ug.draw(new ULine(x2 - x1, y2 - y1));
}
private int getRound(double value) {
final int step = (int) Math.ceil(value / 5.0);
return NiceNumber.getNicer(step * 5);
}
private void printScale(UGraphic ug, int step, double coef, double totalWidth) {
final FontConfiguration fontConfiguration = new FontConfiguration(fontLegend, HtmlColorUtils.BLACK);
final ULine hline = new ULine(totalWidth, 0);
ug = ug.apply(new UChangeColor(HtmlColorUtils.GRAY));
for (int i = 0; i <= max; i += step) {
final double v = i * coef;
String label = "" + i;
final UText text = new UText(label, fontConfiguration);
ug.apply(new UTranslate(0, -v)).draw(text);
ug.apply(new UTranslate(10, -v)).apply(new UStroke(2, 2, 1)).draw(hline);
}
}
}

View File

@ -0,0 +1,66 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import java.util.TreeMap;
import net.sourceforge.plantuml.pstat.time.DateManager;
public class HistogramBuilder {
private final DateManager dateManager;
private final int histoSize;
private final TreeMap<Integer, MutableInteger> data = new TreeMap<Integer, MutableInteger>();
public HistogramBuilder(DateManager dateManager, int histoSize) {
this.dateManager = dateManager;
this.histoSize = histoSize;
}
public Histogram getHistogram(double height, double singleBarWidth, int fontSize) {
final Histogram histogram = new Histogram(height, singleBarWidth, fontSize);
if (data.size() > 0) {
final int last = data.lastKey();
for (int i = last - histoSize + 1; i <= last; i++) {
final String label = dateManager.getDescriptionShort(i);
final MutableInteger n = data.get(i);
final int value = n == null ? 0 : n.intValue();
final String title = "[" + value + " diagrams] at [" + dateManager.getDescription(i) + "]";
histogram.addData(label, value, title);
}
}
return histogram;
}
public void incKey(long time, int value) {
final int k = dateManager.toNumber(time);
final MutableInteger v = data.get(k);
if (v == null) {
data.put(k, new MutableInteger(value));
} else {
v.inc(value);
}
}
}

View File

@ -0,0 +1,42 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
public class MutableInteger {
private int value;
public MutableInteger(int value) {
this.value = value;
}
public void inc(int delta) {
value += delta;
}
public int intValue() {
return value;
}
}

View File

@ -0,0 +1,47 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
public class NiceNumber {
public static int getNicer(final int value) {
if (value <= 18) {
return value;
}
if (value < 93) {
return ((value + 2) / 5) * 5;
}
if (value < 100) {
return ((value + 5) / 10) * 10;
}
int m = 1;
double head = value;
while (head >= 100) {
head = head / 10.0;
m *= 10;
}
return getNicer((int) Math.round(head)) * m;
}
}

View File

@ -0,0 +1,95 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.graph;
import junit.framework.TestCase;
public class NiceNumberTest extends TestCase {
public void testGetNicer203() {
assertEquals(200, NiceNumber.getNicer(203));
assertEquals(1200, NiceNumber.getNicer(1154));
}
public void testGetNicer5249() {
assertEquals(5000, NiceNumber.getNicer(5249));
assertEquals(5500, NiceNumber.getNicer(5250));
}
public void testGetNicerFull() {
assertEquals(-1, NiceNumber.getNicer(-1));
assertEquals(1, NiceNumber.getNicer(1));
assertEquals(2, NiceNumber.getNicer(2));
assertEquals(3, NiceNumber.getNicer(3));
assertEquals(4, NiceNumber.getNicer(4));
assertEquals(5, NiceNumber.getNicer(5));
assertEquals(6, NiceNumber.getNicer(6));
assertEquals(7, NiceNumber.getNicer(7));
assertEquals(8, NiceNumber.getNicer(8));
assertEquals(9, NiceNumber.getNicer(9));
assertEquals(10, NiceNumber.getNicer(10));
assertEquals(11, NiceNumber.getNicer(11));
assertEquals(12, NiceNumber.getNicer(12));
assertEquals(13, NiceNumber.getNicer(13));
assertEquals(14, NiceNumber.getNicer(14));
assertEquals(15, NiceNumber.getNicer(15));
assertEquals(16, NiceNumber.getNicer(16));
assertEquals(17, NiceNumber.getNicer(17));
assertEquals(18, NiceNumber.getNicer(18));
assertEquals(20, NiceNumber.getNicer(19));
assertEquals(20, NiceNumber.getNicer(20));
assertEquals(20, NiceNumber.getNicer(21));
assertEquals(20, NiceNumber.getNicer(22));
assertEquals(25, NiceNumber.getNicer(23));
assertEquals(25, NiceNumber.getNicer(24));
assertEquals(25, NiceNumber.getNicer(25));
assertEquals(25, NiceNumber.getNicer(26));
assertEquals(25, NiceNumber.getNicer(27));
assertEquals(30, NiceNumber.getNicer(28));
assertEquals(30, NiceNumber.getNicer(29));
assertEquals(30, NiceNumber.getNicer(30));
assertEquals(80, NiceNumber.getNicer(80));
assertEquals(80, NiceNumber.getNicer(81));
assertEquals(80, NiceNumber.getNicer(82));
assertEquals(85, NiceNumber.getNicer(83));
assertEquals(85, NiceNumber.getNicer(84));
assertEquals(85, NiceNumber.getNicer(85));
assertEquals(85, NiceNumber.getNicer(86));
assertEquals(85, NiceNumber.getNicer(87));
assertEquals(90, NiceNumber.getNicer(88));
assertEquals(90, NiceNumber.getNicer(89));
assertEquals(90, NiceNumber.getNicer(90));
assertEquals(90, NiceNumber.getNicer(91));
assertEquals(90, NiceNumber.getNicer(92));
assertEquals(90, NiceNumber.getNicer(93));
assertEquals(90, NiceNumber.getNicer(94));
assertEquals(100, NiceNumber.getNicer(95));
assertEquals(100, NiceNumber.getNicer(96));
assertEquals(100, NiceNumber.getNicer(97));
assertEquals(100, NiceNumber.getNicer(98));
assertEquals(100, NiceNumber.getNicer(99));
}
}

View File

@ -0,0 +1,56 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.ArrayList;
import java.util.List;
import net.sourceforge.plantuml.pstat.graph.Chart;
import net.sourceforge.plantuml.pstat.graph.ChartProducer;
import net.sourceforge.plantuml.pstat.graph.HistogramBuilder;
import net.sourceforge.plantuml.pstat.time.DateManager;
public class CounterSetInteger {
private final List<Integer> imageGeneration = new ArrayList<Integer>();
private final HistogramBuilder builder;
public HistogramBuilder getHistogramBuilder() {
return builder;
}
public Chart getChartImageGeneration(double height) {
return new ChartProducer(imageGeneration).getChart(height);
}
public CounterSetInteger(DateManager dateManager, int histoSize) {
builder = new HistogramBuilder(dateManager, histoSize);
}
public void increment(TickImageGeneration tick) {
imageGeneration.add(tick.getDuration());
builder.incKey(tick.getStartMinute() * 1000L * 60, 1);
}
}

View File

@ -0,0 +1,57 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.ArrayList;
import java.util.Collection;
import net.sourceforge.plantuml.pstat.graph.Chart;
import net.sourceforge.plantuml.pstat.graph.ChartProducer;
public class CounterSetLoad {
private final Collection<Integer> pageLoad = new ArrayList<Integer>();
private final Collection<Integer> imageLoad = new ArrayList<Integer>();
public CounterSetLoad() {
}
public void increment(TickBrowser tick) {
if (tick.getImageLoad() > 0) {
imageLoad.add(tick.getImageLoad());
}
if (tick.getPageLoad() > 0) {
pageLoad.add(tick.getPageLoad());
}
}
public Chart getChartPageLoad(double height) {
return new ChartProducer(pageLoad).getChart(height);
}
public Chart getChartImageLoad(double height) {
return new ChartProducer(imageLoad).getChart(height);
}
}

View File

@ -0,0 +1,146 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Map;
import java.util.TreeMap;
import net.sourceforge.plantuml.pstat.graph.Chart;
import net.sourceforge.plantuml.pstat.graph.HistoList;
public class CounterSetString {
private final Map<String, Integer> language = new TreeMap<String, Integer>();
private final Map<String, Integer> host = new TreeMap<String, Integer>();
private final Map<String, Integer> operationSystem = new TreeMap<String, Integer>();
private final Map<String, Integer> browser = new TreeMap<String, Integer>();
private final Map<String, Integer> referer = new TreeMap<String, Integer>();
private final Map<String, Integer> type = new TreeMap<String, Integer>();
private final Map<String, Integer> incomming = new TreeMap<String, Integer>();
private final Map<String, Integer> country = new TreeMap<String, Integer>();
public void increment(TickImageGeneration tick) {
increment(language, tick.getAcceptLanguage());
increment(host, tick.getHost());
increment(operationSystem, tick.getOperatingSystem());
increment(browser, tick.getBrowser());
increment(referer, tick.getReferer());
increment(type, tick.getType());
increment(incomming, tick.getIncomming());
increment(country, tick.getCountry());
}
private void increment(Map<String, Integer> data, String s) {
final Integer v = data.get(s);
if (v == null) {
data.put(s, 1);
} else {
data.put(s, v + 1);
}
}
public String getTitle() {
return "language.getTitle()";
}
public Chart getChartLanguage(double height) {
return getChart(height, language);
}
public Chart getChartHost(double height) {
return getChart(height, host);
}
public Chart getChartOperationSystem(double height) {
return getChart(height, operationSystem);
}
public Chart getChartBrowser(double height) {
return getChart(height, browser);
}
public Chart getChartReferer(double height) {
return getChart(height, referer);
}
public Chart getChartType(double height) {
return getChart(height, type);
}
public Chart getChartIncomming(double height) {
return getChart(height, incomming);
}
private Chart getChart(double height, Map<String, Integer> counter) {
final Chart chart = new Chart(height);
for (Map.Entry<String, Integer> ent : counter.entrySet()) {
final String s = ent.getKey();
if ("??".equals(s)) {
continue;
}
chart.addData(s, ent.getValue());
}
chart.compact();
return chart;
}
public Chart getChartRefererOther(double height) {
final Chart chart = new Chart(height);
for (Map.Entry<String, Integer> ent : referer.entrySet()) {
final String s = ent.getKey();
if ("??".equals(s) || "http://www.plantuml.com".equals(s) || "http://plantuml.com".equals(s)
|| "http://plantuml.sourceforge.net".equals(s) || "Other".equals(s)) {
continue;
}
chart.addData(s, ent.getValue());
}
chart.removeBig(0.5);
return chart;
}
public HistoList getHistoListReferer(double graphWidth, double singleBarHeight, int fontSize) {
final HistoList chart = new HistoList(graphWidth, singleBarHeight, fontSize);
for (Map.Entry<String, Integer> ent : referer.entrySet()) {
final String s = ent.getKey();
if ("??".equals(s)) {
continue;
}
chart.addData(s, ent.getValue());
}
return chart;
}
public HistoList getHistoListCountry(double graphWidth, double singleBarHeight, int fontSize) {
final HistoList chart = new HistoList(graphWidth, singleBarHeight, fontSize);
for (Map.Entry<String, Integer> ent : country.entrySet()) {
final String s = ent.getKey();
if ("??".equals(s)) {
continue;
}
chart.addData(s, ent.getValue());
}
return chart;
}
}

View File

@ -0,0 +1,42 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.concurrent.atomic.AtomicInteger;
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
public class DailyStat {
private final AtomicInteger size = new AtomicInteger();
public void updateStats(StatEventImageGeneration ev) {
size.incrementAndGet();
}
public int getSize() {
return size.intValue();
}
}

View File

@ -0,0 +1,56 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Date;
public class Day {
private final int nday;
public Day(long time) {
nday = (int) (time / 1000L / 3600 / 24);
}
@Override
public int hashCode() {
return nday;
}
@Override
public boolean equals(Object o) {
final Day other = (Day) o;
return nday == other.nday;
}
@Override
public String toString() {
return new Date(nday * 1000L * 3600 * 24).toGMTString();
}
public long getTime() {
return nday * 1000L * 3600 * 24;
}
}

View File

@ -0,0 +1,152 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Iterator;
import net.sourceforge.plantuml.pstat.time.DateManager;
public class GraphData {
// private final CounterSet2 days31 = new CounterSet2();
private final CounterSetString days15 = new CounterSetString();
private final CounterSetString hours48 = new CounterSetString();
private final CounterSetString minutes60 = new CounterSetString();
private final CounterSetString minutes10 = new CounterSetString();
private final CounterSetInteger hdays15 = new CounterSetInteger(DateManager.DAILY, 15);
private final CounterSetInteger hhours48 = new CounterSetInteger(DateManager.HOURLY, 48);
private final CounterSetInteger hminutes60 = new CounterSetInteger(DateManager.MINUTELY, 60);
private final CounterSetInteger hminutes10 = new CounterSetInteger(DateManager.MINUTELY, 10);
private final CounterSetLoad browserDay15 = new CounterSetLoad();
private final CounterSetLoad browserHours48 = new CounterSetLoad();
private final CounterSetLoad browserMinutes60 = new CounterSetLoad();
private final CounterSetLoad browserMinutes10 = new CounterSetLoad();
public GraphData() {
}
public GraphData(Iterator<TickImageGeneration> iterator, Iterator<TickBrowser> iterator2) {
final int now = (int) (System.currentTimeMillis() / 1000L / 60);
while (iterator.hasNext()) {
final TickImageGeneration tick = iterator.next();
final int startMinute = tick.getStartMinute();
// if (startMinute >= now - 31 * 24 * 50) {
// days31.increment(tick);
// } else {
// iterator.remove();
// }
if (startMinute >= now - 15 * 24 * 60) {
days15.increment(tick);
hdays15.increment(tick);
} else {
iterator.remove();
}
if (startMinute >= now - 48 * 60) {
hours48.increment(tick);
hhours48.increment(tick);
}
if (startMinute >= now - 60) {
minutes60.increment(tick);
hminutes60.increment(tick);
}
if (startMinute >= now - 10) {
minutes10.increment(tick);
hminutes10.increment(tick);
}
}
while (iterator2.hasNext()) {
final TickBrowser tick = iterator2.next();
final int startMinute = tick.getStartMinute();
if (startMinute >= now - 15 * 24 * 60) {
browserDay15.increment(tick);
} else {
iterator2.remove();
}
if (startMinute >= now - 24 * 60) {
browserHours48.increment(tick);
}
if (startMinute >= now - 60) {
browserMinutes60.increment(tick);
}
if (startMinute >= now - 10) {
browserMinutes10.increment(tick);
}
}
}
// public final CounterSet2 days31() {
// return days31;
// }
public final CounterSetString days15() {
return days15;
}
public final CounterSetString hours48() {
return hours48;
}
public final CounterSetString minutes60() {
return minutes60;
}
public final CounterSetString minutes10() {
return minutes10;
}
public final CounterSetInteger hdays15() {
return hdays15;
}
public final CounterSetInteger hhours48() {
return hhours48;
}
public final CounterSetInteger hminutes60() {
return hminutes60;
}
public final CounterSetInteger hminutes10() {
return hminutes10;
}
public final CounterSetLoad bdays15() {
return browserDay15;
}
public final CounterSetLoad bhours48() {
return browserHours48;
}
public final CounterSetLoad bminutes60() {
return browserMinutes60;
}
public final CounterSetLoad bminutes10() {
return browserMinutes10;
}
}

View File

@ -0,0 +1,53 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import net.sourceforge.plantuml.pstat.graph.HistogramBuilder;
import net.sourceforge.plantuml.pstat.time.DateManager;
public class GraphDataLongTerm {
private final HistogramBuilder builder = new HistogramBuilder(DateManager.MONTHLY, 24);
public GraphDataLongTerm(Iterator<Entry<Day, DailyStat>> it) {
while (it.hasNext()) {
Map.Entry<Day, DailyStat> ent = it.next();
final Day day = ent.getKey();
final DailyStat stat = ent.getValue();
builder.incKey(day.getTime(), stat.getSize());
}
}
public GraphDataLongTerm() {
}
public HistogramBuilder getHistogramBuilder() {
return builder;
}
}

View File

@ -0,0 +1,87 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import net.sourceforge.plantuml.pstat.event.StatEvent;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
public class TickBrowser {
// private final String token;
private int pageLoad = -1;
private int imageLoad = -1;
private final int startMinute;
public TickBrowser(StatEvent stat) {
startMinute = (int) (stat.getStartServerTime() / 1000L / 60);
// if (stat instanceof StatEventHtmlLoadImage) {
// final StatEventHtmlLoadImage ev = (StatEventHtmlLoadImage) stat;
// // token = ev.getToken();
//
// } else if (stat instanceof StatEventHtmlLoadPage) {
// final StatEventHtmlLoadPage ev = (StatEventHtmlLoadPage) stat;
// // token = ev.getToken();
//
// } else if (stat instanceof StatEventHtmlCreate) {
// final StatEventHtmlCreate ev = (StatEventHtmlCreate) stat;
// // token = ev.getToken();
// } else {
// throw new IllegalArgumentException();
// }
update(stat);
}
public void update(StatEvent stat) {
if (stat instanceof StatEventHtmlLoadImage) {
final StatEventHtmlLoadImage ev = (StatEventHtmlLoadImage) stat;
imageLoad = ev.getImageLoad();
} else if (stat instanceof StatEventHtmlLoadPage) {
final StatEventHtmlLoadPage ev = (StatEventHtmlLoadPage) stat;
pageLoad = ev.getPageLoad();
} else if (stat instanceof StatEventHtmlCreate) {
final StatEventHtmlCreate ev = (StatEventHtmlCreate) stat;
} else {
throw new IllegalArgumentException();
}
}
public final int getPageLoad() {
return pageLoad;
}
public final int getImageLoad() {
return imageLoad;
}
public final int getStartMinute() {
return startMinute;
}
}

View File

@ -0,0 +1,48 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
class TickCollectionFilterTime extends AbstractCollection<TickImageGeneration> {
private final Collection<TickImageGeneration> all;
private final int timeLimitMinute;
TickCollectionFilterTime(Collection<TickImageGeneration> all, int timeLimitMinute) {
this.all = all;
this.timeLimitMinute = timeLimitMinute;
}
public Iterator<TickImageGeneration> iterator() {
return new TickFilterIterator(all.iterator(), timeLimitMinute);
}
public int size() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,97 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import net.sourceforge.plantuml.pstat.event.StatEvent;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlCreate;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadImage;
import net.sourceforge.plantuml.pstat.event.StatEventHtmlLoadPage;
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
public class TickDatabase {
private final LinkedBlockingDeque<TickImageGeneration> all = new LinkedBlockingDeque<TickImageGeneration>();
private final ConcurrentHashMap<String, TickBrowser> browser = new ConcurrentHashMap<String, TickBrowser>();
private final ConcurrentHashMap<Day, DailyStat> dailyStats = new ConcurrentHashMap<Day, DailyStat>();
public void updateStats(StatEvent ev) {
if (ev instanceof StatEventImageGeneration) {
final StatEventImageGeneration ev2 = (StatEventImageGeneration) ev;
final TickImageGeneration tick = new TickImageGeneration(ev2);
final int duration = tick.getDuration();
if (duration > 0) {
all.add(tick);
}
final Day day = new Day(ev2.getStartServerTime());
DailyStat dailyStat = dailyStats.get(day);
if (dailyStat == null) {
dailyStat = new DailyStat();
final DailyStat old = dailyStats.putIfAbsent(day, dailyStat);
if (old != null) {
dailyStat = old;
}
}
dailyStat.updateStats(ev2);
} else if (ev instanceof StatEventHtmlLoadImage || ev instanceof StatEventHtmlLoadPage
|| ev instanceof StatEventHtmlCreate) {
final String token = getToken(ev);
TickBrowser tickBrowser = browser.get(token);
if (tickBrowser == null) {
tickBrowser = new TickBrowser(ev);
final TickBrowser old = browser.putIfAbsent(token, tickBrowser);
if (old != null) {
tickBrowser = old;
}
}
tickBrowser.update(ev);
}
}
static private String getToken(StatEvent ev) {
if (ev instanceof StatEventHtmlLoadImage) {
return ((StatEventHtmlLoadImage) ev).getToken();
}
if (ev instanceof StatEventHtmlLoadPage) {
return ((StatEventHtmlLoadPage) ev).getToken();
}
if (ev instanceof StatEventHtmlCreate) {
return ((StatEventHtmlCreate) ev).getToken();
}
throw new IllegalArgumentException();
}
public GraphData getGraphData() {
return new GraphData(all.iterator(), browser.values().iterator());
}
public GraphDataLongTerm getGraphDataLongTerm() {
return new GraphDataLongTerm(dailyStats.entrySet().iterator());
}
}

View File

@ -0,0 +1,68 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Iterator;
import java.util.NoSuchElementException;
class TickFilterIterator implements Iterator<TickImageGeneration> {
private final Iterator<TickImageGeneration> it;
private final int timeLimitMinute;
private TickImageGeneration potentialNext;
TickFilterIterator(Iterator<TickImageGeneration> it, int timeLimitMinute) {
this.it = it;
this.timeLimitMinute = timeLimitMinute;
this.potentialNext = getPotentialNext();
}
private TickImageGeneration getPotentialNext() {
while (it.hasNext()) {
potentialNext = it.next();
if (potentialNext.getStartMinute() >= timeLimitMinute) {
return potentialNext;
}
}
return null;
}
public boolean hasNext() {
return potentialNext != null;
}
public TickImageGeneration next() {
if (potentialNext == null) {
throw new NoSuchElementException();
}
final TickImageGeneration result = potentialNext;
potentialNext = getPotentialNext();
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,102 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.tick;
import java.util.Date;
import net.sourceforge.plantuml.pstat.event.StatEventImageGeneration;
public class TickImageGeneration {
private final String country;
private final String acceptLanguage;
private final String browser;
private final String operatingSystem;
private final String referer;
private final String type;
private final String incomming;
private final String host;
private final int startMinute;
private final int duration;
public TickImageGeneration(StatEventImageGeneration stat) {
this.country = stat.getCountry();
this.acceptLanguage = stat.getAcceptLanguage();
this.browser = stat.getBrowser();
this.operatingSystem = stat.getOperatingSystem();
this.referer = stat.getReferer();
this.incomming = stat.getIncomming();
this.host = stat.getHost();
this.type = stat.getType();
this.startMinute = (int) (stat.getStartServerTime() / 1000L / 60);
this.duration = stat.getDuration();
}
@Override
public String toString() {
return "tick " + new Date(startMinute * 1000L * 60).toGMTString();
}
public final String getCountry() {
return country;
}
public final String getAcceptLanguage() {
return acceptLanguage;
}
public final String getBrowser() {
return browser;
}
public final String getOperatingSystem() {
return operatingSystem;
}
public final String getReferer() {
return referer;
}
public final String getType() {
return type;
}
public final int getStartMinute() {
return startMinute;
}
public final int getDuration() {
return duration;
}
public final String getIncomming() {
return incomming;
}
public final String getHost() {
return host;
}
}

View File

@ -0,0 +1,40 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
public interface DateManager {
public static final DateManager DAILY = new DateManagerDaily();
public static final DateManager HOURLY = new DateManagerHourly();
public static final DateManager MINUTELY = new DateManagerMinutely();
public static final DateManager MONTHLY = new DateManagerMonthly();
public static final DateManager YEARLY = new DateManagerYear();
public int toNumber(long date);
public String getDescription(int number);
public String getDescriptionShort(int number);
}

View File

@ -0,0 +1,55 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
class DateManagerDaily implements DateManager {
private static final long COEF = 1000L * 3600 * 24;
public int toNumber(long date) {
final long m = date / COEF;
return (int) m;
}
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd", Locale.US);
// private static DateFormat dfShort = new SimpleDateFormat("dd", Locale.US);
public String getDescription(int number) {
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd", Locale.US);
final Date date = new Date(number * COEF);
return df.format(date);
}
public String getDescriptionShort(int number) {
final DateFormat dfShort = new SimpleDateFormat("dd", Locale.US);
final Date date = new Date(number * COEF);
return dfShort.format(date);
}
}

View File

@ -0,0 +1,56 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
class DateManagerHourly implements DateManager {
private static final long COEF = 1000L * 3600;
public int toNumber(long date) {
final long m = date / COEF;
return (int) m;
}
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:00", Locale.US);
// private static DateFormat dfShort = new SimpleDateFormat("HH", Locale.US);
public String getDescription(int number) {
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:00", Locale.US);
final Date date = new Date(number * COEF);
return df.format(date);
// return date.toString();
}
public String getDescriptionShort(int number) {
final DateFormat dfShort = new SimpleDateFormat("HH", Locale.US);
final Date date = new Date(number * COEF);
return dfShort.format(date);
}
}

View File

@ -0,0 +1,56 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
class DateManagerMinutely implements DateManager {
private static final long COEF = 1000L * 60;
public int toNumber(long date) {
final long m = date / COEF;
return (int) m;
}
// private static DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:mm", Locale.US);
// private static DateFormat dfShort = new SimpleDateFormat("mm", Locale.US);
public String getDescription(int number) {
final DateFormat df = new SimpleDateFormat("yyyy MMM EEE dd HH:mm", Locale.US);
final Date date = new Date(number * COEF);
return df.format(date);
// return date.toString();
}
public String getDescriptionShort(int number) {
final DateFormat dfShort = new SimpleDateFormat("mm", Locale.US);
final Date date = new Date(number * COEF);
return dfShort.format(date);
}
}

View File

@ -0,0 +1,52 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
import java.util.Date;
class DateManagerMonthly implements DateManager {
static private final String[] MONTH = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
"Nov", "Dec" };
public int toNumber(long d) {
final Date date = new Date(d);
return date.getYear() * 12 + date.getMonth();
}
public String getDescription(int number) {
final int month = number % 12;
final int year = number / 12;
return MONTH[month] + " " + (1900 + year);
}
public String getDescriptionShort(int number) {
final int month = number % 12;
return MONTH[month];
// final int month = number % 12;
// final int year = number / 12;
// return "" + (year - 100) + "/" + String.format("%02d", month + 1);
}
}

View File

@ -0,0 +1,44 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* Project Info: http://plantuml.sourceforge.net
*
* This file is part of PlantUML.
*
* PlantUML 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 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package net.sourceforge.plantuml.pstat.time;
import java.util.Date;
class DateManagerYear implements DateManager {
public int toNumber(long d) {
final Date date = new Date(d);
return date.getYear();
}
public String getDescription(int number) {
return "Year " + (1900 + number);
}
public String getDescriptionShort(int number) {
return "" + (1900 + number);
}
}