private void entitySubclassify(List<CoreLabel> tokens,
                                 String style) {
    int how;
    if ("iob1".equalsIgnoreCase(style)) {
      how = 0;
    } else if ("iob2".equalsIgnoreCase(style)) {
      how = 1;
    } else if ("ioe1".equalsIgnoreCase(style)) {
      how = 2;
    } else if ("ioe2".equalsIgnoreCase(style)) {
      how = 3;
    } else if ("io".equalsIgnoreCase(style)) {
      how = 4;
    } else if ("sbieo".equalsIgnoreCase(style)) {
      how = 5;
    } else {
      System.err.println("entitySubclassify: unknown style: " + style);
      how = 4;
    }
    tokens = new PaddedList<CoreLabel>(tokens, new CoreLabel());
    int k = tokens.size();
    String[] newAnswers = new String[k];
    for (int i = 0; i < k; i++) {
      final CoreLabel c = tokens.get(i);
      final CoreLabel p = tokens.get(i - 1);
      final CoreLabel n = tokens.get(i + 1);
      final String cAns = c.get(AnswerAnnotation.class);
      if (cAns.length() > 1 && cAns.charAt(1) == '-') {
        String pAns = p.get(AnswerAnnotation.class);
        if (pAns == null) { pAns = OTHER; }
        String nAns = n.get(AnswerAnnotation.class);
        if (nAns == null) { nAns = OTHER; }
        final String base = cAns.substring(2, cAns.length());
        String pBase = (pAns.length() > 2 ? pAns.substring(2, pAns.length()) : pAns);
        String nBase = (nAns.length() > 2 ? nAns.substring(2, nAns.length()) : nAns);
        char prefix = cAns.charAt(0);
        char pPrefix = (pAns.length() > 0) ? pAns.charAt(0) : ' ';
        char nPrefix = (nAns.length() > 0) ? nAns.charAt(0) : ' ';
        boolean isStartAdjacentSame = base.equals(pBase) &&
          (prefix == 'B' || prefix == 'S' || pPrefix == 'E' || pPrefix == 'S');
        boolean isEndAdjacentSame = base.equals(nBase) &&
          (prefix == 'E' || prefix == 'S' || nPrefix == 'B' || pPrefix == 'S');
        boolean isFirst = (!base.equals(pBase)) || cAns.charAt(0) == 'B';
        boolean isLast = (!base.equals(nBase)) || nAns.charAt(0) == 'B';
        switch (how) {
        case 0:
          if (isStartAdjacentSame) {
            newAnswers[i] = intern("B-" + base);
          } else {
            newAnswers[i] = intern("I-" + base);
          }
          break;
        case 1:
          if (isFirst) {
            newAnswers[i] = intern("B-" + base);
          } else {
            newAnswers[i] = intern("I-" + base);
          }
          break;
        case 2:
          if (isEndAdjacentSame) {
            newAnswers[i] = intern("E-" + base);
          } else {
            newAnswers[i] = intern("I-" + base);
          }
          break;
        case 3:
          if (isLast) {
            newAnswers[i] = intern("E-" + base);
          } else {
            newAnswers[i] = intern("I-" + base);
          }
          break;
        case 4:
          newAnswers[i] = intern("I-" + base);
          break;
        case 5:
          if (isFirst && isLast) {
            newAnswers[i] = intern("S-" + base);
          } else if ((!isFirst) && isLast) {
            newAnswers[i] = intern("E-" + base);
          } else if (isFirst && (!isLast)) {
            newAnswers[i] = intern("B-" + base);
          } else {
            newAnswers[i] = intern("I-" + base);
          }
        }
      } else {
        newAnswers[i] = cAns;
      }
    }
    for (int i = 0; i < k; i++) {
      CoreLabel c = tokens.get(i);
      c.set(AnswerAnnotation.class, newAnswers[i]);
    }
  }
private void entitySubclassify ( List < CoreLabel > tokens , String style ) { int how ; if ( "iob1" . equalsIgnoreCase ( style ) ) { how = 0 ; } else if ( "iob2" . equalsIgnoreCase ( style ) ) { how = 1 ; } else if ( "ioe1" . equalsIgnoreCase ( style ) ) { how = 2 ; } else if ( "ioe2" . equalsIgnoreCase ( style ) ) { how = 3 ; } else if ( "io" . equalsIgnoreCase ( style ) ) { how = 4 ; } else if ( "sbieo" . equalsIgnoreCase ( style ) ) { how = 5 ; } else { System . err . println ( "entitySubclassify: unknown style: " + style ) ; how = 4 ; } tokens = new PaddedList < CoreLabel > ( tokens , new CoreLabel ( ) ) ; int k = tokens . size ( ) ; String [ ] newAnswers = new String [ k ] ; for ( int i = 0 ; i < k ; i ++ ) { final CoreLabel c = tokens . get ( i ) ; final CoreLabel p = tokens . get ( i - 1 ) ; final CoreLabel n = tokens . get ( i + 1 ) ; final String cAns = c . get ( AnswerAnnotation . class ) ; if ( cAns . length ( ) > 1 && cAns . charAt ( 1 ) == '-' ) { String pAns = p . get ( AnswerAnnotation . class ) ; if ( pAns == null ) { pAns = OTHER ; } String nAns = n . get ( AnswerAnnotation . class ) ; if ( nAns == null ) { nAns = OTHER ; } final String base = cAns . substring ( 2 , cAns . length ( ) ) ; String pBase = ( pAns . length ( ) > 2 ? pAns . substring ( 2 , pAns . length ( ) ) : pAns ) ; String nBase = ( nAns . length ( ) > 2 ? nAns . substring ( 2 , nAns . length ( ) ) : nAns ) ; char prefix = cAns . charAt ( 0 ) ; char pPrefix = ( pAns . length ( ) > 0 ) ? pAns . charAt ( 0 ) : ' ' ; char nPrefix = ( nAns . length ( ) > 0 ) ? nAns . charAt ( 0 ) : ' ' ; boolean isStartAdjacentSame = base . equals ( pBase ) && ( prefix == 'B' || prefix == 'S' || pPrefix == 'E' || pPrefix == 'S' ) ; boolean isEndAdjacentSame = base . equals ( nBase ) && ( prefix == 'E' || prefix == 'S' || nPrefix == 'B' || pPrefix == 'S' ) ; boolean isFirst = ( ! base . equals ( pBase ) ) || cAns . charAt ( 0 ) == 'B' ; boolean isLast = ( ! base . equals ( nBase ) ) || nAns . charAt ( 0 ) == 'B' ; switch ( how ) { case 0 : if ( isStartAdjacentSame ) { newAnswers [ i ] = intern ( "B-" + base ) ; } else { newAnswers [ i ] = intern ( "I-" + base ) ; } break ; case 1 : if ( isFirst ) { newAnswers [ i ] = intern ( "B-" + base ) ; } else { newAnswers [ i ] = intern ( "I-" + base ) ; } break ; case 2 : if ( isEndAdjacentSame ) { newAnswers [ i ] = intern ( "E-" + base ) ; } else { newAnswers [ i ] = intern ( "I-" + base ) ; } break ; case 3 : if ( isLast ) { newAnswers [ i ] = intern ( "E-" + base ) ; } else { newAnswers [ i ] = intern ( "I-" + base ) ; } break ; case 4 : newAnswers [ i ] = intern ( "I-" + base ) ; break ; case 5 : if ( isFirst && isLast ) { newAnswers [ i ] = intern ( "S-" + base ) ; } else if ( ( ! isFirst ) && isLast ) { newAnswers [ i ] = intern ( "E-" + base ) ; } else if ( isFirst && ( ! isLast ) ) { newAnswers [ i ] = intern ( "B-" + base ) ; } else { newAnswers [ i ] = intern ( "I-" + base ) ; } } } else { newAnswers [ i ] = cAns ; } } for ( int i = 0 ; i < k ; i ++ ) { CoreLabel c = tokens . get ( i ) ; c . set ( AnswerAnnotation . class , newAnswers [ i ] ) ; } }
This can be used on the CoNLL data to map from a representation where
normally entities were marked I-PERS, but the beginning of non-first
items of an entity sequences were marked B-PERS (IOB1 representation).
It changes this representation to other representations:
a 4 way representation of all entities, like S-PERS, B-PERS,
I-PERS, E-PERS for single word, beginning, internal, and end of entity
(SBIEO); always marking the first word of an entity (IOB2);
the reverse IOE1 and IOE2 and IO.
This code is very specific to the particular CoNLL way of labeling
classes.  It will work on any of these styles of input, however, except
for IO which necessarily loses information.

@param tokens List of read in tokens with AnswerAnnotation
@param style Output style; one of iob[12], ioe[12], io, sbieo