blob: 92903299e77935beb4211d39ec5ed40e1186dc6e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#include "uima/api.hpp"
using namespace uima;
class MeetingAnnotator : public Annotator {
private:
//config param window size
int mWindowSize;
//Input types
Type roomNumberT;
Type dateT;
Type timeT;
//output type and its features
Type meetingT;
Feature roomF;
Feature dateF;
Feature startTimeF;
Feature endTimeF;
public:
MeetingAnnotator(void)
{
cout << "MeetingAnnotator: Constructor" << endl;
}
~MeetingAnnotator(void)
{
cout << "MeetingAnnotator: Destructor" << endl;
}
/** */
TyErrorId initialize(AnnotatorContext & rclAnnotatorContext)
{
cout << "MeetingAnnotator: initialize()" << endl;
if (!rclAnnotatorContext.isParameterDefined("WindowSize") ||
rclAnnotatorContext.extractValue("WindowSize", mWindowSize) != UIMA_ERR_NONE) {
/* log the error condition */
rclAnnotatorContext.getLogger().logError("Required configuration parameter \"WindowSize\" not found in component descriptor");
cout << "initialize() - Error. See logfile." << endl;
return UIMA_ERR_USER_ANNOTATOR_COULD_NOT_INIT;
}
if (mWindowSize < 50) {
rclAnnotatorContext.getLogger().logWarning("WindowSize may be too narrow");
}
/* log the configuration parameter setting */
std::stringstream ss;
std::string str;
ss << mWindowSize;
ss >> str;
rclAnnotatorContext.getLogger().logMessage("WindowSize = '" + str + "'");
cout << "initialize() .. mWindowSize.getBuffer: "
<< mWindowSize << endl;
return (TyErrorId)UIMA_ERR_NONE;
}
/** */
TyErrorId typeSystemInit(TypeSystem const & crTypeSystem) {
cout << " typeSystemInit()" << endl;
//input types
roomNumberT = crTypeSystem.getType("org.apache.uima.tutorial.RoomNumber");
dateT = crTypeSystem.getType("org.apache.uima.tutorial.DateAnnot");
timeT = crTypeSystem.getType("org.apache.uima.tutorial.TimeAnnot");
//output types and features
meetingT = crTypeSystem.getType("org.apache.uima.tutorial.Meeting");
if ( !(meetingT.isValid() && roomNumberT.isValid() && dateT.isValid() && timeT.isValid()) ) {
getAnnotatorContext().getLogger().logError("typeSystemInit() Error getting Type objects");
cout << "typeSystemInit() Error getting Type object" << endl;
return (TyErrorId) UIMA_ERR_RESMGR_INVALID_RESOURCE;
}
//get features
roomF = meetingT.getFeatureByBaseName("room");
dateF = meetingT.getFeatureByBaseName("date");
startTimeF = meetingT.getFeatureByBaseName("startTime");
endTimeF = meetingT.getFeatureByBaseName("endTime");
if ( !(roomF.isValid() && dateF.isValid() && startTimeF.isValid() && endTimeF.isValid() ) ) {
getAnnotatorContext().getLogger().logError("typeSystemInit() Error getting Feature objects");
cout << "typeSystemInit() Error getting Feature object" << endl;
return (TyErrorId) UIMA_ERR_RESMGR_INVALID_RESOURCE;
}
return (TyErrorId)UIMA_ERR_NONE;
}
/** */
TyErrorId destroy()
{
cout << "MeetingAnnotator: destroy()" << endl;
return (TyErrorId)UIMA_ERR_NONE;
}
/** */
TyErrorId process(CAS & tcas, ResultSpecification const & crResultSpecification)
{
cout << "MeetingAnnotator: process()" << endl;
//get annotation indexes
FSIndexRepository & indexes = tcas.getIndexRepository();
ANIndex roomNumberIndex = tcas.getAnnotationIndex(roomNumberT);
ANIndex dateIndex = tcas.getAnnotationIndex(dateT);
ANIndex timeIndex = tcas.getAnnotationIndex(timeT);
//store end position of last meeting we identified, to prevent multiple
//annotations over same span
int lastMeetingEnd = -1;
//iterate over all combinations
ANIterator roomNumberIter = roomNumberIndex.iterator();
roomNumberIter.moveToFirst();
while (roomNumberIter.isValid()) {
AnnotationFS room = roomNumberIter.get();
ANIterator dateIter = dateIndex.iterator();
dateIter.moveToFirst();
while (dateIter.isValid()) {
AnnotationFS date = dateIter.get();
ANIterator time1Iter = timeIndex.iterator();
time1Iter.moveToFirst();
while (time1Iter.isValid()) {
AnnotationFS time1 = time1Iter.get();
ANIterator time2Iter = timeIndex.iterator();
time2Iter.moveToFirst();
while (time2Iter.isValid()) {
AnnotationFS time2 = time2Iter.get();
//times must be different annotations
if (time1 != time2) {
//compute the begin and end of the span
int minBegin = min(
min(time1.getBeginPosition(), time2.getBeginPosition()),
min(date.getBeginPosition(), room.getBeginPosition()));
int maxEnd = max(
max(time1.getEndPosition(), time2.getEndPosition()),
max(date.getEndPosition(), room.getEndPosition()));
//span must be smaller than the window size?
if (maxEnd - minBegin < mWindowSize) {
//span must not overlap the last annotation we made
if (minBegin > lastMeetingEnd) {
//annotate
//Create Meeting FS and set the begin and end features
AnnotationFS mtg = tcas.createAnnotation(meetingT, minBegin, maxEnd);
//Set other four features
mtg.setFSValue(roomF, room);
mtg.setFSValue(dateF, date);
mtg.setFSValue(startTimeF, time1);
mtg.setFSValue(endTimeF, time2);
//add annotation to the index
indexes.addFS(mtg);
lastMeetingEnd = maxEnd;
}
}
}
time2Iter.moveToNext();
}
time1Iter.moveToNext();
}
dateIter.moveToNext();
}
roomNumberIter.moveToNext();
}
return (TyErrorId)UIMA_ERR_NONE;
}
};
// This macro exports an entry point that is used to create the annotator.
MAKE_AE(MeetingAnnotator);