Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.streamx.cli.commands;

import com.streamx.cli.commands.local.LocalCommand;
import com.streamx.cli.commands.settings.SettingsCommand;
import com.streamx.cli.framework.AbstractCommandGroup;
import com.streamx.cli.util.VersionProvider;
import picocli.CommandLine;
Expand All @@ -10,7 +11,8 @@
mixinStandardHelpOptions = true,
description = "StreamX CLI. More info at https://streamx.dev",
subcommands = {
LocalCommand.class
LocalCommand.class,
SettingsCommand.class
},
versionProvider = VersionProvider.class
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.streamx.cli.commands.settings;

import com.streamx.cli.commands.settings.get.GetCommand;
import com.streamx.cli.commands.settings.list.ListCommand;
import com.streamx.cli.commands.settings.set.SetCommand;
import com.streamx.cli.framework.AbstractCommandGroup;
import picocli.CommandLine;

@CommandLine.Command(
name = "settings",
mixinStandardHelpOptions = true,
description = "Modify StreamX settings",
abbreviateSynopsis = true,
synopsisHeading = "Synopsis example",
subcommands = {
ListCommand.class,
SetCommand.class,
GetCommand.class
}
)
public class SettingsCommand extends AbstractCommandGroup {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.streamx.cli.commands.settings.get;

import static com.streamx.cli.i18n.MessageProvider.msg;

import com.streamx.cli.config.DotStreamxConfigSource;
import com.streamx.cli.framework.AbstractCommand;
import com.streamx.cli.framework.CliException;
import com.streamx.cli.framework.CommandResult;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Properties;
import picocli.CommandLine;

@CommandLine.Command(
name = "get",
mixinStandardHelpOptions = true,
description = "Get configuration property"
)
public class GetCommand extends AbstractCommand<String> {
@CommandLine.Parameters(index = "0", description = "Property key")
public String key;

@Override
public String getTextOutput(CommandResult<String> result) {
return result.getData();
}

@Override
public CommandResult<String> runCommand() {
URL url = DotStreamxConfigSource.getUrl();

try (InputStream inputStream = url.openStream()) {
Properties properties = new Properties();
properties.load(inputStream);

String value = properties.getProperty(key);
if (value == null) {
throw new CliException(msg.noSettingsPropertyFound(key));
}

return new CommandResult<>(value);
} catch (IOException e) {
throw new CliException(msg.unableToGetSettingsProperty(), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.streamx.cli.commands.settings.list;

import static com.streamx.cli.i18n.MessageProvider.msg;

import com.streamx.cli.config.DotStreamxConfigSource;
import com.streamx.cli.framework.AbstractCommand;
import com.streamx.cli.framework.CliException;
import com.streamx.cli.framework.CommandResult;
import java.io.InputStream;
import java.net.URL;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;
import java.util.stream.Collectors;
import picocli.CommandLine;

@CommandLine.Command(
name = "list",
mixinStandardHelpOptions = true,
description = "Display configuration properties"
)
public class ListCommand extends AbstractCommand<Map<String, String>> {
@Override
public String getTextOutput(CommandResult<Map<String, String>> result) {
if (result.getData().isEmpty()) {
return msg.listSettingsNoPropertiesFound();
}

StringBuilder stringOutput = new StringBuilder();

Map<String, String> sortedProperties = new TreeMap<>(result.getData());

int maxKeyLength = sortedProperties.keySet().stream()
.mapToInt(String::length)
.max()
.orElse(0);

stringOutput.append(msg.listSettingsHeader()).append("\n");

for (Map.Entry<String, String> entry : sortedProperties.entrySet()) {
String paddedKey = String.format("%-" + maxKeyLength + "s", entry.getKey());
stringOutput.append(paddedKey).append(" =");
if (!entry.getValue().isEmpty()) {
stringOutput.append(" ").append(entry.getValue());
}
stringOutput.append("\n");
}

return stringOutput.toString().strip();
}

@Override
public CommandResult<Map<String, String>> runCommand() {
URL url = DotStreamxConfigSource.getUrl();
Map<String, String> properties = getProperties(url);

return new CommandResult<>(properties);
}

private Map<String, String> getProperties(URL url) {
try (InputStream input = url.openStream()) {
Properties properties = new Properties();
properties.load(input);

return properties.stringPropertyNames().stream()
.collect(Collectors.toMap(
key -> key,
properties::getProperty
));
} catch (Exception e) {
throw new CliException(msg.failedToLoadPropertiesFrom(url.getPath()), e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.streamx.cli.commands.settings.set;

import static com.streamx.cli.i18n.MessageProvider.msg;

import com.streamx.cli.config.DotStreamxConfigSource;
import com.streamx.cli.framework.AbstractSilentCommand;
import com.streamx.cli.framework.CliException;
import com.streamx.cli.framework.CommandResult;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Properties;
import picocli.CommandLine;

@CommandLine.Command(
name = "set",
mixinStandardHelpOptions = true,
description = "Set configuration property"
)
public class SetCommand extends AbstractSilentCommand {
@CommandLine.Parameters(index = "0", description = "Property key")
public String key;

@CommandLine.Parameters(index = "1", description = "Property value")
public String value;

@Override
public CommandResult<Void> runCommand() throws RuntimeException {
URL url = DotStreamxConfigSource.getUrl();
Path path = Paths.get(url.getPath());

Properties properties = new Properties();

try (InputStream inputStream = url.openStream()) {
properties.load(inputStream);
} catch (IOException e) {
throw new CliException(msg.unableToSetSettingsProperty(), e);
}

properties.setProperty(key, value);

try (OutputStream outputStream = Files.newOutputStream(path)) {
properties.store(outputStream, null);
} catch (IOException e) {
throw new CliException(msg.unableToSetSettingsProperty(), e);
}

return new CommandResult<>(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import static com.streamx.cli.i18n.MessageProvider.msg;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
Expand All @@ -13,10 +12,14 @@
* @param <ResultT> Must be serializable by Jackson (POJO, JsonSerializable, etc.)
*/
public class CommandResult<ResultT> {
public ResultT result;
private ResultT data;

public CommandResult(ResultT result) {
this.result = result;
public CommandResult(ResultT data) {
this.data = data;
}

public ResultT getData() {
return data;
}

public String toText(
Expand All @@ -30,16 +33,28 @@ public String toText(
}
case OutputFormat.json -> {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.valueToTree(result);
JsonNode jsonNode = mapper.valueToTree(data);
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode);
}
case OutputFormat.yaml -> {
YAMLFactory yamlFactory = YAMLFactory.builder()
.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
.build();
ObjectMapper mapper = new ObjectMapper(yamlFactory);
JsonNode jsonNode = mapper.valueToTree(result);
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonNode).strip();
JsonNode jsonNode = mapper.valueToTree(data);
String formattedJsonNode = mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(jsonNode)
.strip();

if (
(formattedJsonNode.isEmpty() && jsonNode.isTextual())
|| formattedJsonNode.equals("--- \"\"")
) {
return "\"\"";
}

return formattedJsonNode;
}
default -> throw new CliException(msg.unsupportedOutputFormat());
}
Expand Down
39 changes: 24 additions & 15 deletions streamx-cli/src/main/java/com/streamx/cli/i18n/MessageProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,6 @@ String tryForMoreInformationOnAvailableOptions(
)
String somethingWentWrong();

@Message(id = 105, value = "No such settings property found: %s")
String noSettingsPropertyFound(String key);

@Message(id = 106, value = "Unable to get settings property")
String unableToGetSettingsProperty();

@Message(id = 107, value = "Failed to load properties from: %s")
String failedToLoadPropertiesFrom(String path);

@Message(id = 108, value = "Unable to set settings property")
String unableToSetSettingsProperty();

@Message(id = 109, value = "Unable to get settings file path")
String unableToGetSettingsFilePath();

@Message(
id = 110,
value = """
Expand Down Expand Up @@ -158,4 +143,28 @@ String tryForMoreInformationOnAvailableOptions(

@Message(id = 138, value = "Mesh file not found at: %s")
String meshFileNotFound(String path);

@Message(id = 139, value = """
StreamX configuration properties:
=================================
""")
String listSettingsHeader();

@Message(id = 140, value = "No StreamX configuration properties found")
String listSettingsNoPropertiesFound();

@Message(id = 105, value = "No such settings property found: %s")
String noSettingsPropertyFound(String key);

@Message(id = 106, value = "Unable to get settings property")
String unableToGetSettingsProperty();

@Message(id = 107, value = "Failed to load properties from: %s")
String failedToLoadPropertiesFrom(String path);

@Message(id = 108, value = "Unable to set settings property")
String unableToSetSettingsProperty();

@Message(id = 109, value = "Unable to get settings file path")
String unableToGetSettingsFilePath();
}
Loading
Loading