use of de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage in project webanno by webanno.
the class CasDoctor method analyze.
public boolean analyze(Project aProject, CAS aCas, List<LogMessage> aMessages, boolean aFatalChecks) throws CasDoctorException {
long tStart = System.currentTimeMillis();
boolean ok = true;
for (Class<? extends Check> checkClass : checkClasses) {
try {
long tStartTask = System.currentTimeMillis();
Check check = checkClass.newInstance();
if (context != null) {
context.getAutowireCapableBeanFactory().autowireBean(check);
}
LOG.debug("CasDoctor analysis [" + checkClass.getSimpleName() + "] running...");
ok &= check.check(aProject, aCas, aMessages);
LOG.debug("CasDoctor analysis [" + checkClass.getSimpleName() + "] completed in " + (System.currentTimeMillis() - tStartTask) + "ms");
} catch (InstantiationException | IllegalAccessException e) {
aMessages.add(new LogMessage(this, LogLevel.ERROR, "Cannot instantiate [%s]: %s", checkClass.getSimpleName(), ExceptionUtils.getRootCauseMessage(e)));
LOG.error("Error running check", e);
}
}
if (!ok) {
aMessages.forEach(s -> LOG.error("{}", s));
}
if (!ok && aFatalChecks) {
throw new CasDoctorException(aMessages);
}
LOG.debug("CasDoctor completed all analyses in " + (System.currentTimeMillis() - tStart) + "ms");
return ok;
}
use of de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage in project webanno by webanno.
the class CasMerge method reMergeCas.
/**
* Using {@code DiffResult}, determine the annotations to be deleted from the randomly generated
* MergeCase. The initial Merge CAs is stored under a name {@code CurationPanel#CURATION_USER}.
* <p>
* Any similar annotations stacked in a {@code CasDiff2.Position} will be assumed a difference
* <p>
* Any two annotation with different value will be assumed a difference
* <p>
* Any non stacked empty/null annotations are assumed agreement
* <p>
* Any non stacked annotations with similar values for each of the features are assumed
* agreement
* <p>
* Any two link mode / slotable annotations which agree on the base features are assumed
* agreement
*
* @param aDiff
* the {@link DiffResult}
* @param aCases
* a map of {@code CAS}s for each users and the random merge
*/
public void reMergeCas(DiffResult aDiff, SourceDocument aTargetDocument, String aTargetUsername, CAS aTargetCas, Map<String, CAS> aCases) throws AnnotationException, UIMAException {
silenceEvents = true;
int updated = 0;
int created = 0;
Set<LogMessage> messages = new LinkedHashSet<>();
// Remove any annotations from the target CAS - keep type system, sentences and tokens
clearAnnotations(aTargetCas);
// If there is nothing to merge, bail out
if (aCases.isEmpty()) {
return;
}
// Set up a cache for resolving type to layer to avoid hammering the DB as we process each
// position
Map<String, AnnotationLayer> type2layer = aDiff.getPositions().stream().map(Position::getType).distinct().map(type -> schemaService.findLayer(aTargetDocument.getProject(), type)).collect(toMap(AnnotationLayer::getName, identity()));
List<String> layerNames = new ArrayList<>(type2layer.keySet());
// Move token layer to front
if (layerNames.contains(Token.class.getName())) {
layerNames.remove(Token.class.getName());
layerNames.add(0, Token.class.getName());
}
// Move sentence layer to front
if (layerNames.contains(Sentence.class.getName())) {
layerNames.remove(Sentence.class.getName());
layerNames.add(0, Sentence.class.getName());
}
// and sentences before the others)
for (String layerName : layerNames) {
List<SpanPosition> positions = aDiff.getPositions().stream().filter(pos -> layerName.equals(pos.getType())).filter(pos -> pos instanceof SpanPosition).map(pos -> (SpanPosition) pos).filter(pos -> pos.getFeature() == null).collect(Collectors.toList());
if (positions.isEmpty()) {
continue;
}
LOG.debug("Processing {} span positions on layer {}", positions.size(), layerName);
// Slots are also excluded for the moment
for (SpanPosition position : positions) {
LOG.trace(" | processing {}", position);
ConfigurationSet cfgs = aDiff.getConfigurationSet(position);
if (!shouldMerge(aDiff, cfgs)) {
continue;
}
try {
Map<String, List<CAS>> casMap = new LinkedHashMap<>();
aCases.forEach((k, v) -> casMap.put(k, asList(v)));
AnnotationFS sourceFS = (AnnotationFS) cfgs.getConfigurations().get(0).getRepresentative(casMap);
CasMergeOperationResult result = mergeSpanAnnotation(aTargetDocument, aTargetUsername, type2layer.get(position.getType()), aTargetCas, sourceFS, false);
LOG.trace(" `-> merged annotation with agreement");
switch(result.getState()) {
case CREATED:
created++;
break;
case UPDATED:
updated++;
break;
}
} catch (AnnotationException e) {
LOG.trace(" `-> not merged annotation: {}", e.getMessage());
messages.add(LogMessage.error(this, "%s", e.getMessage()));
}
}
}
// After the spans are in place, we can merge the slot features
for (String layerName : layerNames) {
List<SpanPosition> positions = aDiff.getPositions().stream().filter(pos -> layerName.equals(pos.getType())).filter(pos -> pos instanceof SpanPosition).map(pos -> (SpanPosition) pos).filter(pos -> pos.getFeature() != null).collect(Collectors.toList());
if (positions.isEmpty()) {
continue;
}
LOG.debug("Processing {} slot positions on layer [{}]", positions.size(), layerName);
for (SpanPosition position : positions) {
LOG.trace(" | processing {}", position);
ConfigurationSet cfgs = aDiff.getConfigurationSet(position);
if (!shouldMerge(aDiff, cfgs)) {
continue;
}
try {
Map<String, List<CAS>> casMap = new LinkedHashMap<>();
aCases.forEach((k, v) -> casMap.put(k, asList(v)));
AnnotationFS sourceFS = (AnnotationFS) cfgs.getConfigurations().get(0).getRepresentative(casMap);
AID sourceFsAid = cfgs.getConfigurations().get(0).getRepresentativeAID();
mergeSlotFeature(aTargetDocument, aTargetUsername, type2layer.get(position.getType()), aTargetCas, sourceFS, sourceFsAid.feature, sourceFsAid.index);
LOG.trace(" `-> merged annotation with agreement");
} catch (AnnotationException e) {
LOG.trace(" `-> not merged annotation: {}", e.getMessage());
messages.add(LogMessage.error(this, "%s", e.getMessage()));
}
}
}
// Finally, we merge the relations
for (String layerName : layerNames) {
List<RelationPosition> positions = aDiff.getPositions().stream().filter(pos -> layerName.equals(pos.getType())).filter(pos -> pos instanceof RelationPosition).map(pos -> (RelationPosition) pos).collect(Collectors.toList());
if (positions.isEmpty()) {
continue;
}
LOG.debug("Processing {} relation positions on layer [{}]", positions.size(), layerName);
for (RelationPosition position : positions) {
LOG.trace(" | processing {}", position);
ConfigurationSet cfgs = aDiff.getConfigurationSet(position);
if (!shouldMerge(aDiff, cfgs)) {
continue;
}
try {
Map<String, List<CAS>> casMap = new LinkedHashMap<>();
aCases.forEach((k, v) -> casMap.put(k, asList(v)));
AnnotationFS sourceFS = (AnnotationFS) cfgs.getConfigurations().get(0).getRepresentative(casMap);
CasMergeOperationResult result = mergeRelationAnnotation(aTargetDocument, aTargetUsername, type2layer.get(position.getType()), aTargetCas, sourceFS, false);
LOG.trace(" `-> merged annotation with agreement");
switch(result.getState()) {
case CREATED:
created++;
break;
case UPDATED:
updated++;
break;
}
} catch (AnnotationException e) {
LOG.trace(" `-> not merged annotation: {}", e.getMessage());
messages.add(LogMessage.error(this, "%s", e.getMessage()));
}
}
}
if (eventPublisher != null) {
eventPublisher.publishEvent(new BulkAnnotationEvent(this, aTargetDocument, aTargetUsername, null));
}
}
use of de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage in project webanno by webanno.
the class AllFeatureStructuresIndexedCheck method check.
@Override
public boolean check(Project aProject, CAS aCas, List<LogMessage> aMessages) {
Map<FeatureStructure, FeatureStructure> nonIndexed = getNonIndexedFSesWithOwner(aCas);
if (!nonIndexed.isEmpty()) {
aMessages.add(new LogMessage(this, LogLevel.ERROR, "Unindexed feature structures: %d", nonIndexed.size()));
int count = 0;
for (Entry<FeatureStructure, FeatureStructure> e : nonIndexed.entrySet()) {
if (count >= 100) {
break;
}
aMessages.add(LogMessage.error(this, "Non-indexed feature structure [%s] reachable through [%s]", e.getKey(), e.getValue()));
count++;
}
if (count >= 100) {
aMessages.add(LogMessage.error(this, "In total [%d] annotations were reachable but not indexed", count));
}
}
return nonIndexed.isEmpty();
}
use of de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage in project webanno by webanno.
the class NoMultipleIncomingRelationsCheckTest method testFail.
@Test
public void testFail() throws Exception {
AnnotationLayer relationLayer = new AnnotationLayer();
relationLayer.setName(Dependency.class.getName());
relationLayer.setType(WebAnnoConst.RELATION_TYPE);
Mockito.when(annotationService.listAnnotationLayer(Mockito.isNull())).thenReturn(Arrays.asList(relationLayer));
JCas jcas = JCasFactory.createJCas();
jcas.setDocumentText("This is a test.");
Token spanThis = new Token(jcas, 0, 4);
spanThis.addToIndexes();
Token spanIs = new Token(jcas, 5, 7);
spanIs.addToIndexes();
Token spanA = new Token(jcas, 8, 9);
spanA.addToIndexes();
Dependency dep1 = new Dependency(jcas, 0, 7);
dep1.setGovernor(spanThis);
dep1.setDependent(spanIs);
dep1.addToIndexes();
Dependency dep2 = new Dependency(jcas, 0, 9);
dep2.setGovernor(spanA);
dep2.setDependent(spanIs);
dep2.addToIndexes();
List<LogMessage> messages = new ArrayList<>();
boolean result = check.check(null, jcas.getCas(), messages);
messages.forEach(System.out::println);
assertTrue(result);
// also check the message itself
assertEquals(1, messages.size());
assertEquals("[NoMultipleIncomingRelationsCheck] Relation [This] -> [is] points to span that already has an incoming relation [a] -> [is].", messages.get(0).toString());
}
use of de.tudarmstadt.ukp.clarin.webanno.support.logging.LogMessage in project webanno by webanno.
the class NoMultipleIncomingRelationsCheckTest method testOkBecauseCoref.
@Test
public void testOkBecauseCoref() throws Exception {
AnnotationLayer relationLayer = new AnnotationLayer();
relationLayer.setName(CoreferenceChain.class.getName());
relationLayer.setType(WebAnnoConst.CHAIN_TYPE);
Mockito.when(annotationService.listAnnotationLayer(Mockito.isNull())).thenReturn(Arrays.asList(relationLayer));
JCas jcas = JCasFactory.createJCas();
jcas.setDocumentText("This is a test.");
Token spanThis = new Token(jcas, 0, 4);
spanThis.addToIndexes();
Token spanIs = new Token(jcas, 6, 8);
spanIs.addToIndexes();
Token spanA = new Token(jcas, 9, 10);
spanA.addToIndexes();
Dependency dep1 = new Dependency(jcas, 0, 8);
dep1.setGovernor(spanThis);
dep1.setDependent(spanIs);
dep1.addToIndexes();
Dependency dep2 = new Dependency(jcas, 0, 10);
dep2.setGovernor(spanA);
dep2.setDependent(spanIs);
dep2.addToIndexes();
List<LogMessage> messages = new ArrayList<>();
boolean result = check.check(null, jcas.getCas(), messages);
messages.forEach(System.out::println);
assertTrue(result);
}
Aggregations