001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.search.db;
007:
008: import com.sun.portal.search.soif.*;
009: import com.sun.portal.search.util.*;
010: import com.sun.portal.log.common.PortalLogger;
011:
012: import java.util.*;
013: import java.util.logging.Logger;
014: import java.util.logging.Level;
015: import java.util.logging.LogRecord;
016:
017: /**
018: * gV rating and comment handling
019: */
020: public class gVCollaborationPlugin {
021:
022: // XXX This should definitely be done by gV clients, and not here
023:
024: // XXX Nothing is using this yet - the only reason it works
025: // is because C rdsubmit is using the C gV api.
026:
027: // XXX all these need replacing/fixing
028: int rating_factor;
029: int which_pass;
030:
031: // Add option to determine which functions to call
032: static final int RDM_CSDB = 0x01; // Database
033: static final int RDM_SAGE = 0x02; // Verity indexer
034: static final int RDM_UNKNOWN = 0;
035:
036: /** Hide */
037: private gVCollaborationPlugin() {
038: }
039:
040: public SOIF store_read_rd(SToken st, IndexedSOIFDb cdbm,
041: String url, boolean is_persistent) throws Exception {
042: SOIF soif = null;
043: int pflags = is_persistent ? RDMDb.PONLY : RDMDb.NPONLY;
044: try {
045: soif = cdbm.fetch(st, url, pflags, null);
046: if (soif == null) {
047: if (SearchLogger.getLogger().isLoggable(Level.FINE)) {
048: String[] params = new String[2];
049: if (is_persistent)
050: params[0] = "persistent";
051: else
052: params[0] = "nonpersistent";
053: params[1] = url;
054: // log - not found {0} {1}
055: SearchLogger.getLogger().log(Level.FINE,
056: "PSSH_CSPSB0005", params);
057: }
058: }
059: return soif;
060: } catch (Exception e) {
061: if (SearchLogger.getLogger().isLoggable(Level.WARNING)) {
062: String[] params = new String[2];
063: if (is_persistent)
064: params[0] = "persistent";
065: else
066: params[0] = "nonpersistent";
067: params[1] = url;
068: LogRecord logRecord = new LogRecord(Level.WARNING,
069: "PSSH_CSPSB0005");
070: logRecord.setParameters(params);
071: logRecord.setThrown(e);
072: logRecord.setLoggerName(SearchLogger.getLogger()
073: .getName());
074: SearchLogger.getLogger().log(logRecord);
075: }
076: throw e;
077: }
078: }
079:
080: /**
081: * Merges an attr from 3 SOIFs into a unique CSList.
082: * The attr can be MV.
083: */
084: List merge_attrs(SOIF s1, SOIF s2, SOIF s3, String soifAttr) {
085: int loop, i;
086: String val = null;
087: SOIF holder = null;
088: List attr_list = new ArrayList();
089:
090: holder = s1;
091: loop = 1;
092: while (loop < 4) {
093: if (holder != null) {
094: for (i = 0;; i++) {
095: val = holder.getValue(soifAttr, i);
096: if (val == null)
097: break;
098: if (!attr_list.contains(val))
099: attr_list.add(val);
100: }
101: }
102: loop++;
103: if (loop == 2 && s2 != null) {
104: holder = s2;
105: } else if (loop <= 3) {
106: loop = 3;
107: holder = s3;
108: }
109: }
110: return attr_list;
111: }
112:
113: /**
114: * Handle gV comment or rating during update
115: * XXX THIS SHOULD NOT BE HERE - IT MUST BE MOVED TO GV SERVLETS/PLUGINS
116: */
117: void handle_gv(SToken st, IndexedSOIFDb cdbm, SOIF insoif)
118: throws Exception {
119: int rcode = 0;
120: SOIF pps = null;
121:
122: if (!insoif.contains("rd-discussion-id")
123: && insoif.contains("rd-reference-id")) {
124: // This could be a gV comment (a new RD, not a main comment though)
125: pps = handle_comment(st, cdbm, insoif);
126: if (pps != null) {
127: // Parent P needs to be updated
128: cdbm.store(st, pps, RDMDb.PONLY, null);
129: if ((which_pass & RDM_SAGE) == 0)
130: return;
131: if (!pps.contains(SOIFDb.NOREINDEX)) {
132: // XXX replace me... rdmgr.sage.processRD(s, false /*delete*/); // Reindex parent RD
133: }
134: }
135: } else if (insoif.contains("rd-rating")) {
136: // This could be a gV rating (of an existing RD)
137: handle_rating(st, cdbm, insoif, rating_factor);
138: }
139: return;
140: }
141:
142: /**
143: * Replaces the classification(s) of nps with the supplied class_list
144: */
145: void insert_classification_in_child(List class_list, SOIF nps,
146: String soifAttr) {
147: int counter, count;
148: String val = null;
149: boolean isMVAvp;
150: int loop = 0;
151: AVPair class_avp = null;
152:
153: /*
154: if (soifAttr == null) return -1;
155: if (nps == null) return -1;
156: if (class_list == null) return -1;
157: **/
158:
159: if (class_list.size() <= 0)
160: return;
161:
162: nps.remove(soifAttr); // remove old class list
163:
164: int i = 0;
165: for (Iterator it = class_list.iterator(); it.hasNext(); ++i) {
166: nps.insert(soifAttr, val, i);
167: }
168: } // insert-classification
169:
170: /**
171: * Called when we have a potential comment RD.
172: * A comment RD inherits its parent's classifications.
173: * Also adds the discussion-id attr to the parent RD if it was missing.
174: */
175: SOIF handle_comment(SToken st, IndexedSOIFDb cdbm, SOIF gvs)
176: throws Exception {
177: SOIFOutputStream output = null;
178: SOIF soif = null;
179: String attbr = null;
180: String parent_url = null;
181: SOIF pps = null, pns = null, class_s = null;
182: String p = null;
183: int count = 0;
184: List class_list = null, gvclass_list = null;
185: SOIF res = null;
186:
187: if ((parent_url = gvs.getValue("rd-reference-id")) != null
188: && !gvs.contains("rd-discussion-id")) {
189: /*
190: * This looks like a comment RD
191: * retrieve the parent soif (p and np) from the db
192: * returned objects must be freed later
193: */
194: pps = store_read_rd(st, cdbm, parent_url, true); // P - null if not in db
195: if (pps == null)
196: pps = new SOIF(gvs.getSchemaName(), parent_url);
197:
198: pns = store_read_rd(st, cdbm, parent_url, false); // NP
199:
200: if (pns != null) {
201:
202: // set up discussion-id
203: if ((p = pps.getValue("rd-discussion-id")) != null) {
204: /**
205: * If discussion attribute present in the parent RD
206: * insert it into the comment RD.
207: * This allows comments on comments where we don't
208: * know the real url.
209: */
210: gvs.insert("rd-discussion-id", p);
211: } else {
212: // if it is not present then put it in the parent and comment
213: pps.insert("rd-discussion-id", parent_url);
214: gvs.insert("rd-discussion-id", parent_url);
215: // parent was modified - submit and reindex it
216: res = pps;
217: }
218:
219: // set up comment depth
220: if ((p = pps.getValue("rd-depth")) != null) {
221: int d = Integer.parseInt(p);
222: gvs.insert("rd-depth", "" + (d + 1));
223: } else
224: gvs.insert("rd-depth", "1");
225:
226: // Copy classifications from the parent into the comment
227: // use p classes if present, else np classes
228: class_s = pps;
229: if (pns != null
230: && (class_s == null || !class_s
231: .contains("classification")))
232: class_s = pns;
233: class_list = merge_attrs(class_s, gvs, null,
234: "classification");
235: // replace the classification on the child
236: insert_classification_in_child(class_list, gvs,
237: "classification");
238:
239: // ditto for rd-classification
240: class_s = pps;
241: if (pns != null
242: && (class_s == null || class_s
243: .contains("rd-classification")))
244: class_s = pns;
245: gvclass_list = merge_attrs(class_s, gvs, null,
246: "rd-classification");
247: insert_classification_in_child(gvclass_list, gvs,
248: "rd-classification");
249:
250: } else {
251: /*
252: * parentless comments (ie, new discussions) are now accepted
253: * discussion id is the comment URL itself
254: * NB: The comment should use its own url (gvviewall as the ref-id)
255: */
256: gvs.insert("rd-discussion-id", gvs.getURL());
257: }
258:
259: }
260: return res;
261: } // handle_comment
262:
263: /**
264: * Determine if peak rating needs to be updated
265: */
266: void handle_rating(SToken st, IndexedSOIFDb cdbm, SOIF gvs,
267: int rating_factor) throws Exception {
268: long gv_num_rating_old = 0, gv_num_rating_new = 0;
269: long num_rating, sum_rating;
270: long gv_sum_rating_old = 0, gv_sum_rating_new = 0;
271: long gv_peak_rating_old = 0, gv_peak_rating_new = 0;
272: int gv_rating_old = 0, gv_rating_new = 0, irating;
273: float rating;
274: String p;
275: SOIF ops = null;
276:
277: // Is this a rating RD?...
278: p = gvs.getValue("rd-rating");
279: if (p != null)
280: gv_rating_new = Integer.parseInt(p);
281: else
282: return; // Not a rating after all
283:
284: // We must have something to rate
285: ops = store_read_rd(st, cdbm, gvs.getURL(), true); // P
286: if (ops == null)
287: return;
288:
289: p = gvs.getValue("rd-sum-rating");
290: if (p != null)
291: gv_sum_rating_new = Integer.parseInt(p);
292: else
293: gv_sum_rating_new = gv_rating_new;
294:
295: p = ops.getValue("rd-sum-rating");
296: if (p != null)
297: gv_sum_rating_old = Integer.parseInt(p);
298:
299: p = gvs.getValue("rd-num-rating");
300: if (p != null)
301: gv_num_rating_new = Integer.parseInt(p);
302: else
303: gv_num_rating_new = 1;
304:
305: p = ops.getValue("rd-num-rating");
306: if (p != null)
307: gv_num_rating_old = Integer.parseInt(p);
308:
309: p = ops.getValue("rd-peak-rating");
310: if (p != null)
311: gv_peak_rating_old = Integer.parseInt(p);
312:
313: num_rating = gv_num_rating_old + gv_num_rating_new;
314: sum_rating = gv_sum_rating_old + gv_sum_rating_new;
315: rating = (float) sum_rating
316: / (float) (num_rating + rating_factor);
317:
318: // round off the peak
319: if (rating > 3) {
320: rating = 3;
321: sum_rating = 3 * (num_rating + 1);
322: } else if (rating < -1) {
323: rating = -1;
324: sum_rating = -1 * (num_rating + 1);
325: }
326:
327: // round off the rating
328: if (rating < -0.5)
329: irating = -1;
330: else
331: irating = (int) (rating + 0.5);
332:
333: // find the new peak rating from the old peak and the new rating
334:
335: if (rating > gv_peak_rating_old)
336: gv_peak_rating_new = irating;
337: else
338: gv_peak_rating_new = gv_peak_rating_old;
339:
340: gvs.replace("rd-peak-rating", "" + gv_peak_rating_new);
341: gvs.replace("rd-num-rating", "" + num_rating);
342: gvs.replace("rd-sum-rating", "" + sum_rating);
343: gvs.replace("rd-rating", "" + irating);
344:
345: }
346:
347: }
|