mirror of
https://github.com/octoleo/plantuml-server.git
synced 2024-12-31 11:51:48 +00:00
[FEATURE] Add stat packages
This commit is contained in:
parent
8799670f1d
commit
0cfaaf9bbc
@ -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);
|
||||||
|
}
|
@ -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 {
|
||||||
|
}
|
||||||
|
}
|
312
src/main/java/net/sourceforge/plantuml/pstat/Stats.java
Normal file
312
src/main/java/net/sourceforge/plantuml/pstat/Stats.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
285
src/main/java/net/sourceforge/plantuml/pstat/graph/Chart.java
Normal file
285
src/main/java/net/sourceforge/plantuml/pstat/graph/Chart.java
Normal 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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
156
src/main/java/net/sourceforge/plantuml/pstat/graph/Curve.java
Normal file
156
src/main/java/net/sourceforge/plantuml/pstat/graph/Curve.java
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
56
src/main/java/net/sourceforge/plantuml/pstat/tick/Day.java
Normal file
56
src/main/java/net/sourceforge/plantuml/pstat/tick/Day.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
152
src/main/java/net/sourceforge/plantuml/pstat/tick/GraphData.java
Normal file
152
src/main/java/net/sourceforge/plantuml/pstat/tick/GraphData.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user