Skip to content
Snippets Groups Projects
Commit ccb34fd8 authored by Radek Ošlejšek's avatar Radek Ošlejšek
Browse files

Merge branch...

Merge branch '115-make-logging-into-the-outputwindow-available-from-low-level-modules' into 'master'

Resolve "Make logging into the OutputWindow available from low-level modules"

Closes #115

See merge request grp-fidentis/analyst2!127
parents 42761201 a721e90e
No related branches found
No related tags found
No related merge requests found
......@@ -18,7 +18,7 @@ public class RandomStrategy extends UndersamplingStrategy {
/**
* Constructor for PERCENTAGE undersampling type.
*
* @param perc Percentage - a value in (0.0, 1.0&gtl
* @param perc Percentage - a value in (0.0, 1.0>
* @throws IllegalArgumentException if the input parameter is wrong
*/
public RandomStrategy(double perc) {
......
package cz.fidentis.analyst.core;
import cz.fidentis.analyst.Logger;
import java.awt.BorderLayout;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.List;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingWorker;
import org.openide.windows.TopComponent;
import org.openide.windows.WindowManager;
/**
* Wrapper for default output window of the Java Netbeans Platform application.
* It enables to write debug messages into the window.
* Wrapper of the default Java Netbeans Platform output window.
* This wrapper runs in the worker thread, reads messages logged through
* the {@link cz.fidentis.analyst.Logger} and displays them in the output window.
*
* The {@code OutputWindow} is currently executed from
* the {@link cz.fidentis.analyst.core.ProjectTopComp}, which is always presented.
*
* @author Radek Oslejsek
*/
public class OutputWindow {
public class OutputWindow extends SwingWorker<String, String> {
private static JTextArea textArea;
private long lastTime = System.currentTimeMillis();
protected OutputWindow() {
initTextArea();
}
/**
* Prints the message.
*
* @param msg Message to be printed
* Constructor.
*/
public static void print(String msg) {
JTextArea ta = initTextArea();
ta.setText(ta.getText()
+ new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+ " [duration unknown]: "
+ msg.trim()
+ System.lineSeparator()
);
public OutputWindow() {
TopComponent outputWin = WindowManager.getDefault().findTopComponent("output");
textArea = new JTextArea();
JScrollPane sp = new JScrollPane(textArea);
outputWin.add(sp, BorderLayout.CENTER);
}
/**
* Starts measuring of some operation.
* Call {@link #printDuration(java.lang.String)} on returned OutputWindow
* to print the measured duration.
* Reads messages of the {@code Logger} in the background and re-sends them
* the {@link #process(java.util.List)} method.
*
* @return An object used to print measured duration and message
* @return Complete text displayed in the output window.
* @throws Exception
*/
public static OutputWindow measureTime() {
OutputWindow ret = new OutputWindow();
ret.lastTime = System.currentTimeMillis();
return ret;
@Override
protected String doInBackground() throws Exception {
String line = Logger.reader().readLine();
while (line != null) {
publish(line);
line = Logger.reader().readLine();
}
return textArea.getText();
}
/**
* Prints the message about an operation and the duration of the operation.
* The duration is computed as the difference between current system time and
* the time of calling {@link #measureTime()}. The time difference is measured in
* milliseconds and printed as [+mm:ss.SSS] where mm=minutes, ss=seconds,
* and SSS=milliseconds.
* Takes text lines process by the {@link #doInBackground()} method and
* adds them to the output window.
*
* @param msg Message to be printed
* @param chunks process lines
*/
public void printDuration(String msg) {
Duration duration = Duration.ofMillis(System.currentTimeMillis() - lastTime);
textArea.setText(textArea.getText()
+ new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+ " [duration "
+ String.format(
"%02d:%02d.%03d",
duration.toMinutes(),
duration.toSecondsPart(),
duration.toMillisPart())
+ "]: "
+ msg.trim()
+ System.lineSeparator()
);
}
protected static JTextArea initTextArea() {
if (textArea == null) {
TopComponent outputWin = WindowManager.getDefault().findTopComponent("output");
textArea = new JTextArea();
JScrollPane sp = new JScrollPane(textArea);
outputWin.add(sp, BorderLayout.CENTER);
}
return textArea;
@Override
protected void process(List<String> chunks) {
StringBuilder sb = new StringBuilder();
sb.append(textArea.getText());
chunks.forEach(str -> {
sb.append(str + System.lineSeparator());
});
textArea.setText(sb.toString());
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package cz.fidentis.analyst.core;
import cz.fidentis.analyst.Logger;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
......@@ -84,6 +80,10 @@ public final class ProjectTopComp extends TopComponent {
putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
// Execute OutputWindow in the worker thread so that messages
// logged via Logger are displayed in the output window
(new OutputWindow()).execute();
}
/**
......@@ -671,7 +671,7 @@ public final class ProjectTopComp extends TopComponent {
if (files == null) {
System.out.print("No file chosen.");
} else {
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
for (File file : files) {
String faceId = HumanFaceFactory.instance().loadFace(file);
HumanFace face = HumanFaceFactory.instance().getFace(faceId);
......
package cz.fidentis.analyst.curvature;
import cz.fidentis.analyst.Logger;
import cz.fidentis.analyst.canvas.Canvas;
import cz.fidentis.analyst.core.ControlPanelAction;
import cz.fidentis.analyst.core.OutputWindow;
import cz.fidentis.analyst.visitors.mesh.Curvature;
import java.awt.event.ActionEvent;
import javax.swing.JComboBox;
......@@ -77,7 +77,7 @@ public class CurvatureAction extends ControlPanelAction {
protected void setHeatmap() {
if (visitor == null) { // compute missing curvature
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
this.visitor = new Curvature();
getPrimaryDrawableFace().getModel().compute(visitor);
out.printDuration("Computation of curvature for a model with "
......
package cz.fidentis.analyst.distance;
import com.jogamp.opengl.GL2;
import cz.fidentis.analyst.Logger;
import cz.fidentis.analyst.canvas.Canvas;
import cz.fidentis.analyst.core.LoadedActionEvent;
import cz.fidentis.analyst.core.ControlPanelAction;
import cz.fidentis.analyst.core.ControlPanelBuilder;
import cz.fidentis.analyst.core.OutputWindow;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.feature.FeaturePointType;
import cz.fidentis.analyst.mesh.core.MeshFacet;
......@@ -267,7 +267,7 @@ public class DistanceAction extends ControlPanelAction {
throw new UnsupportedOperationException(strategy);
}
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
this.visitor = new HausdorffDistancePrioritized(getPrimaryDrawableFace().getModel(),
featurePoints,
useStrategy,
......
package cz.fidentis.analyst.registration;
import cz.fidentis.analyst.Logger;
import cz.fidentis.analyst.canvas.Canvas;
import cz.fidentis.analyst.core.ControlPanelAction;
import cz.fidentis.analyst.core.OutputWindow;
import cz.fidentis.analyst.face.HumanFace;
import cz.fidentis.analyst.feature.FeaturePoint;
import cz.fidentis.analyst.icp.IcpTransformation;
......@@ -258,7 +258,7 @@ public class RegistrationAction extends ControlPanelAction {
}
protected void applyICP() {
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
IcpTransformer visitor = new IcpTransformer(getPrimaryDrawableFace().getModel(), maxIterations, scale, error, undersampling);
getSecondaryDrawableFace().getModel().compute(visitor); // NOTE: the secondary face is physically transformed
......@@ -306,7 +306,7 @@ public class RegistrationAction extends ControlPanelAction {
* otherwise set color to default
*/
private void calculateFeaturePoints() {
OutputWindow.print("Calculation of feature points");
Logger.print("Calculation of feature points");
if (getPrimaryDrawableFace() == null) { // scene not yet initiated
return;
......@@ -346,7 +346,7 @@ public class RegistrationAction extends ControlPanelAction {
}
private void calculateHausdorffDistance() {
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
HumanFace primFace = getScene().getHumanFace(0);
primFace.computeKdTree(false);
......@@ -467,7 +467,7 @@ public class RegistrationAction extends ControlPanelAction {
}
if (hdVisitor == null) {
OutputWindow out = OutputWindow.measureTime();
Logger out = Logger.measureTime();
this.hdVisitor = new HausdorffDistance(getPrimaryDrawableFace().getModel(), useStrategy, relativeDist, true);
getSecondaryDrawableFace().getModel().compute(hdVisitor);
......
......@@ -17,6 +17,7 @@
<configuration>
<useOSGiDependencies>true</useOSGiDependencies>
<publicPackages> <!-- expose API/packages to other modules -->
<publicPackage>cz.fidentis.analyst.*</publicPackage>
<publicPackage>cz.fidentis.analyst.mesh.core.*</publicPackage>
<publicPackage>cz.fidentis.analyst.mesh.io.*</publicPackage>
<publicPackage>cz.fidentis.analyst.mesh.*</publicPackage>
......
package cz.fidentis.analyst;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.logging.Level;
/**
* A logging class that can be used from anywhere to display debugging or other
* messages.
* <p>
* Messages are printed into the standard output unless the {@link #reader()}
* method is called. Then the messages are redirected to the returned {@code BufferedReader}.
* </p>
* <p>
* The implementation supposes that the caller of the {@link #reader()} method
* (or other object} will read the messages from the {@code BufferedReader} forever.
* Otherwise, the program can freeze due to the full buffer.
* </p>
* <p>
* FIDENTIS application automatically redirects logged messages to the output window.
* </p>
* <p>
* <b>Usage:</b>
* <ul>
* <li>To print a message, use {@code Logger.print("message")}. A timestamp is added automatically.</li>
* <li>To print message together with duration, call {@code Logger log = Logger.measureTime();},
* then call the measured operations and finally call {@code log.printDuration("message")}.
* a timestamp and measured duration are added to the log message automatically.</li>
* </ul>
* </p>
*
* @author Radek Oslejsek
*/
public final class Logger {
private static PrintStream out = System.out;
private static BufferedReader in;
private long lastTime = System.currentTimeMillis();
private Logger() {
}
/**
* Redirects logs from standard output to the {@code BufferedReader}.
*
* @return {@code BufferedReader} to which the logs are redirected.
*/
public static BufferedReader reader() {
if (in == null) {
PipedOutputStream pOut = new PipedOutputStream();
out = new PrintStream(pOut);
try {
in = new BufferedReader(new InputStreamReader(new PipedInputStream(pOut)));
} catch (IOException ex) {
java.util.logging.Logger.getLogger(Logger.class.getName()).log(Level.SEVERE, null, ex);
}
}
return in;
}
/**
* Prints a message. The log time added automatically.
*
* @param msg Message to be logged
*/
public static void print(String msg) {
String outMsg =
new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+ " [duration unknown]: "
+ msg.trim();
out.println(outMsg);
}
/**
* Starts measuring of some operation.
* Call {@link #printDuration(java.lang.String)} on returned object
* to print the measured duration.
*
* @return An object used to print measured duration and message
*/
public static Logger measureTime() {
Logger ret = new Logger();
ret.lastTime = System.currentTimeMillis();
return ret;
}
/**
* Prints the message about an operation and the duration of the operation.
* The duration is computed as the difference between current system time and
* the time of calling {@link #measureTime()}. The time difference is measured in
* milliseconds and printed as [+mm:ss.SSS] where mm=minutes, ss=seconds,
* and SSS=milliseconds.
*
* @param msg Message to be printed
*/
public void printDuration(String msg) {
Duration duration = Duration.ofMillis(System.currentTimeMillis() - lastTime);
String outMsg =
new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis())
+ " [duration "
+ String.format(
"%02d:%02d.%03d",
duration.toMinutes(),
duration.toSecondsPart(),
duration.toMillisPart())
+ "]: "
+ msg.trim();
out.println(outMsg);
}
}
......@@ -19,7 +19,7 @@ public class FeaturePointCsvExporter {
/**
* Exports a file to set location in csv format <br>
* File is located and named as {@param objectName}_landmarks.csv
* File is located and named as {@code objectName}_landmarks.csv
*
* @param featurePointList
* @param objectName
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment