forked from powsybl/powsybl-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add include scripts in AbstractScript nodes Signed-off-by: Paul Bui-Quang <[email protected]> * Add generic script type Signed-off-by: Paul Bui-Quang <[email protected]>
- Loading branch information
1 parent
d55ddf1
commit caed62f
Showing
11 changed files
with
329 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
108 changes: 108 additions & 0 deletions
108
afs/afs-core/src/main/java/com/powsybl/afs/OrderedDependencyManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* Copyright (c) 2019, RTE (http://www.rte-france.com) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
package com.powsybl.afs; | ||
|
||
import org.apache.commons.lang3.tuple.ImmutablePair; | ||
|
||
import java.util.Collections; | ||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
/** | ||
* @author Paul Bui-Quang <paul.buiquang at rte-france.com> | ||
*/ | ||
public class OrderedDependencyManager { | ||
|
||
private final ProjectFile projectFile; | ||
|
||
private List<ProjectDependency<ProjectNode>> dependencyCache = null; | ||
|
||
public OrderedDependencyManager(ProjectFile projectFile) { | ||
this.projectFile = Objects.requireNonNull(projectFile); | ||
projectFile.addListener(new DefaultProjectFileListener() { | ||
@Override | ||
public void dependencyChanged(String name) { | ||
dependencyCache = null; | ||
} | ||
}); | ||
} | ||
|
||
public void appendDependencies(String name, List<ProjectNode> projectNodes) { | ||
List<ProjectNode> nodes = getDependencies(name); | ||
nodes.addAll(projectNodes); | ||
setDependencies(name, nodes); | ||
} | ||
|
||
public void insertDependencies(String name, int index, List<ProjectNode> projectNodes) { | ||
List<ProjectNode> nodes = getDependencies(name); | ||
nodes.addAll(index, projectNodes); | ||
setDependencies(name, nodes); | ||
} | ||
|
||
public void removeDependency(String name, int index) { | ||
List<ProjectNode> nodes = getDependencies(name); | ||
nodes.remove(index); | ||
setDependencies(name, nodes); | ||
} | ||
|
||
public void removeDependencies(String name, List<String> nodeIds) { | ||
List<ProjectNode> nodes = getDependencies(name) | ||
.stream() | ||
.filter(dep -> !nodeIds.contains(dep.getId())) | ||
.collect(Collectors.toList()); | ||
setDependencies(name, nodes); | ||
} | ||
|
||
public void setDependencies(String name, List<ProjectNode> projectNodes) { | ||
getDependenciesFor(name).map(el -> el.getRight().getName()).forEach(projectFile::removeDependencies); | ||
for (int i = 0; i < projectNodes.size(); i++) { | ||
projectFile.setDependencies(name + "_" + i, Collections.singletonList(projectNodes.get(i))); | ||
} | ||
} | ||
|
||
public List<ProjectNode> getDependencies(String name) { | ||
return getDependenciesFor(name) | ||
.sorted(Comparator.comparing(ImmutablePair::getLeft)) | ||
.map(dep -> dep.getRight().getProjectNode()) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public <T extends ProjectNode> List<T> getDependencies(String name, Class<T> nodeClass) { | ||
return getDependenciesFor(name) | ||
.filter(dep -> nodeClass.isAssignableFrom(dep.getRight().getProjectNode().getClass())) | ||
.sorted(Comparator.comparing(ImmutablePair::getLeft)) | ||
.map(dep -> nodeClass.cast(dep.getRight().getProjectNode())) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private List<ProjectDependency<ProjectNode>> getDependencyCache() { | ||
if (dependencyCache == null) { | ||
dependencyCache = projectFile.getDependencies(); | ||
} | ||
return dependencyCache; | ||
} | ||
|
||
private Stream<ImmutablePair<String, ProjectDependency<ProjectNode>>> getDependenciesFor(String name) { | ||
Pattern pattern = Pattern.compile(name + "_(\\d+)"); | ||
return getDependencyCache() | ||
.stream() | ||
.map(dep -> { | ||
Matcher depMatch = pattern.matcher(dep.getName()); | ||
if (depMatch.matches()) { | ||
return ImmutablePair.of(depMatch.group(1), dep); | ||
} | ||
return null; | ||
}) | ||
.filter(Objects::nonNull); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 8 additions & 76 deletions
84
afs/afs-ext-base/src/main/java/com/powsybl/afs/ext/base/AbstractModificationScript.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,21 @@ | ||
/** | ||
* Copyright (c) 2018, RTE (http://www.rte-france.com) | ||
/* | ||
* Copyright (c) 2019, RTE (http://www.rte-france.com) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
* | ||
*/ | ||
|
||
package com.powsybl.afs.ext.base; | ||
|
||
import com.google.common.io.CharStreams; | ||
import com.powsybl.afs.ProjectFile; | ||
import com.powsybl.afs.ProjectFileCreationContext; | ||
import com.powsybl.afs.storage.events.AppStorageListener; | ||
import com.powsybl.afs.storage.events.NodeDataUpdated; | ||
import com.powsybl.afs.storage.events.NodeEvent; | ||
|
||
import java.io.*; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Objects; | ||
|
||
/** | ||
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com> | ||
* @author Paul Bui-Quang <paul.buiquang at rte-france.com> | ||
*/ | ||
public abstract class AbstractModificationScript extends ProjectFile implements StorableScript { | ||
|
||
private static final String NODE_DATA_UPDATED = "NODE_DATA_UPDATED"; | ||
|
||
private final String scriptContentName; | ||
|
||
private final List<ScriptListener> listeners = new ArrayList<>(); | ||
|
||
private final AppStorageListener l = eventList -> processEvents(eventList.getEvents(), info.getId(), listeners); | ||
|
||
@Deprecated | ||
public abstract class AbstractModificationScript extends AbstractScript<AbstractModificationScript> { | ||
public AbstractModificationScript(ProjectFileCreationContext context, int codeVersion, String scriptContentName) { | ||
super(context, codeVersion); | ||
this.scriptContentName = Objects.requireNonNull(scriptContentName); | ||
storage.getEventsBus().addListener(l); | ||
} | ||
|
||
private void processEvents(List<NodeEvent> events, String nodeId, List<ScriptListener> listeners) { | ||
for (NodeEvent event : events) { | ||
if (event.getType().equals(NODE_DATA_UPDATED)) { | ||
NodeDataUpdated dataUpdated = (NodeDataUpdated) event; | ||
if (dataUpdated.getId().equals(nodeId) && scriptContentName.equals(dataUpdated.getDataName())) { | ||
for (ScriptListener listener : listeners) { | ||
listener.scriptUpdated(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public String readScript() { | ||
try { | ||
return CharStreams.toString(new InputStreamReader(storage.readBinaryData(info.getId(), scriptContentName).orElseThrow(AssertionError::new), StandardCharsets.UTF_8)); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void writeScript(String content) { | ||
try (Reader reader = new StringReader(content); | ||
Writer writer = new OutputStreamWriter(storage.writeBinaryData(info.getId(), scriptContentName), StandardCharsets.UTF_8)) { | ||
CharStreams.copy(reader, writer); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
storage.updateModificationTime(info.getId()); | ||
storage.flush(); | ||
|
||
// invalidate backward dependencies | ||
invalidate(); | ||
} | ||
|
||
@Override | ||
public void addListener(ScriptListener listener) { | ||
Objects.requireNonNull(listener); | ||
listeners.add(listener); | ||
} | ||
|
||
@Override | ||
public void removeListener(ScriptListener listener) { | ||
Objects.requireNonNull(listener); | ||
listeners.remove(listener); | ||
super(context, codeVersion, scriptContentName); | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
afs/afs-ext-base/src/main/java/com/powsybl/afs/ext/base/AbstractScript.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/** | ||
* Copyright (c) 2018, RTE (http://www.rte-france.com) | ||
* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
*/ | ||
package com.powsybl.afs.ext.base; | ||
|
||
import com.google.common.io.CharStreams; | ||
import com.powsybl.afs.OrderedDependencyManager; | ||
import com.powsybl.afs.ProjectFile; | ||
import com.powsybl.afs.ProjectFileCreationContext; | ||
import com.powsybl.afs.storage.events.AppStorageListener; | ||
import com.powsybl.afs.storage.events.NodeDataUpdated; | ||
import com.powsybl.afs.storage.events.NodeEvent; | ||
import org.apache.commons.lang3.StringUtils; | ||
|
||
import java.io.*; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com> | ||
*/ | ||
public abstract class AbstractScript<T extends AbstractScript> extends ProjectFile implements StorableScript { | ||
|
||
private static final String NODE_DATA_UPDATED = "NODE_DATA_UPDATED"; | ||
|
||
private static final String INCLUDED_SCRIPTS_DEPENDENCY_NAME = "scriptIncludes"; | ||
private static final String DEFAULT_SCRIPTS_DELIMITER = "\n\n"; | ||
private final String scriptContentName; | ||
private final List<ScriptListener> listeners = new ArrayList<>(); | ||
private final AppStorageListener l = eventList -> processEvents(eventList.getEvents(), info.getId(), listeners); | ||
protected final OrderedDependencyManager orderedDependencyManager = new OrderedDependencyManager(this); | ||
|
||
public AbstractScript(ProjectFileCreationContext context, int codeVersion, String scriptContentName) { | ||
super(context, codeVersion); | ||
this.scriptContentName = Objects.requireNonNull(scriptContentName); | ||
storage.getEventsBus().addListener(l); | ||
} | ||
|
||
private void processEvents(List<NodeEvent> events, String nodeId, List<ScriptListener> listeners) { | ||
for (NodeEvent event : events) { | ||
if (NODE_DATA_UPDATED.equals(event.getType())) { | ||
NodeDataUpdated dataUpdated = (NodeDataUpdated) event; | ||
if (dataUpdated.getId().equals(nodeId) && scriptContentName.equals(dataUpdated.getDataName())) { | ||
for (ScriptListener listener : listeners) { | ||
listener.scriptUpdated(); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
public List<AbstractScript> getIncludedScripts() { | ||
return orderedDependencyManager.getDependencies(INCLUDED_SCRIPTS_DEPENDENCY_NAME, AbstractScript.class); | ||
} | ||
|
||
public void addGenericScript(GenericScript genericScript) { | ||
orderedDependencyManager.appendDependencies(INCLUDED_SCRIPTS_DEPENDENCY_NAME, Collections.singletonList(genericScript)); | ||
} | ||
|
||
public void addScript(T includeScript) { | ||
orderedDependencyManager.appendDependencies(INCLUDED_SCRIPTS_DEPENDENCY_NAME, Collections.singletonList(includeScript)); | ||
} | ||
|
||
public void removeScript(String scriptNodeId) { | ||
orderedDependencyManager.removeDependencies(INCLUDED_SCRIPTS_DEPENDENCY_NAME, Collections.singletonList(scriptNodeId)); | ||
} | ||
|
||
@Override | ||
public String readScript(boolean withIncludes) { | ||
String ownContent = readScript(); | ||
if (withIncludes) { | ||
String includesScript = orderedDependencyManager | ||
.getDependencies(INCLUDED_SCRIPTS_DEPENDENCY_NAME, AbstractScript.class) | ||
.stream() | ||
.map(script -> script.readScript(true)) | ||
.collect(Collectors.joining(DEFAULT_SCRIPTS_DELIMITER)); | ||
if (StringUtils.isNotBlank(includesScript)) { | ||
includesScript += DEFAULT_SCRIPTS_DELIMITER; | ||
} | ||
return includesScript + ownContent; | ||
} | ||
return ownContent; | ||
} | ||
|
||
@Override | ||
public String readScript() { | ||
try { | ||
return CharStreams.toString(new InputStreamReader(storage.readBinaryData(info.getId(), scriptContentName).orElseThrow(AssertionError::new), StandardCharsets.UTF_8)); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
} | ||
|
||
@Override | ||
public void writeScript(String content) { | ||
try (Reader reader = new StringReader(content); | ||
Writer writer = new OutputStreamWriter(storage.writeBinaryData(info.getId(), scriptContentName), StandardCharsets.UTF_8)) { | ||
CharStreams.copy(reader, writer); | ||
} catch (IOException e) { | ||
throw new UncheckedIOException(e); | ||
} | ||
storage.updateModificationTime(info.getId()); | ||
storage.flush(); | ||
|
||
// invalidate backward dependencies | ||
invalidate(); | ||
} | ||
|
||
@Override | ||
public void addListener(ScriptListener listener) { | ||
Objects.requireNonNull(listener); | ||
listeners.add(listener); | ||
} | ||
|
||
@Override | ||
public void removeListener(ScriptListener listener) { | ||
Objects.requireNonNull(listener); | ||
listeners.remove(listener); | ||
} | ||
} |
Oops, something went wrong.