edu.uab.ccts.nlp.uima.annotator.SegmentRegexAnnotator.java Source code

Java tutorial

Introduction

Here is the source code for edu.uab.ccts.nlp.uima.annotator.SegmentRegexAnnotator.java

Source

/**
 * 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.
 */
package edu.uab.ccts.nlp.uima.annotator;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ctakes.typesystem.type.textspan.Segment;
import org.apache.ctakes.ytex.uima.ApplicationContextHolder;
import org.apache.ctakes.ytex.uima.dao.SegmentRegexDao;
import org.apache.ctakes.ytex.uima.model.SegmentRegex;
import org.apache.uima.UimaContext;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import org.uimafit.component.JCasAnnotator_ImplBase;
import org.uimafit.descriptor.ConfigurationParameter;
import org.uimafit.factory.AnalysisEngineFactory;

/**
 * Annotate segments (i.e. sections). Use regexs to find segments. Read the
 * regex-segment id map from the db.
 * 
 * @author vhacongarlav, ozborn
 * 
 */
public class SegmentRegexAnnotator extends JCasAnnotator_ImplBase {

    public static final String PARAM_DEFAULT_SEGMENT = "defaultSegmentId";
    @ConfigurationParameter(name = PARAM_DEFAULT_SEGMENT, description = "Name of the default segment", defaultValue = "DEFAULT")
    private String defaultSegmentId = "DEFAULT";

    public static final String PARAM_SEGMENT_REGEX_DAO = "segmentRegexDaoBeanName";
    @ConfigurationParameter(name = PARAM_SEGMENT_REGEX_DAO, description = "Name of the segment Regex Dao bean", defaultValue = "segmentRegexDao")
    private String segmentRegexDaoBeanName;

    private static final Log log = LogFactory.getLog(SegmentRegexAnnotator.class);
    private SegmentRegexDao segmentRegexDao;
    private Map<SegmentRegex, Pattern> regexMap = new HashMap<SegmentRegex, Pattern>();

    /**
     * Load the regex-segment map from the database using the segmentRegexDao.
     * Compile all the patterns.
     */
    /*
    public void initialize(UimaContext aContext)
     throws ResourceInitializationException {
       segmentRegexDao = (SegmentRegexDao) ApplicationContextHolder
        .getApplicationContext().getBean("segmentRegexDao");
       List<SegmentRegex> regexList = segmentRegexDao.getSegmentRegexs();
       initRegexMap(regexList);
       String defaultSegmentId = (String) aContext
        .getConfigParameterValue("SegmentID");
       if (!Strings.isNullOrEmpty(defaultSegmentId)) {
     this.defaultSegmentId = defaultSegmentId;
       }
    }
    */

    /**
     * Load the regex-segment map from the database using the segmentRegexDao.
     * Compile all the patterns.
     */
    //public void afterResourcesInitialized() {
    //public void initialize(org.apache.uima.resource.ResourceSpecifier aSpecifier, Map<String,Object> aAdditionalParams) {
    public void initialize(UimaContext context) throws ResourceInitializationException {
        super.initialize(context);
        segmentRegexDao = (SegmentRegexDao) ApplicationContextHolder
                //.getApplicationContext().getBean("segmentRegexDao");
                .getApplicationContext().getBean(segmentRegexDaoBeanName);
        List<SegmentRegex> regexList = segmentRegexDao.getSegmentRegexs();
        log.debug("Got " + regexList.size() + " regexLists");
        initRegexMap(regexList);
    }

    protected void initRegexMap(List<SegmentRegex> regexList) {
        for (SegmentRegex regex : regexList) {
            if (log.isDebugEnabled())
                log.debug(regex);
            Pattern pat = Pattern.compile(regex.getRegex());
            regexMap.put(regex, pat);
            //System.out.println(regex);
        }
    }

    /**
     * Add Segment annotations to the cas. First create a list of segments. Then
     * sort the list according to segment start. For each segment that has no
     * end, set the end to the [beginning of next segment - 1], or the eof.
     */
    @Override
    public void process(JCas aJCas) throws AnalysisEngineProcessException {
        log.info("Starting SegmentRegexAnnotator with " + regexMap.size() + " segements.");
        String strDocText = aJCas.getDocumentText();
        if (strDocText == null)
            return;
        List<Segment> segmentsAdded = new ArrayList<Segment>();
        // find all the segments, set begin and id, add to list
        for (Map.Entry<SegmentRegex, Pattern> entry : regexMap.entrySet()) {
            if (log.isDebugEnabled()) {
                log.debug("applying regex:" + entry.getKey().getRegex());
            }
            Matcher matcher = entry.getValue().matcher(strDocText);
            while (matcher.find()) {
                Segment seg = new Segment(aJCas);
                if (entry.getKey().isLimitToRegex() && matcher.groupCount() == 1) {
                    seg.setBegin(matcher.start(1));
                    seg.setEnd(matcher.end(1));
                } else {
                    seg.setBegin(matcher.start());
                    if (entry.getKey().isLimitToRegex()) {
                        seg.setEnd(matcher.end());
                    }
                }
                seg.setId(entry.getKey().getSegmentID());
                //if (log.isDebugEnabled()) {
                log.debug("found match: id=" + seg.getId() + ", begin=" + seg.getBegin() + " end=" + seg.getEnd());
                //}
                segmentsAdded.add(seg);
            }
        }
        if (log.isDebugEnabled()) {
            log.debug("segmentsAdded: " + segmentsAdded.size());
        }
        if (segmentsAdded.size() > 0) {
            // sort the segments by begin
            Collections.sort(segmentsAdded, new Comparator<Segment>() {

                // @Override
                public int compare(Segment o1, Segment o2) {
                    return o1.getBegin() < o2.getBegin() ? -1 : o1.getBegin() > o2.getBegin() ? 1 : 0;
                }

            });
            // set the end for each segment
            for (int i = 0; i < segmentsAdded.size(); i++) {
                Segment seg = segmentsAdded.get(i);
                Segment segNext = (i + 1) < segmentsAdded.size() ? segmentsAdded.get(i + 1) : null;
                if (seg.getEnd() <= 0) {
                    if (segNext != null) {
                        // set end to beginning of next segment
                        seg.setEnd(segNext.getBegin() - 1);
                    } else {
                        // set end to doc end
                        seg.setEnd(strDocText.length());
                    }
                } else {
                    // segments shouldn't overlap
                    if (segNext != null && segNext.getBegin() < seg.getEnd()) {
                        seg.setEnd(segNext.getBegin() - 1);
                    }
                }
                //if (log.isDebugEnabled()) {
                log.debug("Adding Segment: segment id=" + seg.getId() + ", begin=" + seg.getBegin() + ", end="
                        + seg.getEnd());
                //}
                seg.addToIndexes();
            }
        }
        // ctakes 1.3.2 - anything not in a segment will not be annotated - add
        // text outside segments to the 'default' segment
        int end = 0;
        for (Segment seg : segmentsAdded) {
            if ((seg.getBegin() - 1) > end) {
                addGapSegment(aJCas, end, seg.getBegin() - 1);
            }
            end = seg.getEnd();
        }
        if (end < strDocText.length()) {
            addGapSegment(aJCas, end, strDocText.length());
        }
    }

    private void addGapSegment(JCas aJCas, int begin, int end) {
        Segment segGap = new Segment(aJCas);
        segGap.setBegin(begin);
        segGap.setEnd(end);
        segGap.addToIndexes();
        segGap.setId(defaultSegmentId);
    }

    public static AnalysisEngineDescription createAnnotatorDescription() throws ResourceInitializationException {

        return AnalysisEngineFactory.createPrimitiveDescription(SegmentRegexAnnotator.class,
                SegmentRegexAnnotator.PARAM_DEFAULT_SEGMENT, "DEFAULT");
    }
}