Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions use-core/src/main/java/org/tzi/use/util/CollectingUserOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* USE - UML based specification environment
* Copyright (C) 1999-2026 University of Bremen & University of Applied Sciences Hamburg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package org.tzi.use.util;

import java.util.EnumMap;
import java.util.Map;

/**
* A {@link UserOutput} that collects all output in memory. Useful for tests and
* for capturing output before forwarding it somewhere else.
*
* @author Cansin Yildiz
* @author Claude
*/
public class CollectingUserOutput implements UserOutput {

private final StringBuilder all = new StringBuilder();
private final Map<OutputLevel, StringBuilder> byLevel = new EnumMap<>(OutputLevel.class);

@Override
public void print(OutputLevel level, String message) {
all.append(message);
byLevel.computeIfAbsent(level, l -> new StringBuilder()).append(message);
}

/** All collected output across every level, in the order it was produced. */
public String getOutput() {
return all.toString();
}

/** The collected output for a single {@code level}. */
public String getOutput(OutputLevel level) {
StringBuilder sb = byLevel.get(level);
return sb == null ? "" : sb.toString();
}
}
34 changes: 34 additions & 0 deletions use-core/src/main/java/org/tzi/use/util/NullUserOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* USE - UML based specification environment
* Copyright (C) 1999-2026 University of Bremen & University of Applied Sciences Hamburg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package org.tzi.use.util;

/**
* A {@link UserOutput} that discards all output.
*
* @author Cansin Yildiz
* @author Claude
*/
public final class NullUserOutput implements UserOutput {

@Override
public void print(OutputLevel level, String message) {
// discard
}
}
44 changes: 44 additions & 0 deletions use-core/src/main/java/org/tzi/use/util/OutputLevel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* USE - UML based specification environment
* Copyright (C) 1999-2026 University of Bremen & University of Applied Sciences Hamburg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package org.tzi.use.util;

/**
* The level of a piece of {@link UserOutput} meant for the USE user.
*
* <p>This is intentionally separate from developer-facing logging (see issue
* #60): it describes <em>what kind</em> of user output is produced, so that
* different output targets can render or route it accordingly (e.g. errors and
* warnings to an error stream, warnings highlighted, ...).</p>
*
* @author Cansin Yildiz
* @author Claude
*/
public enum OutputLevel {
/** Regular output that is the result the user asked for. */
NORMAL,
/** Additional, informational output. */
INFO,
/** A warning the user should be aware of. */
WARN,
/** An error reported to the user. */
ERROR,
/** Fine-grained trace output for following what USE is doing. */
TRACE
}
60 changes: 60 additions & 0 deletions use-core/src/main/java/org/tzi/use/util/StreamUserOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* USE - UML based specification environment
* Copyright (C) 1999-2026 University of Bremen & University of Applied Sciences Hamburg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package org.tzi.use.util;

import java.io.PrintStream;
import java.util.Objects;

/**
* A {@link UserOutput} that writes to {@link PrintStream}s. Warnings and errors
* are written to the error stream, everything else to the normal stream.
*
* @author Cansin Yildiz
* @author Claude
*/
public class StreamUserOutput implements UserOutput {

private final PrintStream normalStream;
private final PrintStream errorStream;

/**
* @param normalStream stream for {@code NORMAL}, {@code INFO} and {@code TRACE} output
* @param errorStream stream for {@code WARN} and {@code ERROR} output
*/
public StreamUserOutput(PrintStream normalStream, PrintStream errorStream) {
this.normalStream = Objects.requireNonNull(normalStream);
this.errorStream = Objects.requireNonNull(errorStream);
}

/** Writes all levels to the same stream. */
public StreamUserOutput(PrintStream stream) {
this(stream, stream);
}

@Override
public void print(OutputLevel level, String message) {
streamFor(level).print(message);
}

private PrintStream streamFor(OutputLevel level) {
return (level == OutputLevel.WARN || level == OutputLevel.ERROR)
? errorStream : normalStream;
}
}
96 changes: 96 additions & 0 deletions use-core/src/main/java/org/tzi/use/util/UserOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* USE - UML based specification environment
* Copyright (C) 1999-2026 University of Bremen & University of Applied Sciences Hamburg
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

package org.tzi.use.util;

/**
* Abstraction for output that is meant for the USE <em>user</em>, as opposed to
* developer-facing logging.
*
* <p>This is the foundation for unifying USE's output handling (issue #60).
* Instead of statically writing to {@code System.out}/{@code System.err} or the
* static {@link Log}, code that produces user output should be given a
* {@code UserOutput} instance. This separates user output from developer
* logging, allows multiple output targets (e.g. shell and log window) and
* allows decorated output (e.g. warnings in a different color).</p>
*
* <p>Implementations only have to provide {@link #print(OutputLevel, String)};
* the {@code println} and per-level convenience methods are derived from it.</p>
*
* @author Cansin Yildiz
* @author Claude
*/
public interface UserOutput {

/**
* Outputs {@code message} at the given {@code level}. This is the single
* method implementations must provide.
*/
void print(OutputLevel level, String message);

/** Outputs {@code message} followed by a line separator at {@code level}. */
default void println(OutputLevel level, String message) {
print(level, message + System.lineSeparator());
}

/** Outputs an empty line at {@code level}. */
default void println(OutputLevel level) {
print(level, System.lineSeparator());
}

default void printNormal(String message) { print(OutputLevel.NORMAL, message); }
default void printlnNormal(String message) { println(OutputLevel.NORMAL, message); }
default void printlnNormal() { println(OutputLevel.NORMAL); }

default void printInfo(String message) { print(OutputLevel.INFO, message); }
default void printlnInfo(String message) { println(OutputLevel.INFO, message); }

default void printWarn(String message) { print(OutputLevel.WARN, message); }
default void printlnWarn(String message) { println(OutputLevel.WARN, message); }

default void printError(String message) { print(OutputLevel.ERROR, message); }
default void printlnError(String message) { println(OutputLevel.ERROR, message); }

default void printTrace(String message) { print(OutputLevel.TRACE, message); }
default void printlnTrace(String message) { println(OutputLevel.TRACE, message); }

/**
* A {@code UserOutput} that discards everything. Useful where no user output
* is desired.
*/
static UserOutput getSilentOutput() {
return new NullUserOutput();
}

/**
* The default {@code UserOutput}, writing normal output to {@code System.out}
* and warnings/errors to {@code System.err}.
*/
static UserOutput getDefaultOutput() {
return new StreamUserOutput(System.out, System.err);
}

/**
* A {@code UserOutput} that collects everything in memory. Useful for tests
* and for capturing output.
*/
static CollectingUserOutput createCollectingOutput() {
return new CollectingUserOutput();
}
}
Loading