...
  View open merge request
Commits (13)
......@@ -209,6 +209,12 @@
<version>${dkpro.core.version}</version>
</dependency>
<dependency>
<groupId>de.tudarmstadt.ukp.dkpro.core</groupId>
<artifactId>de.tudarmstadt.ukp.dkpro.core.api.syntax-asl</artifactId>
<version>${dkpro.core.version}</version>
</dependency>
<dependency>
<groupId>de.tudarmstadt.ukp.dkpro.core</groupId>
<artifactId>de.tudarmstadt.ukp.dkpro.core.opennlp-asl</artifactId>
......
......@@ -174,6 +174,11 @@
<artifactId>de.tudarmstadt.ukp.dkpro.core.io.xmi-asl</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.tudarmstadt.ukp.dkpro.core</groupId>
<artifactId>de.tudarmstadt.ukp.dkpro.core.api.syntax-asl</artifactId>
</dependency>
</dependencies>
<build>
......
......@@ -73,7 +73,7 @@ public abstract class AnnotationBehavior implements ActionConsumer {
/**
* <p>
* This method can modify the {@link Selection}, changing way the user scrolls through the stream of tokens.
* This method can modify the {@link Selection}, changing way the user scrolls through the streams of tokens.
* For example, if the user moves the selection to right, the {@link AnnotationBehavior} could expand the selection
* across multiple tokens.
* </p>
......@@ -110,7 +110,7 @@ public abstract class AnnotationBehavior implements ActionConsumer {
public abstract Region getTokenTagsRegion();
public abstract Region createTokenRelationsRegion();
public abstract Region getTokenRelationsRegion();
public void activate(PaginationAdapter<TokenLabel, Token> tokenLabelAdapter) {
ChangeListener<JCas> jCasChangeListener = getJCasChangeListener();
......
......@@ -26,7 +26,7 @@ import de.schrieveslaach.nlpf.qpt.input.Action;
import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.service.JCasService;
import de.schrieveslaach.nlpf.qpt.service.ProjectService;
import de.schrieveslaach.nlpf.qpt.view.control.NamedEntityStream;
import de.schrieveslaach.nlpf.qpt.view.control.streams.NamedEntityStream;
import de.schrieveslaach.nlpf.qpt.view.control.TokenLabel;
import de.schrieveslaach.nlpf.qpt.view.control.adapter.PaginationAdapter;
import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity;
......@@ -137,6 +137,7 @@ public class NamedEntityTaggingBehavior extends AnnotationBehavior {
@Override
public Selection suggestNewSelection(Selection oldSelection, Selection newSelection) {
newSelection = super.suggestNewSelection(oldSelection, newSelection);
if (newSelection == null || oldSelection == null) {
return null;
}
......@@ -229,7 +230,7 @@ public class NamedEntityTaggingBehavior extends AnnotationBehavior {
}
@Override
public Region createTokenRelationsRegion() {
public Region getTokenRelationsRegion() {
return null;
}
}
......@@ -25,7 +25,7 @@ package de.schrieveslaach.nlpf.qpt.annotation;
import de.schrieveslaach.nlpf.qpt.input.Action;
import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.service.JCasService;
import de.schrieveslaach.nlpf.qpt.view.control.PosTagStream;
import de.schrieveslaach.nlpf.qpt.view.control.streams.PosTagStream;
import de.schrieveslaach.nlpf.qpt.view.control.TokenLabel;
import de.schrieveslaach.nlpf.qpt.view.control.adapter.PaginationAdapter;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.POS;
......@@ -194,7 +194,7 @@ public class PosTaggingBehavior extends AnnotationBehavior {
}
@Override
public Region createTokenRelationsRegion() {
public Region getTokenRelationsRegion() {
return null;
}
}
......@@ -101,7 +101,7 @@ public class SegmentationBehavior extends AnnotationBehavior {
}
@Override
public Region createTokenRelationsRegion() {
public Region getTokenRelationsRegion() {
return null;
}
......
......@@ -46,6 +46,7 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static de.schrieveslaach.nlpf.qpt.view.control.TokenLabel.TOKEN_LABEL_HEIGHT;
import static de.schrieveslaach.nlpf.qpt.view.control.TokenLabel.VERTICAL_BAR_HEIGHT;
import static org.apache.uima.fit.util.JCasUtil.select;
......@@ -105,6 +106,7 @@ public class AnnotationController implements ActionConsumer {
selectedAnnotationBehaviorProperty.addListener((observable, oldValue, newAnnotationBehavior) -> {
if (selectedAnnotationBehavior != null) {
annotation.getChildren().remove(selectedAnnotationBehavior.getTokenTagsRegion());
annotation.getChildren().remove(selectedAnnotationBehavior.getTokenRelationsRegion());
selectedAnnotationBehavior.unbindBidirectional(selectionProperty);
selectedAnnotationBehavior.deactivate();
......@@ -119,7 +121,9 @@ public class AnnotationController implements ActionConsumer {
selectedAnnotationBehavior.activate(tokenStream.getTokenLabelAdapter());
Region tokenTagsRegion = selectedAnnotationBehavior.getTokenTagsRegion();
double tokenTagsRegionHeight = 0.0;
if (tokenTagsRegion != null) {
tokenTagsRegionHeight = 60.0 + TOKEN_LABEL_HEIGHT;
AnchorPane.setBottomAnchor(tokenTagsRegion, 60.0 + 0.25 * VERTICAL_BAR_HEIGHT);
AnchorPane.setLeftAnchor(tokenTagsRegion, 0.0);
AnchorPane.setRightAnchor(tokenTagsRegion, 0.0);
......@@ -127,6 +131,16 @@ public class AnnotationController implements ActionConsumer {
annotation.getChildren().add(tokenTagsRegion);
tokenTagsRegion.toBack();
}
//TODO: Check if tokenTagsRegion exist
Region tokenRelationsRegion = selectedAnnotationBehavior.getTokenRelationsRegion();
if (tokenRelationsRegion != null) {
AnchorPane.setBottomAnchor(tokenRelationsRegion, 60 + tokenTagsRegionHeight + 0.25 * VERTICAL_BAR_HEIGHT);
AnchorPane.setLeftAnchor(tokenRelationsRegion, 0.0);
AnchorPane.setRightAnchor(tokenRelationsRegion, 0.0);
annotation.getChildren().add(tokenRelationsRegion);
tokenRelationsRegion.toBack();
}
});
}
......
......@@ -294,6 +294,9 @@ public class MenuController extends OverlayController implements ActionConsumer
case "NamedEntityTagging":
selectedAnnotationBehavior.set("NamedEntityTagging");
break;
case "Chunking":
selectedAnnotationBehavior.set("Chunking");
break;
default:
Document document = selection.getSelectedDocument();
......
......@@ -27,6 +27,7 @@ import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import de.tudarmstadt.ukp.dkpro.core.api.syntax.type.chunk.Chunk;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
......@@ -47,6 +48,7 @@ import java.util.Map;
import java.util.Optional;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.apache.uima.fit.pipeline.SimplePipeline.runPipeline;
@Service
......@@ -63,6 +65,9 @@ public class JCasService {
private final ObservableList<NamedEntity> namedEntitiesProperty = FXCollections.observableArrayList();
private final ObservableList<NamedEntity> unmodifiableNamedEntitiesProperty = FXCollections.unmodifiableObservableList(namedEntitiesProperty);
private final ObservableList<Chunk> chunksProperty = FXCollections.observableArrayList();
private final ObservableList<Chunk> unmodifiableChunksProperty = FXCollections.unmodifiableObservableList(chunksProperty);
public JCasService() {
jCas.addListener((observableValue, oldJCas, newJCas) -> {
sentencesProperty.clear();
......@@ -73,6 +78,9 @@ public class JCasService {
namedEntitiesProperty.clear();
namedEntitiesProperty.addAll(JCasUtil.select(newJCas, NamedEntity.class));
chunksProperty.clear();
chunksProperty.addAll(JCasUtil.select(newJCas, Chunk.class));
});
}
......@@ -91,6 +99,11 @@ public class JCasService {
return unmodifiableNamedEntitiesProperty;
}
@Bean
public ObservableList<Chunk> chunksProperty() {
return unmodifiableChunksProperty;
}
@Bean
public ReadOnlyObjectProperty<JCas> jCasProperty() {
return jCas;
......@@ -281,7 +294,7 @@ public class JCasService {
return namedEntityTokens;
}
return asList();
return emptyList();
}
public void createNamedEntity(Selection selection, String namedEntityType) {
......@@ -299,4 +312,41 @@ public class JCasService {
namedEntity.addToIndexes();
namedEntitiesProperty.add(namedEntity);
}
/**
* Creates a {@link Chunk} and adds it to the indexes.
*
* @param selection used to determine the start and end indices of the {@link Chunk}.
* @param chunkType value of the {@link Chunk}.
*/
public void createChunk(Selection selection, String chunkType) {
List<Chunk> chunks = selectCovering(Chunk.class, selection.getBegin(), selection.getEnd());
if (!chunks.isEmpty()) {
chunks.forEach(chunk -> {
chunk.removeFromIndexes(jCas.get());
chunksProperty.remove(chunk);
});
}
Chunk chunk = new Chunk(jCas.get(), selection.getBegin(), selection.getEnd());
chunk.setChunkValue(chunkType);
chunk.addToIndexes();
chunksProperty.add(chunk);
}
public List<Token> removeChunk(Selection selection) {
List<Chunk> chunks = selectCovering(Chunk.class, selection.getBegin(), selection.getEnd());
for (Chunk chunk : chunks) {
List<Token> chunkTokens = selectCovered(Token.class, chunk);
chunk.removeFromIndexes(jCas.get());
chunksProperty.remove(chunk);
return chunkTokens;
}
return emptyList();
}
}
......@@ -94,6 +94,8 @@ public class ProjectService {
private final ObservableList<String> namedEntitiesProperty = FXCollections.observableArrayList();
private final ObservableList<String> unmodifiableNamedEntitiesProperty = FXCollections.unmodifiableObservableList(namedEntitiesProperty);
private final StringProperty chunkTagSetProperty = new SimpleStringProperty();
private final SimpleObjectProperty<Document> currentDocument = new SimpleObjectProperty<>();
private final ObservableList<Document> documents = observableArrayList();
......@@ -182,6 +184,8 @@ public class ProjectService {
namedEntitiesProperty.clear();
namedEntitiesProperty.addAll(newLoadProjectResult.getNamedEntites());
chunkTagSetProperty.set(newLoadProjectResult.getChunkTagSetName());
documents.addAll(newLoadProjectResult.getDocuments());
});
......@@ -204,6 +208,11 @@ public class ProjectService {
return unmodifiableNamedEntitiesProperty;
}
@Bean
public ReadOnlyStringProperty chunkTagSetProperty() {
return chunkTagSetProperty;
}
@Bean
public ReadOnlyStringProperty defaultLanguageProperty() {
return defaultLanguageProperty;
......@@ -402,6 +411,9 @@ public class ProjectService {
@Getter
private ImmutableList<String> namedEntites;
@Getter
private String chunkTagSetName;
public LoadProjectResult(List<Document> documents, ClassLoader classLoader, Properties properties) {
this.documents = documents;
this.classLoader = classLoader;
......@@ -412,6 +424,8 @@ public class ProjectService {
List<String> namedEntites = Lists.newArrayList(namedEntityNames.split("\\s*,\\s*"));
Collections.sort(namedEntites);
this.namedEntites = ImmutableList.copyOf(namedEntites);
this.chunkTagSetName = properties.getProperty("chunk.tag.set", "default");
}
}
......
package de.schrieveslaach.nlpf.qpt.view.control;
/*-
* ========================LICENSE_START=================================
* quick-pad-tagger
* %%
* Copyright (C) 2017 Schrieveslaach
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* =========================LICENSE_END==================================
*/
import javafx.beans.value.ChangeListener;
import javafx.geometry.Point2D;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.shape.CubicCurve;
import java.util.List;
public class LabelSpinnerCurve<T> extends LabelSpinner<T> implements ChangeListener<T>, MinWidthLabel {
public LabelSpinnerCurve() {
super();
}
public void drawCurves(List<Region> regions) {
int n = regions.size();
int middle = Math.floorDiv(n, 2) - 1;
if (n % 2 == 0 && regions.size() > 1) {
// get middle values || only if regions.size > 1
Region leftFromMiddle = regions.get(middle - 1);
Region rightFromMiddle = regions.get(middle + 1);
for (int i = 0; i <= middle; i++) {
Region leftRegion = regions.get(i);
Region rightRegion = regions.get(n - 1 - i);
Point2D p1 = leftRegion.getLocalToSceneTransform().transform(leftRegion.getLayoutX(), leftRegion.getLayoutY());
Point2D p2 = rightRegion.getLocalToSceneTransform().transform(rightRegion.getLayoutX(), rightRegion.getLayoutY());
Point2D pEnd = leftFromMiddle.getLocalToSceneTransform().transform(leftFromMiddle.getLayoutX(), leftFromMiddle.getLayoutY());
CubicCurve leftCC = new CubicCurve(p1.getX(), p1.getY(), p1.getX(), pEnd.getY(), pEnd.getX(), p1.getY(), pEnd.getX(), pEnd.getY());
leftCC.setFill(Color.TRANSPARENT);
leftCC.setStroke(Color.BLACK);
CubicCurve rightCC = new CubicCurve(p2.getX(), p2.getY(), p2.getX(), pEnd.getY(), pEnd.getX(), p2.getY(), pEnd.getX(), pEnd.getY());
rightCC.setFill(Color.TRANSPARENT);
rightCC.setStroke(Color.BLACK);
getChildren().addAll(leftCC, rightCC);
}
}
}
}
......@@ -31,6 +31,7 @@ import javafx.beans.binding.DoubleBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyDoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.control.Label;
......@@ -176,6 +177,10 @@ public class TokenLabel extends Region implements MinWidthLabel {
return label.minWidthProperty();
}
public ReadOnlyDoubleProperty labelWidthProperty() {
return label.widthProperty();
}
public Transition createColoringTransition(Coloring from, Coloring to) {
ParallelTransition pt = new ParallelTransition();
pt.getChildren().addAll(
......
......@@ -43,6 +43,7 @@ import java.util.Optional;
import static org.apache.uima.fit.util.JCasUtil.select;
import static org.apache.uima.fit.util.JCasUtil.selectCovered;
//TODO: Refactor to derive from TaggingStream
public class TokenStream extends Region {
private Selection selection = new Selection();
......@@ -52,40 +53,7 @@ public class TokenStream extends Region {
@Getter
private PaginationAdapter<TokenLabel, Token> tokenLabelAdapter = new PaginationAdapter<>(
() -> new TokenLabel(TokenLabel.VERTICAL_BAR_HEIGHT),
(TokenLabel tokenLabel, Token token) -> {
boolean showCircle = false;
boolean showVerticalBar = false;
if (token != null) {
if (jCas != null) {
Map<Token, Collection<Sentence>> tokenSentenceMap = JCasUtil.indexCovering(jCas, Token.class, Sentence.class);
Optional<Sentence> sentence = tokenSentenceMap.get(token)
.stream()
.findFirst();
showVerticalBar = sentence.isPresent() && sentence.get().getEnd() == token.getEnd();
if (token.getBegin() > 0) {
Token preceding = JCasUtil.selectSingleRelative(jCas, Token.class, token, -1);
showCircle = preceding != null && preceding.getEnd() == token.getBegin();
}
}
tokenLabel.setText(token.getText());
if (selection != null && selection.getSelectedSentenceTokens().contains(token)) {
tokenLabel.setColoring(Coloring.FOCUS);
}
if (selection != null && selection.getSelectedTokens().contains(token)) {
tokenLabel.setColoring(Coloring.MORE_FOCUS);
}
tokenLabel.setId("token-" + token.hashCode());
} else {
tokenLabel.setText(null);
tokenLabel.setColoring(Coloring.LESS_FOCUS);
tokenLabel.setId(null);
}
tokenLabel.showVerticalBar(showVerticalBar);
tokenLabel.showCircle(showCircle);
},
this::bind,
TokenLabel::fullWidthProperty
);
......@@ -103,6 +71,41 @@ public class TokenStream extends Region {
});
}
private void bind(TokenLabel tokenLabel, Token token) {
boolean showCircle = false;
boolean showVerticalBar = false;
if (token != null) {
if (jCas != null) {
Map<Token, Collection<Sentence>> tokenSentenceMap = JCasUtil.indexCovering(jCas, Token.class, Sentence.class);
Optional<Sentence> sentence = tokenSentenceMap.get(token)
.stream()
.findFirst();
showVerticalBar = sentence.isPresent() && sentence.get().getEnd() == token.getEnd();
if (token.getBegin() > 0) {
Token preceding = JCasUtil.selectSingleRelative(jCas, Token.class, token, -1);
showCircle = preceding != null && preceding.getEnd() == token.getBegin();
}
}
tokenLabel.setText(token.getText());
if (selection != null && selection.getSelectedSentenceTokens().contains(token)) {
tokenLabel.setColoring(Coloring.FOCUS);
}
if (selection != null && selection.getSelectedTokens().contains(token)) {
tokenLabel.setColoring(Coloring.MORE_FOCUS);
}
tokenLabel.setId("token-" + token.hashCode());
} else {
tokenLabel.setText(null);
tokenLabel.setColoring(Coloring.LESS_FOCUS);
tokenLabel.setId(null);
}
tokenLabel.showVerticalBar(showVerticalBar);
tokenLabel.showCircle(showCircle);
}
public void bindToSentences(ObservableList<Sentence> sentences) {
sentences.addListener((ListChangeListener<Sentence>) c -> {
if (jCas == null) {
......
......@@ -24,6 +24,7 @@ package de.schrieveslaach.nlpf.qpt.view.control.adapter;
import de.schrieveslaach.nlpf.qpt.view.control.Constants;
import javafx.animation.Animation;
import javafx.animation.FadeTransition;
import javafx.animation.ParallelTransition;
import javafx.animation.SequentialTransition;
import javafx.animation.TranslateTransition;
......@@ -49,6 +50,7 @@ import java.util.stream.Collectors;
import static de.schrieveslaach.nlpf.qpt.view.control.Constants.TRANSITION_DURATION;
import static javafx.beans.binding.Bindings.createDoubleBinding;
import static javafx.beans.binding.Bindings.format;
import static javafx.collections.FXCollections.observableArrayList;
public class PaginationAdapter<R extends Region, V> implements ChangeListener<Number>, ListChangeListener<V> {
......@@ -88,7 +90,7 @@ public class PaginationAdapter<R extends Region, V> implements ChangeListener<Nu
private List<PaginationAdapter<? extends Region, V>> childPaginationAdapters = new ArrayList<>();
public void addChildPaginationAdapter(PaginationAdapter<? extends Region, V> paginationAdapter) {
childPaginationAdapters.clear();
// TODO: If statement that checks if a paginationadapter already exists in childPaginationAdapters.
childPaginationAdapters.add(paginationAdapter);
}
......
package de.schrieveslaach.nlpf.qpt.view.control;
package de.schrieveslaach.nlpf.qpt.view.control.streams;
/*-
* ========================LICENSE_START=================================
......@@ -24,6 +24,8 @@ package de.schrieveslaach.nlpf.qpt.view.control;
import com.google.common.collect.Lists;
import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.view.control.LabelSpinner;
import de.schrieveslaach.nlpf.qpt.view.control.MinWidthLabel;
import de.schrieveslaach.nlpf.qpt.view.control.adapter.PaginationAdapter;
import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
......@@ -36,13 +38,10 @@ import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.layout.Region;
import lombok.Getter;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import java.util.Collections;
import java.util.List;
......@@ -55,102 +54,35 @@ import static org.apache.uima.fit.util.JCasUtil.select;
import static org.apache.uima.fit.util.JCasUtil.selectCovered;
import static org.apache.uima.fit.util.JCasUtil.selectCovering;
public class NamedEntityStream extends Region {
@Getter
private Selection selection;
private JCas jCas;
private final ObservableList<Token> tokens = observableArrayList();
public class NamedEntityStream extends TaggingStream {
private final ObservableList<String> namedEntityTags = observableArrayList();
private final SimpleStringProperty namedEntityTag = new SimpleStringProperty();
private final PaginationAdapter<LabelSpinner<String>, Token> namedEntityPaginationAdapter = new PaginationAdapter<>(
() -> {
LabelSpinner spinner = new LabelSpinner();
spinner.setLabelMinWidth(TOKEN_LABEL_WIDTH);
spinner.setValueFactory(new SpinnerValueFactory.ListSpinnerValueFactory<>(namedEntityTags));
spinner.collapseText().setValue("");
spinner.setOpacity(0.0);
spinner.valueProperty().addListener((observable, oldValue, newValue) -> namedEntityTag.set(newValue != null ? newValue.toString() : null));
return spinner;
},
this::bind,
Region::widthProperty
);
public NamedEntityStream() {
widthProperty().addListener(namedEntityPaginationAdapter);
namedEntityPaginationAdapter.regionsProperty().addListener((ListChangeListener<? super LabelSpinner<String>>) c -> {
while (c.next()) {
getChildren().removeAll(c.getRemoved());
getChildren().addAll(c.getAddedSubList());
}
});
tokens.addListener(namedEntityPaginationAdapter);
}
public ReadOnlyStringProperty namedEntityTagProperty() {
return namedEntityTag;
}
public void setJCas(JCas jCas) {
this.jCas = jCas;
rebindTokens(Lists.newArrayList(select(jCas, Token.class)));
}
public void setTokens(List<Token> tokens) {
this.tokens.clear();
this.tokens.addAll(tokens);
}
public void setSelection(Selection selection) {
updateSelection(selection);
this.selection = selection;
@Override
PaginationAdapter<LabelSpinner<String>, Token> initPaginationAdapter() {
return new PaginationAdapter<LabelSpinner<String>, Token>(
() -> {
LabelSpinner spinner = new LabelSpinner();
spinner.setLabelMinWidth(TOKEN_LABEL_WIDTH);
spinner.setValueFactory(new SpinnerValueFactory.ListSpinnerValueFactory<>(namedEntityTags));
spinner.collapseText().setValue("");
spinner.setOpacity(0.0);
spinner.valueProperty().addListener((observable, oldValue, newValue) -> namedEntityTag.set(newValue != null ? newValue.toString() : null));
return spinner;
},
this::bind,
Region::widthProperty
);
}
public void setParentPaginationAdapter(PaginationAdapter<?, Token> parentPaginationAdapter) {
namedEntityPaginationAdapter.setParentPaginationAdapter(parentPaginationAdapter);
parentPaginationAdapter.addChildPaginationAdapter(namedEntityPaginationAdapter);
}
public void setNamedEntitiesSet(List<String> namedEntitiesSet) {
namedEntityTags.clear();
namedEntityTags.addAll(namedEntitiesSet);
if (jCas != null) {
namedEntityPaginationAdapter.rebind(Lists.newArrayList(select(jCas, Token.class)));
}
}
public void selectPreviousNamedEntityTagGroup() {
namedEntityPaginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectPreviousGroup);
}
public void selectPreviousNamedEntityTag() {
namedEntityPaginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectPrevious);
}
public void selectNextNamedEntityTagGroup() {
namedEntityPaginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectNextGroup);
}
public void selectNextNamedEntityTag() {
namedEntityPaginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectNext);
}
public void rebindTokens(List<Token> tokens) {
namedEntityPaginationAdapter.rebind(tokens);
}
private void updateSelection(Selection newSelection) {
void updateSelection(Selection newSelection) {
ParallelTransition pt = new ParallelTransition();
if (selection != null && !selection.isEmpty() && newSelection != null && !newSelection.beginsWith(selection)) {
Token firstToken = selection.getSelectedTokens().get(0);
namedEntityPaginationAdapter.apply(firstToken, spinner ->
paginationAdapter.apply(firstToken, spinner ->
pt.getChildren().add(spinner.createExpandTransition(false))
);
pt.getChildren().addAll(
......@@ -160,7 +92,7 @@ public class NamedEntityStream extends Region {
if (newSelection != null && !newSelection.isEmpty()) {
Token firstToken = newSelection.getSelectedTokens().get(0);
namedEntityPaginationAdapter.apply(firstToken, spinner -> {
paginationAdapter.apply(firstToken, spinner -> {
pt.getChildren().add(spinner.createExpandTransition(true));
if (jCas != null) {
pt.getChildren().add(spinner.createMinWidthAnimation(calculateLabelWidth(newSelection.getBegin(), newSelection.getEnd())));
......@@ -174,6 +106,34 @@ public class NamedEntityStream extends Region {
pt.play();
}
public ReadOnlyStringProperty namedEntityTagProperty() {
return namedEntityTag;
}
public void setNamedEntitiesSet(List<String> namedEntitiesSet) {
namedEntityTags.clear();
namedEntityTags.addAll(namedEntitiesSet);
if (jCas != null) {
rebindTokens(Lists.newArrayList(select(jCas, Token.class)));
}
}
public void selectPreviousNamedEntityTagGroup() {
paginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectPreviousGroup);
}
public void selectPreviousNamedEntityTag() {
paginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectPrevious);
}
public void selectNextNamedEntityTagGroup() {
paginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectNextGroup);
}
public void selectNextNamedEntityTag() {
paginationAdapter.apply(selection.getSelectedTokens(), LabelSpinner::selectNext);
}
private Transition createFadeTransition(Selection selection, boolean show) {
ParallelTransition pt = new ParallelTransition();
......@@ -188,7 +148,7 @@ public class NamedEntityStream extends Region {
if (!selection.isEmpty()) {
Token firstToken = selection.getSelectedTokens().get(0);
namedEntityPaginationAdapter.apply(firstToken, spinner -> {
paginationAdapter.apply(firstToken, spinner -> {
FadeTransition ft = new FadeTransition(TRANSITION_DURATION, spinner);
if (show) {
ft.setToValue(1.0);
......@@ -207,7 +167,7 @@ public class NamedEntityStream extends Region {
private double calculateLabelWidth(int begin, int end) {
double width = 0;
for (Token t : selectCovered(jCas, Token.class, begin, end)) {
MinWidthLabel region = (MinWidthLabel) namedEntityPaginationAdapter.getParentOrSelfRegion(t);
MinWidthLabel region = (MinWidthLabel) paginationAdapter.getParentOrSelfRegion(t);
if (region == null) {
continue;
}
......@@ -282,7 +242,7 @@ public class NamedEntityStream extends Region {
private double rebindSpinnerOfNamedEntityToken(NamedEntity namedEntity, Token token, BooleanProperty visible) {
final DoubleExpression firstRegionWidth = new SimpleDoubleProperty(calculateLabelWidth(namedEntity.getBegin(), token.getEnd()));
Token firstTokenOfNamedEntity = JCasUtil.selectAt(jCas, Token.class, namedEntity.getBegin(), namedEntity.getEnd()).get(0);
namedEntityPaginationAdapter.apply(Collections.singletonList(firstTokenOfNamedEntity), c -> {
paginationAdapter.apply(Collections.singletonList(firstTokenOfNamedEntity), c -> {
c.unbindLabelsMinWidth();
c.bindLabelsMinWidth(firstRegionWidth);
});
......
package de.schrieveslaach.nlpf.qpt.view.control.streams;
/*-
* ========================LICENSE_START=================================
* quick-pad-tagger
* %%
* Copyright (C) 2017 Schrieveslaach
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* =========================LICENSE_END==================================
*/
import com.google.common.collect.Lists;
import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.view.control.LabelSpinner;
import de.schrieveslaach.nlpf.qpt.view.control.adapter.PaginationAdapter;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.layout.Region;
import lombok.Getter;
import lombok.Setter;
import org.apache.uima.jcas.JCas;
import java.util.List;
import static javafx.collections.FXCollections.observableArrayList;
import static org.apache.uima.fit.util.JCasUtil.select;
public abstract class TaggingStream extends Region {
final PaginationAdapter<? extends LabelSpinner<String>, Token> paginationAdapter;
JCas jCas;
ObservableList<Token> tokens = observableArrayList();
@Getter
Selection selection;
@Getter
@Setter
boolean active = true;
public TaggingStream() {
this.paginationAdapter = initPaginationAdapter();
widthProperty().addListener(paginationAdapter);
paginationAdapter.regionsProperty().addListener((ListChangeListener<? super LabelSpinner<String>>) c -> {
while (c.next()) {
getChildren().removeAll(c.getRemoved());
getChildren().addAll(c.getAddedSubList());
}
});
tokens.addListener(paginationAdapter);
}
abstract PaginationAdapter<? extends LabelSpinner<String>, Token> initPaginationAdapter();
abstract void updateSelection(Selection selection);
public void setTokens(List<Token> tokens) {
this.tokens.clear();
this.tokens.addAll(tokens);
}
public void setSelection(Selection selection) {
updateSelection(selection);
this.selection = selection;
}
public void setJCas(JCas jCas) {
this.jCas = jCas;
rebindTokens(Lists.newArrayList(select(jCas, Token.class)));
}
public void rebindTokens(List<Token> tokens) {
paginationAdapter.rebind(tokens);
}
public void setParentPaginationAdapter(PaginationAdapter<?, Token> parentPaginationAdapter) {
paginationAdapter.setParentPaginationAdapter(parentPaginationAdapter);
parentPaginationAdapter.addChildPaginationAdapter(paginationAdapter);
}
}
......@@ -40,7 +40,7 @@
<VBox GridPane.columnIndex="2"
GridPane.rowIndex="0"
GridPane.rowSpan="4"
GridPane.rowSpan="5"
prefHeight="600"
prefWidth="300">
......
......@@ -80,15 +80,27 @@ public abstract class AnnotationBehaviorTest<B extends AnnotationBehavior> exten
behavior.activate(tokenStream.getTokenLabelAdapter());
Region tokenTagsRegion = behavior.getTokenTagsRegion();
if (tokenTagsRegion != null) {
AnchorPane.setBottomAnchor(tokenTagsRegion, 85.0);
AnchorPane.setLeftAnchor(tokenTagsRegion, 0.0);
AnchorPane.setRightAnchor(tokenTagsRegion, 0.0);
AnchorPane.setBottomAnchor(tokenTagsRegion, 85.0);
AnchorPane.setLeftAnchor(tokenTagsRegion, 0.0);
AnchorPane.setRightAnchor(tokenTagsRegion, 0.0);
AnchorPane pane = find("#annotation");
pane.getChildren().add(tokenTagsRegion);
AnchorPane pane = find("#annotation");
pane.getChildren().add(tokenTagsRegion);
tokenTagsRegion.toBack();
}
Region tokenRelationsRegion = behavior.getTokenRelationsRegion();
if (tokenRelationsRegion != null) {
AnchorPane.setBottomAnchor(tokenRelationsRegion, 85.0);
AnchorPane.setLeftAnchor(tokenRelationsRegion, 0.0);
AnchorPane.setRightAnchor(tokenRelationsRegion, 0.0);
AnchorPane pane = find("#annotation");
pane.getChildren().add(tokenRelationsRegion);
tokenTagsRegion.toBack();
tokenRelationsRegion.toBack();
}
});
}
......
......@@ -28,7 +28,7 @@ import de.schrieveslaach.nlpf.qpt.service.JCasService;
import de.schrieveslaach.nlpf.qpt.service.ProjectService;
import de.schrieveslaach.nlpf.qpt.view.AnnotationView;
import de.schrieveslaach.nlpf.qpt.view.control.LabelSpinner;
import de.schrieveslaach.nlpf.qpt.view.control.NamedEntityStream;
import de.schrieveslaach.nlpf.qpt.view.control.streams.NamedEntityStream;
import de.tudarmstadt.ukp.dkpro.core.api.ner.type.NamedEntity;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Sentence;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
......@@ -93,10 +93,6 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
public void shouldShowAssignedNamedEntityTag() {
loadJCasAndSelectFirstToken();
// TODO workaround
moveSelectionToRight();
moveSelectionToLeft();
pressAcceptButton();
LabelSpinner<String> spinner = find("#spinner-13");
......@@ -107,9 +103,7 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
public void shouldAssignNamedEntityTag() {
loadJCasAndSelectFirstToken();
// TODO workaround
moveSelectionToRight();
moveSelectionToLeft();
//workaround
moveSelectionDown();
moveSelectionUp();
......@@ -126,9 +120,6 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
public void shouldRemoveAssignedNamedEntityTag() {
loadJCasAndSelectFirstToken();
moveSelectionToRight();
moveSelectionToLeft();
pressAcceptButton();
pressRemoveLeftButton();
......@@ -142,8 +133,6 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
loadJCasAndSelectFirstToken();
//TODO: Workaround
moveSelectionToRight();
moveSelectionToLeft();
moveSelectionDown();
moveSelectionUp();
......@@ -162,9 +151,6 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
public void shouldShowAssignedNamedEntityTag_AfterChangingSelection() {
loadJCasAndSelectFirstToken();
moveSelectionToRight();
moveSelectionToLeft();
moveSelectionDown();
pressAcceptButton();
......@@ -322,17 +308,12 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
public void shouldSuggestSelection_OldSelectionContainsNoNamedEntity_NewSelection_Preceding_ContainsNoNamedEntity() {
loadJCasAndSelectFirstToken();
moveSelectionToRight();
moveSelectionToLeft();
assertThatSelectionIsEqualTo(getTokenByText("Hello"));
}
@Test
public void shouldExpandSelectionToRight_IfCurrentSelection_IsNamedEntity() {
loadJCasWithFirstTokenNamedEntityAndSelectFirstToken();
moveSelectionToRight();
moveSelectionToLeft();
expandSelectionToRight();
......@@ -342,6 +323,8 @@ public class NamedEntityTaggingBehaviorTest extends AnnotationBehaviorTest<Named
@Test
public void shouldNotExpandSelectionToLeft_IfCurrentSelection_IsNamedEntity() {
loadJCasWithLastTokensNamedEntityAndSelectLastTokens();
//TODO workaround
moveSelectionToLeft();
moveSelectionToRight();
......
......@@ -27,7 +27,7 @@ import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.service.JCasService;
import de.schrieveslaach.nlpf.qpt.view.AnnotationView;
import de.schrieveslaach.nlpf.qpt.view.control.LabelSpinner;
import de.schrieveslaach.nlpf.qpt.view.control.PosTagStream;
import de.schrieveslaach.nlpf.qpt.view.control.streams.PosTagStream;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.POS;
import de.tudarmstadt.ukp.dkpro.core.api.lexmorph.type.pos.POS_NOUN;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
......
......@@ -33,6 +33,8 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Region;
import org.apache.uima.jcas.JCas;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
......@@ -51,12 +53,19 @@ import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.PostConstruct;
import java.util.Objects;
import static de.schrieveslaach.nlpf.qpt.view.control.TokenLabel.TOKEN_LABEL_HEIGHT;
import static de.schrieveslaach.nlpf.qpt.view.control.TokenLabel.VERTICAL_BAR_HEIGHT;
import static de.schrieveslaach.nlpf.testing.JCasTestFactory.createOpenNlpExample;
import static org.apache.uima.fit.util.JCasUtil.select;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testfx.matcher.base.NodeMatchers.hasChild;
import static org.testfx.matcher.base.NodeMatchers.hasChildren;
import static org.testfx.matcher.base.NodeMatchers.isDisabled;
import static org.testfx.util.WaitForAsyncUtils.waitForFxEvents;
@RunWith(SpringRunner.class)
......@@ -296,6 +305,55 @@ public class AnnotationControllerTest extends GuiTest {
assertThat(annotationController, hasSelected(suggestedSelection));
}
@Test
public void shouldShowTokenTagsRegion_SelectedBehaviorProvidesTagsRegion() {
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehaviorWithTokenTagsAndRelationsRegions"));
AnchorPane annotation = find("#annotation");
assertThat(annotation, hasChild("#tokenTagsRegion"));
}
@Test
public void shouldShowTokenRelationsRegion_SelectedBehaviorProvidesRelationRegion() {
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehaviorWithTokenTagsAndRelationsRegions"));
AnchorPane annotation = find("#annotation");
assertThat(annotation, hasChild("#tokenRelationsRegion"));
}
@Test
public void shouldRemoveTokenTagsRegion_SwitchBehavior() {
AnchorPane annotation = find("#annotation");
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehavior"));
assertThat(annotation, not(hasChild("#tokenTagsRegion")));
}
@Test
public void shouldRemoveTokenRelationsRegion_SwitchBehavior() {
AnchorPane annotation = find("#annotation");
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehavior"));
assertThat(annotation, not(hasChild("#tokenRelationsRegion")));
}
@Test
public void shouldAdjustTokenRelationsHeight_TokenTagsRegionExists() {
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehaviorWithTokenTagsAndRelationsRegions"));
Region tokenRelationsRegion = find("#tokenRelationsRegion");
double tokenRegionHeight = 60 + TOKEN_LABEL_HEIGHT;
assertThat(AnchorPane.getBottomAnchor(tokenRelationsRegion), is(60 + tokenRegionHeight + 0.25 * VERTICAL_BAR_HEIGHT));
}
@Test
public void shouldAdjustTokenRelationsHeight_TokenTagsRegionNotExists() {
interact(() -> selectedAnnotationBehaviorProperty.setValue("MockedBehaviorWithTokenRelationsRegion"));
Region tokenRelationsRegion = find("#tokenRelationsRegion");
assertThat(AnchorPane.getBottomAnchor(tokenRelationsRegion), is(60.0 + 0.25 * VERTICAL_BAR_HEIGHT));
}
private void moveSelectionToRight() {
interact(() -> {
Action action = mock(Action.class);
......@@ -408,6 +466,52 @@ public class AnnotationControllerTest extends GuiTest {
public static class AnnotationControllerConfig {
@Bean
@Qualifier("behavior-consumer")
public AnnotationBehavior mockedAnnotationBehaviorWithTokenTagsAndRelationsRegions() {
AnnotationBehavior annotationBehavior = mock(AnnotationBehavior.class);
when(annotationBehavior.getName()).thenReturn("MockedBehaviorWithTokenTagsAndRelationsRegions");
when(annotationBehavior.suggestNewSelection(any(Selection.class), any(Selection.class)))
.then(invocation -> invocation.<Selection>getArgument(1));
Region tokenTagsRegion = new Region();
tokenTagsRegion.setId("tokenTagsRegion");
when(annotationBehavior.getTokenTagsRegion()).thenReturn(tokenTagsRegion);
Region tokenRelationsRegion = new Region();
tokenRelationsRegion.setId("tokenRelationsRegion");
when(annotationBehavior.getTokenRelationsRegion()).thenReturn(tokenRelationsRegion);
return annotationBehavior;
}
@Bean
@Qualifier("behavior-consumer")
public AnnotationBehavior mockedAnnotationBehaviorWithTokenTagsRegion() {
AnnotationBehavior annotationBehavior = mock(AnnotationBehavior.class);
when(annotationBehavior.getName()).thenReturn("MockedBehaviorWithTokenTagsRegion");
when(annotationBehavior.suggestNewSelection(any(Selection.class), any(Selection.class)))
.then(invocation -> invocation.<Selection>getArgument(1));
Region tokenTagsRegion = new Region();
tokenTagsRegion.setId("tokenTagsRegion");
when(annotationBehavior.getTokenRelationsRegion()).thenReturn(tokenTagsRegion);
return annotationBehavior;
}
@Bean
@Qualifier("behavior-consumer")
public AnnotationBehavior mockedAnnotationBehaviorWithTokenRelationsRegion() {
AnnotationBehavior annotationBehavior = mock(AnnotationBehavior.class);
when(annotationBehavior.getName()).thenReturn("MockedBehaviorWithTokenRelationsRegion");
when(annotationBehavior.suggestNewSelection(any(Selection.class), any(Selection.class)))
.then(invocation -> invocation.<Selection>getArgument(1));
Region tokenRelationsRegion = new Region();
tokenRelationsRegion.setId("tokenRelationsRegion");
when(annotationBehavior.getTokenRelationsRegion()).thenReturn(tokenRelationsRegion);
return annotationBehavior;
}
@Bean
@Qualifier("behavior-consumer")
public AnnotationBehavior mockedAnnotationBehavior() {
......@@ -415,6 +519,7 @@ public class AnnotationControllerTest extends GuiTest {
when(annotationBehavior.getName()).thenReturn("MockedBehavior");
when(annotationBehavior.suggestNewSelection(any(Selection.class), any(Selection.class)))
.then(invocation -> invocation.<Selection>getArgument(1));
return annotationBehavior;
}
......
......@@ -53,6 +53,7 @@ import java.util.List;
import static de.schrieveslaach.nlpf.testing.JCasTestFactory.createHelloWorld;
import static java.util.Arrays.asList;
import static java.util.Arrays.fill;
import static javafx.collections.FXCollections.observableArrayList;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
......@@ -145,7 +146,7 @@ public class MenuControllerTest extends GuiTest {
@Test
public void shouldHighlightSelectedAnnotationBehaviour_TextSegmentation() {
pressMenuButton();
moveSelectionDown();
moveSelectionDown(); // move to segmentation
pressAcceptButton();
......@@ -157,6 +158,9 @@ public class MenuControllerTest extends GuiTest {
lb = find("#NamedEntityTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#Chunking");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
}
@Test
......@@ -173,8 +177,8 @@ public class MenuControllerTest extends GuiTest {
@Test
public void shouldHighlightSelectedAnnotationBehaviour_PosTagging() {
pressMenuButton();
moveSelectionDown();
moveSelectionDown();
moveSelectionDown(); //move to segmentation
moveSelectionDown(); // move to pos
pressAcceptButton();
......@@ -184,14 +188,36 @@ public class MenuControllerTest extends GuiTest {
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(true)));
lb = find("#NamedEntityTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#Chunking");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
}
@Test
public void shouldHighlightSelectedAnnotationBehaviour_NamedEntityTagging() {
pressMenuButton();
moveSelectionDown();
moveSelectionDown();
moveSelectionDown();
moveSelectionDown(); //move to segmentation
moveSelectionDown(); // move to pos
moveSelectionDown(); // move to ne
pressAcceptButton();
TokenLabel lb = find("#Segmentation");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#PosTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#NamedEntityTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(true)));
lb = find("#Chunking");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
}
@Test
public void shouldHighlightSelectedAnnotationBehaviour_Chunking() {
pressMenuButton();
moveSelectionDown(); //move to segmentation
moveSelectionDown(); // move to pos
moveSelectionDown(); // move to ne
moveSelectionDown(); // move to chunking
pressAcceptButton();
......@@ -200,6 +226,8 @@ public class MenuControllerTest extends GuiTest {
lb = find("#PosTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#NamedEntityTagging");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(false)));
lb = find("#Chunking");
assertThat(lb.showSelectedIndicatorProperty().get(), is(equalTo(true)));
}
......@@ -219,9 +247,10 @@ public class MenuControllerTest extends GuiTest {
for (int i = 0; i < 10; ++i) {
moveSelectionDown();
}
moveSelectionToLeft();
moveSelectionUp();
moveSelectionUp();
moveSelectionToLeft(); // move to chunking
moveSelectionUp(); // move to NE
moveSelectionUp(); // move to pos
moveSelectionUp(); // move to segmentation
pressAcceptButton();
assertThat(menuController.selectedAnnotationBehaviorProperty().get(), is("Segmentation"));
......@@ -242,8 +271,9 @@ public class MenuControllerTest extends GuiTest {
for (int i = 0; i < 10; ++i) {
moveSelectionDown();
}
moveSelectionToLeft();
moveSelectionUp();
moveSelectionToLeft(); // move to chunking
moveSelectionUp(); // move to NE
moveSelectionUp(); // move to pos
pressAcceptButton();
assertThat(menuController.selectedAnnotationBehaviorProperty().get(), is("PosTagging"));
......@@ -264,12 +294,34 @@ public class MenuControllerTest extends GuiTest {
for (int i = 0; i < 10; ++i) {
moveSelectionDown();
}
moveSelectionToLeft();
moveSelectionToLeft(); // move to chunking
moveSelectionUp(); // move to NE
pressAcceptButton();
assertThat(menuController.selectedAnnotationBehaviorProperty().get(), is("NamedEntityTagging"));
}
@Test
public void shouldSwitchFromDocumentsToAnnotationBehaviors_Chunking_LongListOfDocuments() {
List<Document> documents = new ArrayList<>();
for (int i = 0; i < 20; ++i) {
Document doc = mock(Document.class);
when(doc.getName()).thenReturn("doc" + i);
documents.add(doc);
}
openDocuments(documents.toArray(new Document[documents.size()]));
pressMenuButton();
moveSelectionToRight();
for (int i = 0; i < 10; ++i) {
moveSelectionDown();
}
moveSelectionToLeft(); // move to chunking
pressAcceptButton();
assertThat(menuController.selectedAnnotationBehaviorProperty().get(), is("Chunking"));
}
@Test
public void shouldSwitchFromDocumentsToAnnotationBehaviorsAndBackAgain_LongListOfDocuments() {
List<Document> documents = new ArrayList<>();
......@@ -619,7 +671,10 @@ public class MenuControllerTest extends GuiTest {
AnnotationBehavior namedEntity = mock(AnnotationBehavior.class);
when(namedEntity.getName()).thenReturn("NamedEntityTagging");
return asList(segmentation, posTagging, namedEntity);
AnnotationBehavior chunking = mock(AnnotationBehavior.class);
when(chunking.getName()).thenReturn("Chunking");
return asList(segmentation, posTagging, namedEntity, chunking);
}
}
}
......@@ -195,6 +195,27 @@ public class ProjectServiceTest extends GuiTest {
assertThat(projectService.namedEntitiesProperty(), contains("location", "organization", "person"));
}
@Test
public void shouldLoadChunkTagsSetFromProperties() {
Properties properties = new Properties();
properties.setProperty("chunk.tag.set", "conll2000");
File pom = createExampleCorpus(properties);
projectService.open(pom);
assertThat(projectService.chunkTagSetProperty().get(), is("conll2000"));
}
@Test
public void shouldLoadChunkTagSet_NoValueSpecifiedInMavenProperties() {
File pom = createExampleCorpus();
projectService.open(pom);
//TODO: Replace with a useful standard tagset
assertThat(projectService.chunkTagSetProperty().get(), is("default"));
}
@Test
public void shouldLoadDocuments() {
File pom = createExampleCorpus();
......
package de.schrieveslaach.nlpf.qpt.view.control.streams;
/*-
* ========================LICENSE_START=================================
* quick-pad-tagger
* %%
* Copyright (C) 2017 Schrieveslaach
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* =========================LICENSE_END==================================
*/
import com.google.common.collect.Lists;
import de.roskenet.jfxsupport.test.GuiTest;
import de.schrieveslaach.nlpf.qpt.model.Selection;
import de.schrieveslaach.nlpf.qpt.view.control.LabelSpinner;
import de.tudarmstadt.ukp.dkpro.core.api.segmentation.type.Token;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import org.apache.uima.jcas.JCas;
import org.hamcrest.Matcher;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import static de.schrieveslaach.nlpf.testing.JCasTestFactory.createOpenNlpExampleWithChunks;
import static javafx.collections.FXCollections.observableArrayList;
import static org.apache.uima.fit.util.JCasUtil.select;
import static org.apache.uima.fit.util.JCasUtil.selectFollowing;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.testfx.matcher.base.GeneralMatchers.baseMatcher;
import static org.testfx.util.WaitForAsyncUtils.waitForFxEvents;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
ChunkstreamView.class
})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class ChunkStreamTest extends GuiTest {
private ObservableList<Token> tokens = observableArrayList();
private ObjectProperty<JCas> jCas = new SimpleObjectProperty<>();
private ChunkStream chunkStream;
@PostConstruct
public void constructView() throws Exception {
init(ChunkstreamView.class);
}
@Test
public void shouldShowChunkSpinner_ForChunk_SpinnerShouldBeCentered() {
loadOpenNlpExample();
LabelSpinner<String> labelSpinnerFirstChunk = find("#spinner-29");
// Chunks consists of two Tokens: 2 * TOKEN_LABEL_WIDTH + 20
assertThat(labelSpinnerFirstChunk.labelMinWidthProperty().get(), is(420.0));
}
@Test
public void shouldShowChunkSpinner_SelectionDoesNotCoverExistingChunk() {
loadOpenNlpExample();
moveSelectionToRight();
moveSelectionToRight();
LabelSpinner<String> labelSpinnerThirdToken = find("#spinner-59");
assertThat(labelSpinnerThirdToken, isOpaque());
}
@Test
public void shouldNotShowChunkSpinner_SelectionCoversExistingChunk() {
loadOpenNlpExample();
moveSelectionToRight();
LabelSpinner<String> labelSpinnerSecondToken = find("#spinner-41");
assertThat(labelSpinnerSecondToken, isTranslucent());
}
@Test
public void shouldDrawLine_ChunkSizeOne() {
loadOpenNlpExample();
}
@Test
public void shouldDrawLine_ChunkSizeTwo() {
}
@Test
public void shouldDrawLine_ChunkSizeThree() {
}
private void loadOpenNlpExample() {
interact(() -> {
JCas openNlpExample = createOpenNlpExampleWithChunks();
this.jCas.setValue(openNlpExample);
ArrayList<Token> tokens = Lists.newArrayList(select(openNlpExample, Token.class));
chunkStream = find("#chunkStream");
chunkStream.setSelection(new Selection(openNlpExample, tokens.get(0)));
chunkStream.setJCas(openNlpExample);
chunkStream.setTokens(tokens);