~vcs-imports/xena/trunk

« back to all changes in this revision

Viewing changes to ext/src/javahelp/jhMaster/JSearch/client/com/sun/java/help/search/RoleFiller.java

  • Committer: matthewoliver
  • Date: 2009-12-10 03:18:07 UTC
  • Revision ID: vcs-imports@canonical.com-20091210031807-l086qguzdlljtkl9
Merged Xena Testing into Xena Stable for the Xena 5 release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * @(#)RoleFiller.java  1.6 06/10/30
 
3
 * 
 
4
 * Copyright (c) 2006 Sun Microsystems, Inc.  All Rights Reserved.
 
5
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
6
 * 
 
7
 * This code is free software; you can redistribute it and/or modify it
 
8
 * under the terms of the GNU General Public License version 2 only, as
 
9
 * published by the Free Software Foundation.  Sun designates this
 
10
 * particular file as subject to the "Classpath" exception as provided
 
11
 * by Sun in the LICENSE file that accompanied this code.
 
12
 * 
 
13
 * This code is distributed in the hope that it will be useful, but WITHOUT
 
14
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
15
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
16
 * version 2 for more details (a copy is included in the LICENSE file that
 
17
 * accompanied this code).
 
18
 * 
 
19
 * You should have received a copy of the GNU General Public License version
 
20
 * 2 along with this work; if not, write to the Free Software Foundation,
 
21
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
22
 * 
 
23
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 
24
 * CA 95054 USA or visit www.sun.com if you need additional information or
 
25
 * have any questions.
 
26
 */
 
27
 
 
28
/**
 
29
 * @date   1/13/98
 
30
 * @author Jacek R. Ambroziak
 
31
 * @group  Sun Microsystems Laboratories
 
32
 */
 
33
 
 
34
package com.sun.java.help.search;
 
35
 
 
36
import java.io.PrintStream;
 
37
 
 
38
class RoleFiller
 
39
{
 
40
  static int Threshold = 300;
 
41
 
 
42
  private ConceptData _conceptData;
 
43
  private byte        _fixedRole;
 
44
  private short        _filled;
 
45
  private int        _begin;
 
46
  private int        _end;
 
47
  private int        _limit;
 
48
  private RoleFiller       _next;
 
49
  private RoleFiller[]     _fillers;
 
50
  
 
51
  public static final RoleFiller STOP = new RoleFiller();
 
52
  
 
53
  private RoleFiller() {}
 
54
 
 
55
  public RoleFiller(int nColumns, ConceptData first, int role,
 
56
                    int pos, int limit)
 
57
  {
 
58
    _conceptData = first;
 
59
    _fixedRole = (byte)role; // primary/constitutive concept/role
 
60
    _filled = (short)(1 << _fixedRole);
 
61
    _begin = pos;               // offset in file
 
62
    _end = _begin + first.getConceptLength();
 
63
    _limit = limit;
 
64
    _next = null;
 
65
    _fillers = new RoleFiller[nColumns];
 
66
    _fillers[role] = this;
 
67
  }
 
68
 
 
69
  public void print(PrintStream out) {
 
70
    out.println(_begin + ", " + _end);
 
71
  }
 
72
  
 
73
  void makeQueryHit(Query q, int nColumns, int doc, double penalty)
 
74
  {
 
75
    if (q.goodEnough(penalty))
 
76
      {
 
77
        int[] array =
 
78
          q.getConceptArrayOfNewHit(penalty,
 
79
                                    new Location(doc, _begin, _end));
 
80
        for (int i = 0; i < nColumns; i++)
 
81
          array[i] = (_filled & 1 << i) != 0 ? _fillers[i].getConcept() : 0;
 
82
      }
 
83
  }
 
84
 
 
85
  boolean isHit() {
 
86
    return _filled > (1 << _fixedRole);
 
87
  }
 
88
  
 
89
  double getScore() {
 
90
    return _conceptData.getScore();
 
91
  }
 
92
  
 
93
  int getConcept() {
 
94
    return _conceptData.getConcept();
 
95
  }
 
96
  
 
97
  RoleFiller next() {
 
98
    return _next;
 
99
  }
 
100
  
 
101
  void use(RoleFiller[] place, int index)
 
102
  {
 
103
    if (place[index] != null)
 
104
      {
 
105
        RoleFiller rf = place[index];
 
106
        place[index] = this;
 
107
        _next = rf;
 
108
        while (rf._limit >= _begin)
 
109
          {
 
110
            // check if we can grow/improve a hit
 
111
            // we don't ever replace filler's fixed role
 
112
            if (_fixedRole != rf._fixedRole)
 
113
              {
 
114
                if ((rf._filled & (1 << _fixedRole)) == 0) // not filled yet
 
115
                  {
 
116
                    rf._filled |= 1 << _fixedRole;
 
117
                    rf._fillers[_fixedRole] = this;
 
118
                    rf._end = _end;
 
119
                  }
 
120
                else
 
121
                  rf.considerReplacementWith(this);
 
122
              }
 
123
              
 
124
            if (rf._next != null)
 
125
              rf = rf._next;
 
126
            else
 
127
              return;
 
128
          }
 
129
      }
 
130
    else
 
131
      place[index] = this;
 
132
  }
 
133
  
 
134
  private void considerReplacementWith(RoleFiller replacement)
 
135
  {
 
136
    // !!! simplistic for now
 
137
    // needs gap and out of order
 
138
    int role = replacement._fixedRole;
 
139
    if (replacement.getScore() > _fillers[role].getScore())
 
140
      _fillers[role] = replacement;
 
141
  }
 
142
 
 
143
  private double penalty(Query query, int nColumns)
 
144
  {
 
145
    int length = _end - _begin + 1;
 
146
    double penalty = query.lookupPenalty(_filled);
 
147
    // !!! here is a chance to check against query if hit worth scoring further
 
148
    // might not be if query already has lots of good hits
 
149
    for (int i = 0; i < nColumns; i++)
 
150
      if ((_filled & (1 << i)) != 0)
 
151
        {
 
152
          penalty += _fillers[i]._conceptData.getPenalty();
 
153
          length -= _fillers[i]._conceptData.getConceptLength() + 1;
 
154
          if ((_filled >> (i + 1)) != 0)
 
155
            for (int j = i + 1; j < nColumns; j++)
 
156
              if ((_filled & 1 << j) != 0 && _fillers[j]._begin < _begin)
 
157
                penalty += query.getOutOufOrderPenalty();
 
158
        }
 
159
    return penalty + length*query.getGapPenalty();
 
160
  }
 
161
  
 
162
  public void scoreList(Query query, int document)
 
163
  {
 
164
    int nColumns = query.getNColumns();
 
165
    RoleFiller candidateHit = this; // function called for the head of list
 
166
    RoleFiller next;            // lookahead: if overlap, if so, is it better
 
167
 
 
168
    // 'candidateHit' always points at the current candidate to be converted to a QueryHit
 
169
    // 'penalty' is its penalty
 
170
    // 'next' is used to explore earlier overlapping fillers
 
171
    // the decision to emit a QueryHit is made when either there's no next
 
172
    // or next doesn't overlap the current candidate
 
173
    // the loop's logic makes sure that at emit time there's no better/earlier filler
 
174
    // to overlap with the candidate
 
175
 
 
176
    double penalty = candidateHit.penalty(query, nColumns);
 
177
  
 
178
    for (next = candidateHit._next; next != null; next = next._next)
 
179
      if (next._end < candidateHit._begin) // no overlap
 
180
        {
 
181
          candidateHit.makeQueryHit(query, nColumns, document, penalty);
 
182
          candidateHit = next;
 
183
          penalty = candidateHit.penalty(query, nColumns);
 
184
        }
 
185
      else
 
186
        {
 
187
          // !!! can be computed in two steps
 
188
          double penalty2 = next.penalty(query, nColumns);
 
189
          if (penalty2 <= penalty)      // prefer next, disregard candidateHit
 
190
            {
 
191
              penalty = penalty2;
 
192
              candidateHit = next;
 
193
            }
 
194
        }
 
195
    candidateHit.makeQueryHit(query, nColumns, document, penalty);
 
196
  }
 
197
 
 
198
}