的
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2020-2021 Frederic Thevenet
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
compileOnly project(':binjr-core')
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes(
|
||||
'Specification-Title': project.name,
|
||||
'Specification-Version': project.version,
|
||||
'Implementation-Title': project.name,
|
||||
'Implementation-Version': project.version,
|
||||
'Build-Number': BINJR_BUILD_NUMBER
|
||||
)
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2020 Frederic Thevenet
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package eu.binjr.sources.text.adapters;
|
||||
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import eu.binjr.common.preferences.ObservablePreference;
|
||||
import eu.binjr.core.data.adapters.DataAdapter;
|
||||
import eu.binjr.core.data.adapters.DataAdapterPreferences;
|
||||
|
||||
/**
|
||||
* Defines the preferences associated with the Text files adapter.
|
||||
*/
|
||||
public class TextAdapterPreferences extends DataAdapterPreferences {
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* The default text panel font size preference.
|
||||
*/
|
||||
public ObservablePreference<Number> defaultTextViewFontSize = integerPreference("defaultTextViewFontSize", 10);
|
||||
|
||||
/**
|
||||
* The filters used when scanning folders in the source filesystem.
|
||||
*/
|
||||
public ObservablePreference<String[]> folderFilters = objectPreference(String[].class,
|
||||
"folderFilters",
|
||||
new String[]{"*"},
|
||||
gson::toJson,
|
||||
s -> gson.fromJson(s, String[].class));
|
||||
|
||||
/**
|
||||
* The filters used to prune file extensions to scan in the source filesystem.
|
||||
*/
|
||||
public ObservablePreference<String[]> fileExtensionFilters = objectPreference(String[].class,
|
||||
"fileExtensionFilters",
|
||||
new String[]{".xml", ".txt", ".env", ".properties", ".csv", ".log", "md", ".json", ".yml"},
|
||||
gson::toJson,
|
||||
s -> gson.fromJson(s, String[].class));
|
||||
|
||||
/**
|
||||
* Initialize a new instance of the {@link TextAdapterPreferences} class associated to
|
||||
* a {@link DataAdapter} instance.
|
||||
*
|
||||
* @param dataAdapterClass the associated {@link DataAdapter}
|
||||
*/
|
||||
public TextAdapterPreferences(Class<? extends DataAdapter<?>> dataAdapterClass) {
|
||||
super(dataAdapterClass, false);
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright 2020-2023 Frederic Thevenet
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package eu.binjr.sources.text.adapters;
|
||||
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import eu.binjr.common.io.FileSystemBrowser;
|
||||
import eu.binjr.common.javafx.controls.TreeViewUtils;
|
||||
import eu.binjr.common.logging.Logger;
|
||||
import eu.binjr.common.logging.Profiler;
|
||||
import eu.binjr.common.text.BinaryPrefixFormatter;
|
||||
import eu.binjr.core.data.adapters.BaseDataAdapter;
|
||||
import eu.binjr.core.data.adapters.SourceBinding;
|
||||
import eu.binjr.core.data.adapters.TextFilesBinding;
|
||||
import eu.binjr.core.data.exceptions.DataAdapterException;
|
||||
import eu.binjr.core.data.timeseries.TextProcessor;
|
||||
import eu.binjr.core.data.timeseries.TimeSeriesProcessor;
|
||||
import eu.binjr.core.data.workspace.TimeSeriesInfo;
|
||||
import eu.binjr.core.dialogs.Dialogs;
|
||||
import javafx.scene.chart.XYChart;
|
||||
import org.eclipse.fx.ui.controls.tree.FilterableTreeItem;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A {@link eu.binjr.core.data.adapters.DataAdapter} implementation to retrieve data from a text file.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
public class TextDataAdapter extends BaseDataAdapter<String> {
|
||||
private static final Logger logger = Logger.create(TextDataAdapter.class);
|
||||
private static final Gson gson = new Gson();
|
||||
private final BinaryPrefixFormatter binaryPrefixFormatter = new BinaryPrefixFormatter("###,###.## ");
|
||||
private Path rootPath;
|
||||
private FileSystemBrowser fileBrowser;
|
||||
private String[] folderFilters;
|
||||
private String[] fileExtensionsFilters;
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link TextDataAdapter} class.
|
||||
*
|
||||
* @throws DataAdapterException if an error occurs while initializing the adapter.
|
||||
*/
|
||||
public TextDataAdapter() throws DataAdapterException {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link TextDataAdapter} class from the provided {@link Path}
|
||||
*
|
||||
* @param rootPath the {@link Path} from which to load content.
|
||||
* @param folderFilters a list of names of folders to inspect for content.
|
||||
* @param fileExtensionsFilters a list of file extensions to inspect for content.
|
||||
* @throws DataAdapterException if an error occurs initializing the adapter.
|
||||
*/
|
||||
public TextDataAdapter(Path rootPath, String[] folderFilters, String[] fileExtensionsFilters) throws DataAdapterException {
|
||||
super();
|
||||
this.rootPath = rootPath;
|
||||
Map<String, String> params = new HashMap<>();
|
||||
initParams(rootPath, folderFilters, fileExtensionsFilters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getParams() {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put("rootPath", rootPath.toString());
|
||||
params.put("folderFilters", gson.toJson(folderFilters));
|
||||
params.put("fileExtensionsFilters", gson.toJson(fileExtensionsFilters));
|
||||
return params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadParams(Map<String, String> params) throws DataAdapterException {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(() -> "TextDataAdapter params:");
|
||||
params.forEach((s, s2) -> logger.debug(() -> "key=" + s + ", value=" + s2));
|
||||
}
|
||||
initParams(Paths.get(validateParameterNullity(params, "rootPath")),
|
||||
gson.fromJson(validateParameterNullity(params, "folderFilters"), String[].class),
|
||||
gson.fromJson(validateParameterNullity(params, "fileExtensionsFilters"), String[].class));
|
||||
}
|
||||
|
||||
private void initParams(Path rootPath, String[] folderFilters, String[] fileExtensionsFilters) throws DataAdapterException {
|
||||
this.rootPath = rootPath;
|
||||
this.folderFilters = folderFilters;
|
||||
this.fileExtensionsFilters = fileExtensionsFilters;
|
||||
try {
|
||||
this.fileBrowser = FileSystemBrowser.of(rootPath);
|
||||
} catch (IOException e) {
|
||||
throw new DataAdapterException("Could not create file system browser instance", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterableTreeItem<SourceBinding> getBindingTree() throws DataAdapterException {
|
||||
FilterableTreeItem<SourceBinding> rootNode = new FilterableTreeItem<>(
|
||||
new TextFilesBinding.Builder()
|
||||
.withLabel(getSourceName())
|
||||
.withAdapter(this)
|
||||
.build());
|
||||
attachTextFilesTree(rootNode);
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
private void attachTextFilesTree(FilterableTreeItem<SourceBinding> rootNode) throws DataAdapterException {
|
||||
try (var p = Profiler.start("Building text binding tree", logger::perf)) {
|
||||
Map<Path, FilterableTreeItem<SourceBinding>> nodeDict = new HashMap<>();
|
||||
nodeDict.put(fileBrowser.toInternalPath("/"), rootNode);
|
||||
for (var fsEntry : fileBrowser.listEntries(folderFilters, fileExtensionsFilters)) {
|
||||
String fileName = fsEntry.getPath().getFileName().toString();
|
||||
var attachTo = rootNode;
|
||||
if (fsEntry.getPath().getParent() != null) {
|
||||
attachTo = nodeDict.get(fsEntry.getPath().getParent());
|
||||
if (attachTo == null) {
|
||||
attachTo = makeBranchNode(nodeDict, fsEntry.getPath().getParent(), rootNode);
|
||||
}
|
||||
}
|
||||
FilterableTreeItem<SourceBinding> filenode = new FilterableTreeItem<>(
|
||||
new TextFilesBinding.Builder()
|
||||
.withLabel(fileName + " (" + binaryPrefixFormatter.format(fsEntry.getSize()) + "B)")
|
||||
.withPath(fsEntry.getPath().toString())
|
||||
.withParent(attachTo.getValue())
|
||||
.withAdapter(this)
|
||||
.build());
|
||||
attachTo.getInternalChildren().add(filenode);
|
||||
}
|
||||
TreeViewUtils.sortFromBranch(rootNode);
|
||||
} catch (Exception e) {
|
||||
Dialogs.notifyException("Error while enumerating files: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private FilterableTreeItem<SourceBinding> makeBranchNode(Map<Path, FilterableTreeItem<SourceBinding>> nodeDict,
|
||||
Path path,
|
||||
FilterableTreeItem<SourceBinding> root) {
|
||||
var parent = root;
|
||||
var rootPath = path.isAbsolute() ? path.getRoot() : path.getName(0);
|
||||
for (int i = 0; i < path.getNameCount(); i++) {
|
||||
Path current = rootPath.resolve(path.getName(i));
|
||||
FilterableTreeItem<SourceBinding> filenode = nodeDict.get(current);
|
||||
if (filenode == null) {
|
||||
filenode = new FilterableTreeItem<>(
|
||||
new TextFilesBinding.Builder()
|
||||
.withLabel(current.getFileName().toString())
|
||||
.withPath(path.toString())
|
||||
.withParent(parent.getValue())
|
||||
.withAdapter(this)
|
||||
.build());
|
||||
nodeDict.put(current, filenode);
|
||||
parent.getInternalChildren().add(filenode);
|
||||
}
|
||||
parent = filenode;
|
||||
rootPath = current;
|
||||
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<TimeSeriesInfo<String>, TimeSeriesProcessor<String>> fetchData(String path,
|
||||
Instant start,
|
||||
Instant end,
|
||||
List<TimeSeriesInfo<String>> seriesInfos,
|
||||
boolean bypassCache) throws DataAdapterException {
|
||||
Map<TimeSeriesInfo<String>, TimeSeriesProcessor<String>> data = new HashMap<>();
|
||||
for (var info : seriesInfos) {
|
||||
try {
|
||||
var proc = new TextProcessor();
|
||||
proc.setData(List.of(new XYChart.Data<>(ZonedDateTime.now(), readTextFile(info.getBinding().getPath()))));
|
||||
data.put(info, proc);
|
||||
} catch (IOException e) {
|
||||
throw new DataAdapterException("Error fetching text from " + info.getBinding().getPath(), e);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoding() {
|
||||
return "utf-8";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZoneId getTimeZoneId() {
|
||||
return ZoneId.systemDefault();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceName() {
|
||||
return "[Text] " + (rootPath != null ? rootPath.getFileName() : "???");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() throws DataAdapterException {
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (fileBrowser != null) {
|
||||
try {
|
||||
fileBrowser.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("An error occurred while closing file system browser instance: " + e.getMessage());
|
||||
logger.debug(e);
|
||||
}
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the content of the text file located at the provided path
|
||||
*
|
||||
* @param path the path of the text file to read
|
||||
* @return The content of the text file, as a String
|
||||
* @throws IOException if an error occurs while reading the file.
|
||||
*/
|
||||
public String readTextFile(String path) throws IOException {
|
||||
try (Profiler ignored = Profiler.start("Extracting text from file " + path, logger::perf)) {
|
||||
try (var reader = new BufferedReader(new InputStreamReader(fileBrowser.getData(path), StandardCharsets.UTF_8))) {
|
||||
return reader.lines().collect(Collectors.joining("\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright 2020-2023 Frederic Thevenet
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package eu.binjr.sources.text.adapters;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import eu.binjr.common.javafx.controls.NodeUtils;
|
||||
import eu.binjr.common.logging.Logger;
|
||||
import eu.binjr.core.data.adapters.DataAdapter;
|
||||
import eu.binjr.core.data.adapters.DataAdapterFactory;
|
||||
import eu.binjr.core.data.exceptions.CannotInitializeDataAdapterException;
|
||||
import eu.binjr.core.data.exceptions.DataAdapterException;
|
||||
import eu.binjr.core.data.exceptions.NoAdapterFoundException;
|
||||
import eu.binjr.core.dialogs.DataAdapterDialog;
|
||||
import eu.binjr.core.dialogs.Dialogs;
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Side;
|
||||
import javafx.geometry.VPos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.ContextMenu;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.stage.DirectoryChooser;
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link DataAdapterDialog} class that presents a dialog box to retrieve the parameters specific {@link TextDataAdapterDialog}
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
public class TextDataAdapterDialog extends DataAdapterDialog<Path> {
|
||||
private static final Logger logger = Logger.create(TextDataAdapterDialog.class);
|
||||
private final TextField extensionFiltersTextField;
|
||||
private final TextAdapterPreferences prefs;
|
||||
private static final Gson gson = new Gson();
|
||||
|
||||
/**
|
||||
* Initializes a new instance of the {@link TextDataAdapterDialog} class.
|
||||
*
|
||||
* @param owner the owner window for the dialog
|
||||
* @throws NoAdapterFoundException if no adapter could be found to get preferences for.
|
||||
*/
|
||||
public TextDataAdapterDialog(Node owner) throws NoAdapterFoundException {
|
||||
super(owner, Mode.PATH, "mostRecentTextArchives", false);
|
||||
this.prefs = (TextAdapterPreferences) DataAdapterFactory.getInstance().getAdapterPreferences(TextDataAdapter.class.getName());
|
||||
setDialogHeaderText("Add a TExt File, Zip Archive or Folder");
|
||||
extensionFiltersTextField = new TextField(gson.toJson(prefs.fileExtensionFilters.get()));
|
||||
var label = new Label("Extensions:");
|
||||
GridPane.setConstraints(label, 0, 1, 1, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS, new Insets(4, 0, 4, 0));
|
||||
GridPane.setConstraints(extensionFiltersTextField, 1, 1, 1, 1, HPos.LEFT, VPos.CENTER, Priority.ALWAYS, Priority.ALWAYS, new Insets(4, 0, 4, 0));
|
||||
|
||||
getParamsGridPane().getChildren().addAll(label, extensionFiltersTextField);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected File displayFileChooser(Node owner) {
|
||||
try {
|
||||
ContextMenu sourceMenu = new ContextMenu();
|
||||
MenuItem fileMenuItem = new MenuItem("Text file");
|
||||
fileMenuItem.setOnAction(eventHandler -> {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Open Text File");
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Text files", "*.txt", "*.text"));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("All files", "*.*", "*"));
|
||||
Dialogs.getInitialDir(getMostRecentList()).ifPresent(fileChooser::setInitialDirectory);
|
||||
File selectedFile = fileChooser.showOpenDialog(NodeUtils.getStage(owner));
|
||||
if (selectedFile != null) {
|
||||
setSourceUri(selectedFile.getPath());
|
||||
}
|
||||
});
|
||||
sourceMenu.getItems().add(fileMenuItem);
|
||||
MenuItem menuItem = new MenuItem("Zip file");
|
||||
menuItem.setOnAction(eventHandler -> {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Open Zip Archive");
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Zip archive", "*.zip"));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("All files", "*.*", "*"));
|
||||
Dialogs.getInitialDir(getMostRecentList()).ifPresent(fileChooser::setInitialDirectory);
|
||||
File selectedFile = fileChooser.showOpenDialog(NodeUtils.getStage(owner));
|
||||
if (selectedFile != null) {
|
||||
setSourceUri(selectedFile.getPath());
|
||||
}
|
||||
});
|
||||
sourceMenu.getItems().add(menuItem);
|
||||
MenuItem folderMenuItem = new MenuItem("Folder");
|
||||
folderMenuItem.setOnAction(eventHandler -> {
|
||||
DirectoryChooser dirChooser = new DirectoryChooser();
|
||||
dirChooser.setTitle("Open Folder");
|
||||
Dialogs.getInitialDir(getMostRecentList()).ifPresent(dirChooser::setInitialDirectory);
|
||||
File selectedFile = dirChooser.showDialog(NodeUtils.getStage(owner));
|
||||
if (selectedFile != null) {
|
||||
setSourceUri(selectedFile.getPath());
|
||||
}
|
||||
});
|
||||
sourceMenu.getItems().add(folderMenuItem);
|
||||
sourceMenu.show(owner, Side.RIGHT, 0, 0);
|
||||
} catch (Exception e) {
|
||||
Dialogs.notifyException("Error while displaying file chooser: " + e.getMessage(), e, owner);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<DataAdapter> getDataAdapters() throws DataAdapterException {
|
||||
Path path = Paths.get(getSourceUri());
|
||||
if (!Files.exists(path)) {
|
||||
throw new CannotInitializeDataAdapterException("Cannot find " + getSourceUri());
|
||||
}
|
||||
if (!path.isAbsolute()) {
|
||||
throw new CannotInitializeDataAdapterException("The provided path is not valid.");
|
||||
}
|
||||
getMostRecentList().push(path);
|
||||
prefs.fileExtensionFilters.set(gson.fromJson(extensionFiltersTextField.getText(), String[].class));
|
||||
return List.of(new TextDataAdapter(path, prefs.folderFilters.get(), prefs.fileExtensionFilters.get()));
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2020-2023 Frederic Thevenet
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package eu.binjr.sources.text.adapters;
|
||||
|
||||
|
||||
import eu.binjr.core.data.adapters.AdapterMetadata;
|
||||
import eu.binjr.core.data.adapters.BaseDataAdapterInfo;
|
||||
import eu.binjr.core.data.adapters.SourceLocality;
|
||||
import eu.binjr.core.data.adapters.VisualizationType;
|
||||
import eu.binjr.core.data.exceptions.CannotInitializeDataAdapterException;
|
||||
import eu.binjr.core.preferences.AppEnvironment;
|
||||
|
||||
|
||||
/**
|
||||
* Defines the metadata associated with TextDataAdapterInfo.
|
||||
*
|
||||
* @author Frederic Thevenet
|
||||
*/
|
||||
@AdapterMetadata(
|
||||
name = "Text",
|
||||
description = "Text Files Data Adapter",
|
||||
copyright = AppEnvironment.COPYRIGHT_NOTICE,
|
||||
license = AppEnvironment.LICENSE,
|
||||
siteUrl = AppEnvironment.HTTP_WWW_BINJR_EU,
|
||||
adapterClass = TextDataAdapter.class,
|
||||
dialogClass = TextDataAdapterDialog.class,
|
||||
preferencesClass = TextAdapterPreferences.class,
|
||||
sourceLocality = SourceLocality.LOCAL,
|
||||
apiLevel = AppEnvironment.PLUGIN_API_LEVEL,
|
||||
visualizationType = VisualizationType.TEXT
|
||||
)
|
||||
public class TextDataAdapterInfo extends BaseDataAdapterInfo {
|
||||
|
||||
/**
|
||||
* Initialises a new instance of the {@link TextDataAdapterInfo} class.
|
||||
*
|
||||
* @throws CannotInitializeDataAdapterException if the adapter's initialization failed
|
||||
*/
|
||||
public TextDataAdapterInfo() throws CannotInitializeDataAdapterException {
|
||||
super(TextDataAdapterInfo.class);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright 2020 Frederic Thevenet
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
# Text Data adapter service implementation
|
||||
# eu.binjr.sources.text.adapters.TextDataAdapterInfo
|
||||
Reference in New Issue
Block a user