[Bedework-commit] r369 - in trunk/calendar3: bldfiles
calCore/src/org/bedework/calcore/hibernate
calFacade/src/org/bedework/calfacade
calFacade/src/org/bedework/calfacade/base
calFacade/src/org/bedework/calfacade/ifs
caldav/src/edu/rpi/cct/uwcal/caldav/calquery calsvc
calsvc/src/org/bedework/calsvc
calsvci/src/org/bedework/calsvci common
common/src/edu/rpi/cct common/src/edu/rpi/cct/misc
common/src/edu/rpi/cct/misc/indexing
common/src/edu/rpi/cct/uwcal lib
webclient/src/org/bedework/webclient webclient/war/docs
svnadmin at bedework.org
svnadmin at bedework.org
Thu Apr 13 09:35:11 EDT 2006
Author: douglm
Date: 2006-04-13 09:35:10 -0400 (Thu, 13 Apr 2006)
New Revision: 369
Added:
trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexKey.java
trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneDefs.java
trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneImpl.java
trunk/calendar3/common/src/edu/rpi/cct/misc/
trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/
trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/Index.java
trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexDummyImpl.java
trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexException.java
trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexLuceneImpl.java
trunk/calendar3/lib/lucene-core-1.9.1.jar
Removed:
trunk/calendar3/common/src/edu/rpi/cct/uwcal/common/
Modified:
trunk/calendar3/bldfiles/defjars.properties
trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/Calendars.java
trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/CalintfImpl.java
trunk/calendar3/calFacade/src/org/bedework/calfacade/BwFreeBusy.java
trunk/calendar3/calFacade/src/org/bedework/calfacade/base/CalintfBase.java
trunk/calendar3/calFacade/src/org/bedework/calfacade/ifs/CalendarsI.java
trunk/calendar3/caldav/src/edu/rpi/cct/uwcal/caldav/calquery/FreeBusyQuery.java
trunk/calendar3/calsvc/build.xml
trunk/calendar3/calsvc/src/org/bedework/calsvc/CalSvc.java
trunk/calendar3/calsvci/src/org/bedework/calsvci/CalSvcI.java
trunk/calendar3/common/build.xml
trunk/calendar3/webclient/src/org/bedework/webclient/BwFreeBusyAction.java
trunk/calendar3/webclient/war/docs/freeBusy.jsp
Log:
Code to support lucene indexing. Nothing being used yet but builds OK
Modified: trunk/calendar3/bldfiles/defjars.properties
===================================================================
--- trunk/calendar3/bldfiles/defjars.properties 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/bldfiles/defjars.properties 2006-04-13 13:35:10 UTC (rev 369)
@@ -61,6 +61,10 @@
ical4j.jar.name=ical4j-0.9.19-pre.jar
ical4j.jar=${org.bedework.default.lib}/${ical4j.jar.name}
+# lucene.jar Used for indexing and searching
+lucene.jar.name=lucene-core-1.9.1.jar
+lucene.jar=${org.bedework.default.lib}/${lucene.jar.name}
+
# regexp.jar Handles regular expressions
regexp.jar=${org.bedework.default.lib}/jakarta-regexp-1.3.jar
Modified: trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/Calendars.java
===================================================================
--- trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/Calendars.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/Calendars.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -221,10 +221,14 @@
}
public BwCalendar getCalendars() throws CalFacadeException {
+ return getCalendars(getUser());
+ }
+
+ public BwCalendar getCalendars(BwUser user) throws CalFacadeException {
HibSession sess = getSess();
sess.namedQuery("getCalendarByPath");
- sess.setString("path", userCalendarRootPath + "/" + getUser().getAccount());
+ sess.setString("path", userCalendarRootPath + "/" + user.getAccount());
sess.cacheableQuery();
BwCalendar cal = (BwCalendar)sess.getUnique();
Modified: trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/CalintfImpl.java
===================================================================
--- trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/CalintfImpl.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calCore/src/org/bedework/calcore/hibernate/CalintfImpl.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -816,6 +816,12 @@
return calendars.getCalendars();
}
+ public BwCalendar getCalendars(BwUser user) throws CalFacadeException {
+ checkOpen();
+
+ return calendars.getCalendars(user);
+ }
+
public Collection getCalendarCollections() throws CalFacadeException {
checkOpen();
Modified: trunk/calendar3/calFacade/src/org/bedework/calfacade/BwFreeBusy.java
===================================================================
--- trunk/calendar3/calFacade/src/org/bedework/calfacade/BwFreeBusy.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calFacade/src/org/bedework/calfacade/BwFreeBusy.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -71,7 +71,7 @@
private BwDateTime start;
private BwDateTime end;
- /** Collection of FreeBusyComponentVO
+ /** Collection of BwFreeBusyComponent
*/
private Collection times;
Modified: trunk/calendar3/calFacade/src/org/bedework/calfacade/base/CalintfBase.java
===================================================================
--- trunk/calendar3/calFacade/src/org/bedework/calfacade/base/CalintfBase.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calFacade/src/org/bedework/calfacade/base/CalintfBase.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -425,6 +425,10 @@
throw new CalFacadeUnimplementedException();
}
+ public BwCalendar getCalendars(BwUser user) throws CalFacadeException {
+ throw new CalFacadeUnimplementedException();
+ }
+
public Collection getCalendarCollections() throws CalFacadeException {
checkOpen();
Modified: trunk/calendar3/calFacade/src/org/bedework/calfacade/ifs/CalendarsI.java
===================================================================
--- trunk/calendar3/calFacade/src/org/bedework/calfacade/ifs/CalendarsI.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calFacade/src/org/bedework/calfacade/ifs/CalendarsI.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -1,3 +1,56 @@
+/*
+ Copyright (c) 2000-2005 University of Washington. All rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+
+ The above copyright notice and this permission notice appear in
+ all copies and supporting documentation;
+
+ The name, identifiers, and trademarks of the University of Washington
+ are not used in advertising or publicity without the express prior
+ written permission of the University of Washington;
+
+ Recipients acknowledge that this distribution is made available as a
+ research courtesy, "as is", potentially with defects, without
+ any obligation on the part of the University of Washington to
+ provide support, services, or repair;
+
+ THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR
+ IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ WASHINGTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING
+ NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* **********************************************************************
+ Copyright 2005 Rensselaer Polytechnic Institute. All worldwide rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+ The above copyright notice and this permission notice appear in all
+ copies and supporting documentation;
+
+ The name, identifiers, and trademarks of Rensselaer Polytechnic
+ Institute are not used in advertising or publicity without the
+ express prior written permission of Rensselaer Polytechnic Institute;
+
+ DISCLAIMER: The software is distributed" AS IS" without any express or
+ implied warranty, including but not limited to, any implied warranties
+ of merchantability or fitness for a particular purpose or any warrant)'
+ of non-infringement of any current or pending patent rights. The authors
+ of the software make no representations about the suitability of this
+ software for any particular purpose. The entire risk as to the quality
+ and performance of the software is with the user. Should the software
+ prove defective, the user assumes the cost of all necessary servicing,
+ repair or correction. In particular, neither Rensselaer Polytechnic
+ Institute, nor the authors of the software are liable for any indirect,
+ special, consequential, or incidental damages related to the software,
+ to the maximum extent the law permits.
+*/
package org.bedework.calfacade.ifs;
import org.bedework.calfacade.BwCalendar;
@@ -40,9 +93,17 @@
/** Returns calendars owned by the current user.
*
- * <p>For anonymous (public events) access, this method returns the same
- * as getPublicCalendars().
+ * <p>For authenticated, personal access this always returns the user
+ * entry in the /user calendar tree, e.g. for user smithj it would return
+ * an entry /user/smithj
*
+ * @return BwCalendar root with all children attached
+ * @throws CalFacadeException
+ */
+ public BwCalendar getCalendars() throws CalFacadeException;
+
+ /** Returns calendars owned by the given user.
+ *
* <p>For authenticated, personal access this always returns the user
* entry in the /user calendar tree, e.g. for user smithj it would return
* an entry smithj
@@ -50,7 +111,7 @@
* @return BwCalendar root with all children attached
* @throws CalFacadeException
*/
- public BwCalendar getCalendars() throws CalFacadeException;
+ public BwCalendar getCalendars(BwUser user) throws CalFacadeException;
/** Return a list of user calendars in which calendar objects can be
* placed by the current user.
Modified: trunk/calendar3/caldav/src/edu/rpi/cct/uwcal/caldav/calquery/FreeBusyQuery.java
===================================================================
--- trunk/calendar3/caldav/src/edu/rpi/cct/uwcal/caldav/calquery/FreeBusyQuery.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/caldav/src/edu/rpi/cct/uwcal/caldav/calquery/FreeBusyQuery.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -146,7 +146,8 @@
try {
BwFreeBusy fb = svci.getFreeBusy(null, new BwUser(user),
- tr.getStart(), tr.getEnd(), null);
+ tr.getStart(), tr.getEnd(), null,
+ false);
if (debug) {
trace("Got " + fb);
Modified: trunk/calendar3/calsvc/build.xml
===================================================================
--- trunk/calendar3/calsvc/build.xml 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calsvc/build.xml 2006-04-13 13:35:10 UTC (rev 369)
@@ -30,6 +30,7 @@
<path id="compile.classpath">
<pathelement location="${ical4j.jar}"/>
<pathelement location="${log4j.jar}"/>
+ <pathelement location="${lucene.jar}"/>
<pathelement location="${org.bedework.calsvci.jar}"/>
<pathelement location="${org.bedework.calcore.jar}"/>
<pathelement location="${org.bedework.common.jar}"/>
Added: trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexKey.java
===================================================================
--- trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexKey.java (rev 0)
+++ trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexKey.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,394 @@
+/*
+ Copyright (c) 2000-2005 University of Washington. All rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+
+ The above copyright notice and this permission notice appear in
+ all copies and supporting documentation;
+
+ The name, identifiers, and trademarks of the University of Washington
+ are not used in advertising or publicity without the express prior
+ written permission of the University of Washington;
+
+ Recipients acknowledge that this distribution is made available as a
+ research courtesy, "as is", potentially with defects, without
+ any obligation on the part of the University of Washington to
+ provide support, services, or repair;
+
+ THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR
+ IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ WASHINGTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING
+ NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* **********************************************************************
+ Copyright 2005 Rensselaer Polytechnic Institute. All worldwide rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+ The above copyright notice and this permission notice appear in all
+ copies and supporting documentation;
+
+ The name, identifiers, and trademarks of Rensselaer Polytechnic
+ Institute are not used in advertising or publicity without the
+ express prior written permission of Rensselaer Polytechnic Institute;
+
+ DISCLAIMER: The software is distributed" AS IS" without any express or
+ implied warranty, including but not limited to, any implied warranties
+ of merchantability or fitness for a particular purpose or any warrant)'
+ of non-infringement of any current or pending patent rights. The authors
+ of the software make no representations about the suitability of this
+ software for any particular purpose. The entire risk as to the quality
+ and performance of the software is with the user. Should the software
+ prove defective, the user assumes the cost of all necessary servicing,
+ repair or correction. In particular, neither Rensselaer Polytechnic
+ Institute, nor the authors of the software are liable for any indirect,
+ special, consequential, or incidental damages related to the software,
+ to the maximum extent the law permits.
+*/
+package org.bedework.calsvc;
+
+import org.bedework.calfacade.BwCalendar;
+import org.bedework.calfacade.CalFacadeDefs;
+import org.bedework.calsvci.CalSvcI;
+
+import edu.rpi.cct.misc.indexing.Index;
+import edu.rpi.cct.misc.indexing.IndexException;
+
+import java.io.CharArrayWriter;
+import java.util.Collection;
+
+/**
+ * @author Mike Douglass douglm @ rpi.edu
+ *
+ */
+public class BwIndexKey extends Index.Key {
+ private CalSvcI svci;
+
+ private String key1; // calendar:path
+ private String key2; // event:guid
+ private String key3; // event:recurrenceid
+
+ /** An event key is stored as a concatenated set of Strings,
+ * calendar:path + guid + (recurrenceid | null).
+ *
+ * <p>We set it here and use the decode methods to split it up.
+ */
+ private char[] encoded;
+
+ private String itemType;
+
+ public BwIndexKey() {
+ }
+
+ public BwIndexKey(CalSvcI svci) {
+ this.svci = svci;
+ }
+
+ public BwIndexKey(CalSvcI svci, float score) {
+ this.score = score;
+ this.svci = svci;
+ }
+
+ public void setItemType(String val) {
+ itemType = val;
+ }
+
+ public void setScore(float val) {
+ score = val;
+ }
+
+ public void setCalendarKey(String key1) {
+ this.key1 = key1;
+ }
+
+ public void setEventKey(String key) throws IndexException {
+ encoded = key.toCharArray();
+ pos = 0;
+
+ this.key1 = getKeyString();
+ this.key2 = getKeyString();
+ this.key3 = getKeyString();
+ }
+
+ public String makeEventKey(String key1, String key2,
+ String key3) throws IndexException {
+ startEncoding();
+ encodeString(key1);
+ encodeString(key2);
+ encodeString(key3);
+
+ return getEncodedKey();
+ }
+
+ public Object getRecord() throws IndexException {
+ try {
+ if (itemType == null) {
+ throw new IndexException("org.bedework.index.nullkeyitemtype");
+ }
+
+ if (itemType.equals(BwIndexLuceneDefs.itemTypeCalendar)) {
+ return svci.getCalendar(key1);
+ }
+
+ if (itemType.equals(BwIndexLuceneDefs.itemTypeEvent)) {
+ BwCalendar cal = svci.getCalendar(key1);
+ if (cal == null) {
+ return null;
+ }
+ Collection eis = svci.getEvent(null, cal, key2, key3,
+ CalFacadeDefs.retrieveRecurExpanded);
+ if ((eis == null) || (eis.size() == 0)) {
+ return null;
+ }
+
+ return eis.iterator().next();
+ }
+
+ throw new IndexException(IndexException.unknownRecordType,
+ itemType);
+ } catch (IndexException ie) {
+ throw ie;
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /* ====================================================================
+ * Key decoding methods
+ * ==================================================================== */
+
+ /** Current position in the key */
+ private int pos;
+
+ /** When encoding a key we build it here.
+ */
+ private CharArrayWriter caw;
+
+ /** Get next char from encoded value. Return < 0 for no more
+ *
+ * @return char value
+ */
+ public char getChar() {
+ if ((encoded == null) || (pos == encoded.length)) {
+ return (char)-1;
+ }
+
+ char c = encoded[pos];
+ pos++;
+
+ return c;
+ }
+
+ /** Back off one char
+ *
+ * @throws AccessException
+ */
+ public void back() throws IndexException {
+ back(1);
+ }
+
+ /** Back off n chars
+ *
+ * @param n int number of chars
+ * @throws AccessException
+ */
+ public void back(int n) throws IndexException {
+ if (pos - n < 0) {
+ throw new IndexException("org.bedework.index.badKeyRewind");
+ }
+
+ pos -= n;
+ }
+
+ /** Get current position
+ *
+ * @return int position
+ */
+ public int getPos() {
+ return pos;
+ }
+
+ /** Set current position
+ *
+ * @param val int position
+ */
+ public void setPos(int val) {
+ pos = val;
+ }
+
+ /** Get number of chars remaining
+ *
+ * @return int number of chars remaining
+ */
+ public int remaining() {
+ if (encoded == null) {
+ return 0;
+ }
+ return encoded.length - pos;
+ }
+
+ /** Test for more
+ *
+ * @return boolean true for more
+ */
+ public boolean hasMore() {
+ return remaining() > 0;
+ }
+
+ /** Test for no more
+ *
+ * @return boolean true for no more
+ */
+ public boolean empty() {
+ return (encoded == null) || (encoded.length == 0);
+ }
+
+ /** Rewind to the start
+ */
+ public void rewind() {
+ pos = 0;
+ }
+
+ /** Return the value of a blank terminated length. On success current pos
+ * has been incremented.
+ *
+ * @return int length
+ * @throws AccessException
+ */
+ public int getLength() throws IndexException {
+ int res = 0;
+
+ for (;;) {
+ char c = getChar();
+ if (c == ' ') {
+ break;
+ }
+
+ if (c < 0) {
+ throw new IndexException("org.bedework.index.badKeyLength");
+ }
+
+ if ((c < '0') || (c > '9')) {
+ throw new IndexException("org.bedework.index.badkeychar");
+ }
+
+ res = res * 10 + Character.digit(c, 10);
+ }
+
+ return res;
+ }
+
+ /** Get a String from the encoded acl at the current position.
+ *
+ * @return String decoded String value
+ * @throws AccessException
+ */
+ public String getKeyString() throws IndexException {
+ if (getChar() == 'N') {
+ return null;
+ }
+ back();
+ int len = getLength();
+
+ if ((encoded.length - pos) < len) {
+ throw new IndexException("org.bedework.index.badKeyLength");
+ }
+
+ String s = new String(encoded, pos, len);
+ pos += len;
+
+ return s;
+ }
+
+ /** Skip a String from the encoded acl at the current position.
+ *
+ * @throws AccessException
+ */
+ public void skipString() throws IndexException {
+ if (getChar() == 'N') {
+ return;
+ }
+
+ back();
+ int len = getLength();
+ pos += len;
+ }
+
+ /* ====================================================================
+ * Encoding methods
+ * ==================================================================== */
+
+ /** Get ready to encode
+ *
+ */
+ public void startEncoding() {
+ caw = new CharArrayWriter();
+ }
+
+ /** Encode a blank terminated 0 prefixed length.
+ *
+ * @param len
+ * @throws AccessException
+ */
+ public void encodeLength(int len) throws IndexException {
+ try {
+ String slen = String.valueOf(len);
+ caw.write('0');
+ caw.write(slen, 0, slen.length());
+ caw.write(' ');
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Encode a String with length prefix. String is encoded as <ul>
+ * <li>One byte 'N' for null string or</li>
+ * <li>length {@link #encodeLength(int)} followed by</li>
+ * <li>String value.</li>
+ * </ul>
+ *
+ * @param val
+ * @throws AccessException
+ */
+ public void encodeString(String val) throws IndexException {
+ try {
+ if (val == null) {
+ caw.write('N'); // flag null
+ } else {
+ encodeLength(val.length());
+ caw.write(val, 0, val.length());
+ }
+ } catch (IndexException ie) {
+ throw ie;
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Add a character
+ *
+ * @param c char
+ * @throws AccessException
+ */
+ public void addChar(char c) throws IndexException {
+ try {
+ caw.write(c);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Get the current encoed value
+ *
+ * @return char[] encoded value
+ */
+ public String getEncodedKey() {
+ return new String(caw.toCharArray());
+ }
+}
Added: trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneDefs.java
===================================================================
--- trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneDefs.java (rev 0)
+++ trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneDefs.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,152 @@
+/*
+ Copyright (c) 2000-2005 University of Washington. All rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+
+ The above copyright notice and this permission notice appear in
+ all copies and supporting documentation;
+
+ The name, identifiers, and trademarks of the University of Washington
+ are not used in advertising or publicity without the express prior
+ written permission of the University of Washington;
+
+ Recipients acknowledge that this distribution is made available as a
+ research courtesy, "as is", potentially with defects, without
+ any obligation on the part of the University of Washington to
+ provide support, services, or repair;
+
+ THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR
+ IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ WASHINGTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING
+ NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* **********************************************************************
+ Copyright 2005 Rensselaer Polytechnic Institute. All worldwide rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+ The above copyright notice and this permission notice appear in all
+ copies and supporting documentation;
+
+ The name, identifiers, and trademarks of Rensselaer Polytechnic
+ Institute are not used in advertising or publicity without the
+ express prior written permission of Rensselaer Polytechnic Institute;
+
+ DISCLAIMER: The software is distributed" AS IS" without any express or
+ implied warranty, including but not limited to, any implied warranties
+ of merchantability or fitness for a particular purpose or any warrant)'
+ of non-infringement of any current or pending patent rights. The authors
+ of the software make no representations about the suitability of this
+ software for any particular purpose. The entire risk as to the quality
+ and performance of the software is with the user. Should the software
+ prove defective, the user assumes the cost of all necessary servicing,
+ repair or correction. In particular, neither Rensselaer Polytechnic
+ Institute, nor the authors of the software are liable for any indirect,
+ special, consequential, or incidental damages related to the software,
+ to the maximum extent the law permits.
+*/
+
+package org.bedework.calsvc;
+
+/** Haven't yet figured out how we'll internationalize queries. I think internal
+ * lucene field names will have to be fixed and defined below and front end
+ * implementors will need to provide a mapping.
+ *
+ * <p>We can possibly provide a subsclass of the parser to take a mapping table
+ * of allowable external names to internal names.
+ *
+ * <p>In any case, this class defines the names of all the fields we index.
+ *
+ * @author Mike Douglass douglm @ rpi.edu
+ *
+ */
+public class BwIndexLuceneDefs {
+ private BwIndexLuceneDefs() {
+ // There'll be no instantiation here
+ }
+
+ /* ---------------------------- Calendar fields ------------------------- */
+
+ /** */
+ public static final String calendarDescription = "calendarDescription";
+
+ /** Key field for a calendar */
+ public static final String calendarPath = "calendarPath";
+
+ /** */
+ public static final String calendarSummary = "calendarSummary";
+
+ /* ---------------------------- Event fields ------------------------- */
+
+ /** */
+ public static final String eventCategory = "eventCategory";
+
+ /** */
+ public static final String eventDescription = "eventDescription";
+
+ /** */
+ public static final String eventEnd = "eventEnd";
+
+ /** */
+ public static final String eventLocation = "eventLocation";
+
+ /** */
+ public static final String eventStart = "eventStart";
+
+ /** */
+ public static final String eventSummary = "eventSummary";
+
+ /** */
+ public static final String defaultFieldName = "default";
+
+ /* Field names for fields which contain item type and key information.
+ */
+
+ /** Field name defining type of item */
+ public static final String itemTypeName = "itemType";
+
+ /** */
+ public static final String[] termNames = {
+ itemTypeName,
+
+ // ----------------- Calendar
+ calendarDescription,
+ calendarSummary,
+
+ // ----------------- Event
+ eventCategory,
+ eventDescription,
+ eventLocation,
+ eventSummary,
+ };
+
+ /**
+ * @return String[]
+ */
+ public static String[] getTermNames() {
+ return termNames;
+ }
+
+ /* Item types. We index various item types and these strings define each
+ * type.
+ */
+
+ /** */
+ public static final String itemTypeCalendar = "calendar";
+
+ /** */
+ public static final String itemTypeEvent = "event";
+
+ /** Key field for calendar */
+ public static final String keyCalendar = "calendarPath";
+
+ /** Key for an event */
+ public static final String keyEvent = "eventKey";
+
+}
Added: trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneImpl.java
===================================================================
--- trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneImpl.java (rev 0)
+++ trunk/calendar3/calsvc/src/org/bedework/calsvc/BwIndexLuceneImpl.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,238 @@
+/*
+ Copyright (c) 2000-2005 University of Washington. All rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+
+ The above copyright notice and this permission notice appear in
+ all copies and supporting documentation;
+
+ The name, identifiers, and trademarks of the University of Washington
+ are not used in advertising or publicity without the express prior
+ written permission of the University of Washington;
+
+ Recipients acknowledge that this distribution is made available as a
+ research courtesy, "as is", potentially with defects, without
+ any obligation on the part of the University of Washington to
+ provide support, services, or repair;
+
+ THE UNIVERSITY OF WASHINGTON DISCLAIMS ALL WARRANTIES, EXPRESS OR
+ IMPLIED, WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT LIMITATION
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
+ WASHINGTON BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ PROFITS, WHETHER IN AN ACTION OF CONTRACT, TORT (INCLUDING
+ NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF OR IN CONNECTION WITH
+ THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/* **********************************************************************
+ Copyright 2005 Rensselaer Polytechnic Institute. All worldwide rights reserved.
+
+ Redistribution and use of this distribution in source and binary forms,
+ with or without modification, are permitted provided that:
+ The above copyright notice and this permission notice appear in all
+ copies and supporting documentation;
+
+ The name, identifiers, and trademarks of Rensselaer Polytechnic
+ Institute are not used in advertising or publicity without the
+ express prior written permission of Rensselaer Polytechnic Institute;
+
+ DISCLAIMER: The software is distributed" AS IS" without any express or
+ implied warranty, including but not limited to, any implied warranties
+ of merchantability or fitness for a particular purpose or any warrant)'
+ of non-infringement of any current or pending patent rights. The authors
+ of the software make no representations about the suitability of this
+ software for any particular purpose. The entire risk as to the quality
+ and performance of the software is with the user. Should the software
+ prove defective, the user assumes the cost of all necessary servicing,
+ repair or correction. In particular, neither Rensselaer Polytechnic
+ Institute, nor the authors of the software are liable for any indirect,
+ special, consequential, or incidental damages related to the software,
+ to the maximum extent the law permits.
+*/
+package org.bedework.calsvc;
+
+import org.bedework.calfacade.BwCalendar;
+import org.bedework.calfacade.BwCategory;
+import org.bedework.calfacade.BwEvent;
+import org.bedework.calfacade.BwLocation;
+import org.bedework.calsvci.CalSvcI;
+
+import edu.rpi.cct.misc.indexing.Index;
+import edu.rpi.cct.misc.indexing.IndexException;
+import edu.rpi.cct.misc.indexing.IndexLuceneImpl;
+
+import java.util.Iterator;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.Term;
+
+/**
+ * @author Mike Douglass douglm @ rpi.edu
+ *
+ */
+public class BwIndexLuceneImpl extends IndexLuceneImpl {
+ private CalSvcI svci;
+ private BwIndexKey keyConverter = new BwIndexKey();
+
+ public BwIndexLuceneImpl(CalSvcI svci,
+ String sysfilePath,
+ boolean admin,
+ boolean debug) throws IndexException {
+ super(sysfilePath,
+ BwIndexLuceneDefs.defaultFieldName,
+ admin, debug);
+ this.svci = svci;
+ }
+
+ /** Called to make or fill in a Key object.
+ *
+ * @param key Possible Index.Key object for reuse
+ * @param doc The retrieved Document
+ * @param score The rating for this entry
+ * @return Index.Key new or reused object
+ */
+ public Index.Key makeKey(Index.Key key,
+ Document doc,
+ float score) throws IndexException {
+ if ((key == null) || (!(key instanceof BwIndexKey))) {
+ key = new BwIndexKey(svci);
+ }
+
+ BwIndexKey bwkey = (BwIndexKey)key;
+
+ bwkey.setScore(score);
+
+ String itemType = doc.get(BwIndexLuceneDefs.itemTypeName);
+ bwkey.setItemType(itemType);
+
+ if (itemType == null) {
+ throw new IndexException("org.bedework.index.noitemtype");
+ }
+
+ if (itemType.equals(BwIndexLuceneDefs.itemTypeCalendar)) {
+ bwkey.setCalendarKey(doc.get(BwIndexLuceneDefs.keyCalendar));
+ } else if (itemType.equals(BwIndexLuceneDefs.itemTypeEvent)) {
+ bwkey.setEventKey(doc.get(BwIndexLuceneDefs.keyEvent));
+ } else {
+ throw new IndexException(IndexException.unknownRecordType,
+ itemType);
+ }
+
+ return key;
+ }
+
+ /** Called to make a key term for a record.
+ *
+ * @param rec The record
+ * @return Term Lucene term which uniquely identifies the record
+ */
+ public Term makeKeyTerm(Object rec) throws IndexException {
+ String name = makeKeyName(rec);
+ String key = makeKeyVal(rec);
+
+ return new Term(name, key);
+ }
+
+ /** Called to make a key value for a record.
+ *
+ * @param rec The record
+ * @return String String which uniquely identifies the record
+ */
+ public String makeKeyVal(Object rec) throws IndexException {
+ if (rec instanceof BwCalendar) {
+ return ((BwCalendar)rec).getPath();
+ }
+
+ if (rec instanceof BwEvent) {
+ BwEvent ev = (BwEvent)rec;
+
+ String path = ev.getCalendar().getPath();
+ String guid = ev.getGuid();
+ String recurid = null;
+ if (ev.getRecurrence() != null) {
+ recurid = ev.getRecurrence().getRecurrenceId();
+ }
+
+ return keyConverter.makeEventKey(path, guid, recurid);
+ }
+
+ throw new IndexException(IndexException.unknownRecordType,
+ rec.getClass().getName());
+ }
+
+ /** Called to make the primary key name for a record.
+ *
+ * @param rec The record
+ * @return String Name for the field/term
+ */
+ public String makeKeyName(Object rec) throws IndexException {
+ if (rec instanceof BwCalendar) {
+ return BwIndexLuceneDefs.keyCalendar;
+ }
+
+ if (rec instanceof BwEvent) {
+ return BwIndexLuceneDefs.keyEvent;
+ }
+
+ throw new IndexException(IndexException.unknownRecordType,
+ rec.getClass().getName());
+ }
+
+ /** Called to fill in a Document from an object.
+ *
+ * @param doc The Document
+ * @param o Object to be indexed
+ */
+ public void addFields(Document doc,
+ Object o) throws IndexException {
+ if (o == null) {
+ System.out.println("Tried to index null record");
+ return;
+ }
+
+ if (o instanceof BwCalendar) {
+ BwCalendar cal = (BwCalendar)o;
+
+ addString(doc, BwIndexLuceneDefs.calendarPath, cal.getPath());
+ addLongString(doc, BwIndexLuceneDefs.calendarDescription, cal.getDescription());
+ addString(doc, BwIndexLuceneDefs.calendarSummary, cal.getSummary());
+ } else if (o instanceof BwEvent) {
+ BwEvent ev = (BwEvent)o;
+
+ addString(doc, BwIndexLuceneDefs.keyEvent, makeKeyVal(ev));
+
+ addLongString(doc, BwIndexLuceneDefs.eventDescription, ev.getDescription());
+ addString(doc, BwIndexLuceneDefs.eventSummary, ev.getSummary());
+
+ addUntokenized(doc, BwIndexLuceneDefs.eventStart, ev.getDtstart().getDtval());
+ addUntokenized(doc, BwIndexLuceneDefs.eventStart, ev.getDtend().getDtval());
+
+ BwLocation loc = ev.getLocation();
+ if (loc != null) {
+ addString(doc, BwIndexLuceneDefs.eventLocation, loc.getAddress());
+ addString(doc, BwIndexLuceneDefs.eventLocation, loc.getSubaddress());
+ }
+
+ Iterator it = ev.iterateCategories();
+ while (it.hasNext()) {
+ BwCategory cat = (BwCategory)it.next();
+
+ addString(doc, BwIndexLuceneDefs.eventCategory, cat.getWord());
+ addString(doc, BwIndexLuceneDefs.eventCategory, cat.getDescription());
+ }
+ } else {
+ throw new IndexException(IndexException.unknownRecordType,
+ o.getClass().getName());
+ }
+ }
+
+ /** Called to return an array of valid term names.
+ *
+ * @return String[] term names
+ */
+ public String[] getTermNames() {
+ return BwIndexLuceneDefs.getTermNames();
+ }
+}
Modified: trunk/calendar3/calsvc/src/org/bedework/calsvc/CalSvc.java
===================================================================
--- trunk/calendar3/calsvc/src/org/bedework/calsvc/CalSvc.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calsvc/src/org/bedework/calsvc/CalSvc.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -99,6 +99,7 @@
import org.bedework.icalendar.URIgen;
//import org.bedework.mail.MailerIntf;
+import edu.rpi.cct.misc.indexing.Index;
import edu.rpi.cct.uwcal.access.PrivilegeDefs;
import edu.rpi.cct.uwcal.access.Acl.CurrentAccess;
import edu.rpi.cct.uwcal.resources.Resources;
@@ -127,6 +128,8 @@
public class CalSvc extends CalSvcI {
private CalSvcIPars pars;
+ private Index indexer;
+
private boolean debug;
private boolean open;
@@ -1014,21 +1017,19 @@
public BwFreeBusy getFreeBusy(BwCalendar cal, BwPrincipal who,
BwDateTime start, BwDateTime end,
- BwDuration granularity)
+ BwDuration granularity,
+ boolean returnAll)
throws CalFacadeException {
if (!(who instanceof BwUser)) {
throw new CalFacadeException("Unsupported: non user principal for free-busy");
}
- if (isGuest() || (!currentUser().equals(who))) {
- // No access for the moment
- throw new CalFacadeAccessException();
- }
-
BwUser u = (BwUser)who;
Collection subs;
if (cal != null) {
+ getCal().checkAccess(cal, PrivilegeDefs.privReadFreeBusy, false);
+
BwSubscription sub = BwSubscription.makeSubscription(cal);
subs = new ArrayList();
@@ -1036,6 +1037,9 @@
} else if (currentUser().equals(who)) {
subs = getSubscriptions();
} else {
+ getCal().checkAccess(getCal().getCalendars(u),
+ PrivilegeDefs.privReadFreeBusy, false);
+
subs = dbi.fetchPreferences(u).getSubscriptions();
}
@@ -1079,15 +1083,19 @@
gpp.dur = granularity;
gpp.tzcache = getTimezones();
- /* For the moment just build a single BwFreeBusyComponent
- */
- BwFreeBusyComponent fbc = new BwFreeBusyComponent();
+ BwFreeBusyComponent fbc = null;
+ if (!returnAll) {
+ // One component
+ fbc = new BwFreeBusyComponent();
+ fb.addTime(fbc);
+ }
+
int limit = 10000; // XXX do this better
while (gpp.startDt.before(end)) {
- if (debug) {
- trace("gpp.startDt=" + gpp.startDt + " end=" + end);
- }
+ //if (debug) {
+ // trace("gpp.startDt=" + gpp.startDt + " end=" + end);
+ //}
if (limit < 0) {
throw new CalFacadeException("org.bedework.svci.limit.exceeded");
}
@@ -1095,14 +1103,21 @@
Collection periodEvents = CalFacadeUtil.getPeriodsEvents(gpp);
- if (periodEvents.size() != 0) {
+ if (returnAll) {
+ fbc = new BwFreeBusyComponent();
+ fb.addTime(fbc);
+ fbc.addPeriod(new Period(new DateTime(gpp.startDt.getDtval()),
+ new DateTime(gpp.endDt.getDtval())));
+ if (periodEvents.size() == 0) {
+ fbc.setType(BwFreeBusyComponent.typeFree);
+ }
+ } else if (periodEvents.size() != 0) {
// Some events fall in the period. Add an entry.
fbc.addPeriod(new Period(new DateTime(gpp.startDt.getDtval()),
new DateTime(gpp.endDt.getDtval())));
}
}
- fb.addTime(fbc);
return fb;
}
@@ -2373,6 +2388,70 @@
}
}
+ /* ====================================================================
+ * Private indexing methods
+ * ==================================================================== */
+
+ private Index getIndexer() throws CalFacadeException {
+ try {
+ if (indexer == null) {
+ indexer = new BwIndexLuceneImpl(this,
+ // XXX Schema change - in syspars
+ "/temp/bedeworkindex",
+ isPublicAdmin(),
+ debug);
+ }
+
+ return indexer;
+ } catch (Throwable t) {
+ throw new CalFacadeException(t);
+ }
+ }
+
+ /* Call to (re)index an event
+ */
+ private void indexEvent(BwEvent ev) throws CalFacadeException {
+ try {
+ getIndexer().indexRec(ev);
+ } catch (Throwable t) {
+ throw new CalFacadeException(t);
+ }
+ }
+
+ private void unindexEvent(BwEvent ev) throws CalFacadeException {
+ try {
+ getIndexer().unindexRec(ev);
+ } catch (Throwable t) {
+ throw new CalFacadeException(t);
+ }
+ }
+
+ /* Call to (re)index a calendar
+ */
+ private void indexCalendar(BwCalendar cal) throws CalFacadeException {
+ try {
+ getIndexer().indexRec(cal);
+ } catch (Throwable t) {
+ throw new CalFacadeException(t);
+ }
+ }
+
+ private void unindexCalendar(BwCalendar cal) throws CalFacadeException {
+ try {
+ getIndexer().unindexRec(cal);
+
+ // And all the children
+ Iterator it = cal.iterateChildren();
+ while (it.hasNext()) {
+ BwCalendar ch = (BwCalendar)it.next();
+
+ unindexCalendar(ch);
+ }
+ } catch (Throwable t) {
+ throw new CalFacadeException(t);
+ }
+ }
+
/* Get a logger for messages
*/
private Logger getLogger() {
Modified: trunk/calendar3/calsvci/src/org/bedework/calsvci/CalSvcI.java
===================================================================
--- trunk/calendar3/calsvci/src/org/bedework/calsvci/CalSvcI.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/calsvci/src/org/bedework/calsvci/CalSvcI.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -809,12 +809,15 @@
* @param granularity BwDuration object defining how to divide free/busy
* null for one big glob. or set to e.g. 1 hour for
* hourly chunks.
+ * @param returnAll if true return entries for free time otherwise just for busy
+ * (only for granularity not null)
* @return BwFreeBusy
* @throws CalFacadeException
*/
public abstract BwFreeBusy getFreeBusy(BwCalendar cal, BwPrincipal who,
BwDateTime start, BwDateTime end,
- BwDuration granularity)
+ BwDuration granularity,
+ boolean returnAll)
throws CalFacadeException;
/* ====================================================================
Modified: trunk/calendar3/common/build.xml
===================================================================
--- trunk/calendar3/common/build.xml 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/common/build.xml 2006-04-13 13:35:10 UTC (rev 369)
@@ -16,13 +16,11 @@
<!-- ==================== Sources and classes ====================== -->
<fileset id="base.java.sources" dir="${source.home}" >
- <include name="edu/rpi/sss/util/**/*.java"/>
- <include name="edu/rpi/cct/uwcal/**/*.java"/>
+ <include name="edu/rpi/**/*.java"/>
</fileset>
<patternset id="base.class.patternset">
- <include name="edu/rpi/sss/util/**/*.class"/>
- <include name="edu/rpi/cct/uwcal/**/*.class"/>
+ <include name="edu/rpi/**/*.class"/>
</patternset>
<!-- ==================== Compilation Classpath ==================== -->
@@ -33,7 +31,8 @@
<pathelement location="${fop.jar}"/>
<pathelement location="${avalon.jar}"/>
<pathelement location="${log4j.jar}"/>
- <pathelement location="${logkit.jar}"/>
+ <pathelement location="${log4j.jar}"/>
+ <pathelement location="${lucene.jar}"/>
<pathelement location="${jtidy.jar}"/>
</path>
Added: trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/Index.java
===================================================================
--- trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/Index.java (rev 0)
+++ trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/Index.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,119 @@
+package edu.rpi.cct.misc.indexing;
+
+import java.io.Serializable;
+
+/** This interface describes how we build and search indexes for
+ * applications such as Luwak, forum systems etc.
+ */
+public interface Index extends Serializable {
+ public void setDebug(boolean val);
+
+ /** This might need to be called to open the index in the appropriate manner
+ * probably determined by information passed to the constructor.
+ */
+ public void open() throws IndexException;
+
+ /** This can be called to (re)create the index. It will destroy any
+ * previously existing index.
+ */
+ public void create() throws IndexException;
+
+ /** See if we need to call open
+ */
+ public boolean getIsOpen();
+
+ /** This gives a single keyword to identify the implementation.
+ *
+ * @return String An identifying key.
+ */
+ public String id();
+
+ /** This can be called to obtain some information about the index
+ * implementation. id gives a single keyword whereas this gives a more
+ * detailed description.
+ *
+ * @return String A descrptive string.
+ */
+ public String info();
+
+ /** Called to (re)index a record
+ *
+ * @param rec The record to index
+ */
+ public void indexRec(Object rec) throws IndexException;
+
+ /** Called to unindex a record
+ *
+ * @param rec The record to unindex
+ */
+ public void unindexRec(Object rec) throws IndexException;
+
+ /** Called to (re)index a batch of records
+ *
+ * @param recs The records to index
+ */
+ public void indexRecs(Object[] recs) throws IndexException;
+
+ /** Called to index a batch of new records. More efficient way of
+ * rebuilding the index.
+ *
+ * @param recs The records to index
+ */
+ public void indexNewRecs(Object[] recs) throws IndexException;
+
+ /** Called to unindex a batch of records
+ *
+ * @param recs The records to unindex
+ */
+ public void unindexRecs(Object[] recs) throws IndexException;
+
+ /** Called to find entries that match the search string. This string may
+ * be a simple sequence of keywords or some sort of query the syntax of
+ * which is determined by the underlying implementation.
+ *
+ * @param query Query string
+ * @return int Number found. 0 means none found,
+ * -1 means indeterminate
+ */
+ public int search(String query) throws IndexException;
+
+ /** The implementation will determine what information the Key object
+ * actually contains. The getRecord method can be called to retrieve the
+ * referenced entry.
+ */
+ public abstract class Key {
+ public float score; // Score this record
+
+ public abstract Object getRecord() throws IndexException;
+ }
+
+ /** Called to retrieve record keys from the result.
+ *
+ * @param n Starting index
+ * @param keys Array for the record keys
+ * @return int Actual number of records
+ */
+ public int retrieve(int n, Key[] keys) throws IndexException;
+
+ /** Called if we intend to run a batch of updates. endBatch MUST be
+ * called or manual intervention may be required to remove locks.
+ */
+ public void startBatch() throws IndexException;
+
+ /** Called at the end of a batch of updates.
+ */
+ public void endBatch() throws IndexException;
+
+ /** Called to close at the end of a session.
+ */
+ public void close() throws IndexException;
+
+ /** Called to provide some debugging dump info. Must be open.
+ */
+ public void dump();
+
+ /** Called to provide some statistics. Must be open.
+ */
+ public void stats();
+
+}
Added: trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexDummyImpl.java
===================================================================
--- trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexDummyImpl.java (rev 0)
+++ trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexDummyImpl.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,136 @@
+package edu.rpi.cct.misc.indexing;
+
+/** This class implements a dummy null indexer.
+ */
+public class IndexDummyImpl implements Index {
+ private boolean isOpen;
+
+ public IndexDummyImpl() throws IndexException {
+ }
+
+ public void setDebug(boolean val) {
+ }
+
+ /** This must be called to open the index in the appropriate manner
+ * probably determined by information passed to the constructor.
+ */
+ public void open() throws IndexException {
+ isOpen = true;
+ }
+
+ /** This can be called to (re)create the index. It will destroy any
+ * previously existing index.
+ */
+ public void create() throws IndexException {
+ isOpen = true;
+ }
+
+ /** See if we need to call open
+ */
+ public boolean getIsOpen() {
+ return isOpen;
+ }
+
+ /** This gives a single keyword to identify the implementation.
+ *
+ * @return String An identifying key.
+ */
+ public String id() {
+ return "dummy";
+ }
+
+ /** This can be called to obtain some information about the index
+ * implementation. id gives a single keyword whereas this gives a more
+ * detailed description.
+ *
+ * @return String A descrptive string.
+ */
+ public String info() {
+ return "A dummy implementation of an indexer.";
+ }
+
+ /** Called to index a record
+ *
+ * @param rec The record to index
+ */
+ public void indexRec(Object rec) throws IndexException {
+ }
+
+ /** Called to unindex a record
+ *
+ * @param rec The record to unindex
+ */
+ public void unindexRec(Object rec) throws IndexException {
+ }
+
+ /** Called to (re)index a batch of records
+ *
+ * @param recs The records to index
+ */
+ public void indexRecs(Object[] recs) throws IndexException {
+ }
+
+ /** Called to index a batch of new records. More efficient way of
+ * rebuilding the index.
+ *
+ * @param recs The records to index
+ */
+ public void indexNewRecs(Object[] recs) throws IndexException {
+ }
+
+ /** Called to unindex a batch of records
+ *
+ * @param recs The records to unindex
+ */
+ public void unindexRecs(Object[] recs) throws IndexException {
+ }
+
+ /** Called to find entries that match the search string. This string may
+ * be a simple sequence of keywords or some sort of query the syntax of
+ * which is determined by the underlying implementation.
+ *
+ * @param query Query string
+ * @return int Number found. 0 means none found,
+ * -1 means indeterminate
+ */
+ public int search(String query) throws IndexException {
+ return 0;
+ }
+
+ /** Called to retrieve record keys from the result.
+ *
+ * @param n Starting index
+ * @param keys Array for the record keys
+ * @return int Actual number of records
+ */
+ public int retrieve(int n, Index.Key[] keys) throws IndexException {
+ return 0;
+ }
+
+ /** Called if we intend to run a batch of updates. endBatch MUST be
+ * called or manual intervention may be required to remove locks.
+ */
+ public void startBatch() throws IndexException {
+ }
+
+ /** Called at the end of a batch of updates.
+ */
+ public void endBatch() throws IndexException {
+ }
+
+ /** Called to close at the end of a session.
+ */
+ public void close() {
+ isOpen = false;
+ }
+
+ /** Called to provide some debugging dump info.
+ */
+ public void dump() {
+ }
+
+ /** Called to provide some statistics.
+ */
+ public void stats() {
+ }
+}
Added: trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexException.java
===================================================================
--- trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexException.java (rev 0)
+++ trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexException.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,56 @@
+package edu.rpi.cct.misc.indexing;
+
+/** Pass back an exception from the indexing classes.
+ * The object will contain a property name and optionally one of an
+ * exception object representing some underlying cause or a string value for
+ * insertion in the message.
+ * <p>If a call on getCause returns a non-null result, the cause of the
+ * exception is some underlying exception.
+ * <p>Otherwise the property name and possibly the reason will be set.
+ */
+public class IndexException extends Exception {
+ /** Exception property names.
+ */
+
+ /** "No base path specified" */
+ public final static String noBasePath = "edu.rpi.sss.indexing.exc.nobasepath";
+
+ /** "Insufficient access to create an index" */
+ public final static String noIdxCreateAccess = "edu.rpi.sss.indexing.exc.noIdxCreateAccess";
+
+ /** "Non-unique key term {0}" */
+ public final static String dupKey = "edu.rpi.sss.indexing.exc.dupkey";
+
+ /** "Insufficient access" */
+ public final static String noAccess = "edu.rpi.sss.indexing.exc.noaccess";
+
+ /** "Application error: Unknown record type {0}" */
+ public final static String unknownRecordType = "edu.rpi.sss.indexing.exc.unknownrecordtype";
+
+ /** "Exception occurred" */
+ public final static String errException = "edu.rpi.sss.indexing.exc.exception";
+
+ private String reason1;
+
+ public IndexException() {
+ super();
+ }
+
+ public IndexException(Throwable cause) {
+ super(cause);
+ }
+
+ public IndexException(String pr) {
+ super(pr);
+ }
+
+ public IndexException(String pr, String reason1) {
+ super(pr);
+ this.reason1 = reason1;
+ }
+
+ public String getReason1() {
+ return reason1;
+ }
+}
+
Added: trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexLuceneImpl.java
===================================================================
--- trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexLuceneImpl.java (rev 0)
+++ trunk/calendar3/common/src/edu/rpi/cct/misc/indexing/IndexLuceneImpl.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -0,0 +1,700 @@
+package edu.rpi.cct.misc.indexing;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.queryParser.ParseException;
+import org.apache.lucene.queryParser.QueryParser;
+import org.apache.lucene.search.Hits;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Query;
+import org.apache.lucene.search.Searcher;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.sql.Timestamp;
+
+/** This class implements indexing using Lucene.
+ * There is an abstract method to create a Lucene Document from an object.
+ * Also an abstract method to create the Key object.
+ */
+public abstract class IndexLuceneImpl implements Index {
+ private boolean debug;
+ private boolean writeable;
+ private String basePath;
+ private String defaultFieldName;
+
+ /** We append this to basePath to reach the indexes.
+ */
+ private final static String indexDir = "/indexes";
+
+ private boolean updatedIndex;
+ private boolean isOpen;
+
+ /** We try to keep readers and writers open if batchMode is true.
+ */
+ //private boolean batchMode;
+
+ IndexReader rdr;
+ IndexWriter wtr;
+ Searcher sch;
+ Analyzer defaultAnalyzer;
+
+ QueryParser queryParser;
+
+ Hits lastResult;
+
+ private String[] stopWords;
+
+ /** Create an indexer with the default set of stop words.
+ *
+ * @param basePath String path to where we should read/write indexes
+ * @param defaultFieldName default name for searches
+ * @param writeable true if the caller can update the index
+ * @param debug true if we want to see what's going on
+ */
+ public IndexLuceneImpl(String basePath,
+ String defaultFieldName,
+ boolean writeable,
+ boolean debug) throws IndexException {
+ this(basePath, defaultFieldName, writeable, null, debug);
+ }
+
+ /** Create an indexer with the given set of stop words.
+ *
+ * @param basePath String path to where we should read/write indexes
+ * @param defaultFieldName default name for searches
+ * @param writeable true if the caller can update the index
+ * @param stopWords set of stop words, null for default.
+ * @param debug true if we want to see what's going on
+ */
+ public IndexLuceneImpl(String basePath,
+ String defaultFieldName,
+ boolean writeable,
+ String[] stopWords,
+ boolean debug) throws IndexException {
+ setDebug(debug);
+ this.writeable = writeable;
+ this.basePath = basePath;
+ this.defaultFieldName = defaultFieldName;
+ this.stopWords = stopWords;
+ }
+
+ public boolean getDebug() {
+ return debug;
+ }
+
+ /** Called to make or fill in a Key object.
+ *
+ * @param key Possible Index.Key object for reuse
+ * @param doc The retrieved Document
+ * @param score The rating for this entry
+ * @return Index.Key new or reused object
+ */
+ public abstract Index.Key makeKey(Index.Key key,
+ Document doc,
+ float score) throws IndexException;
+
+ /** Called to make a key term for a record.
+ *
+ * @param rec The record
+ * @return Term Lucene term which uniquely identifies the record
+ */
+ public abstract Term makeKeyTerm(Object rec) throws IndexException;
+
+ /** Called to make the primary key name for a record.
+ *
+ * @param rec The record
+ * @return String Name for the field/term
+ */
+ public abstract String makeKeyName(Object rec) throws IndexException;
+
+ /** Called to fill in a Document from an object.
+ *
+ * @param doc The =Document
+ * @param rec The record
+ */
+ public abstract void addFields(Document doc,
+ Object rec) throws IndexException;
+
+ /** Called to return an array of valid term names.
+ *
+ * @return String[] term names
+ */
+ public abstract String[] getTermNames();
+
+ public void setDebug(boolean val) {
+ debug = val;
+ }
+
+ /** This can be called to open the index in the appropriate manner
+ * probably determined by information passed to the constructor.
+ *
+ * <p>For a first time call a new analyzer will be created.
+ */
+ public void open() throws IndexException {
+ close();
+
+ if (defaultAnalyzer == null) {
+ if (stopWords == null) {
+ defaultAnalyzer = new StandardAnalyzer();
+ } else {
+ defaultAnalyzer = new StandardAnalyzer(stopWords);
+ }
+
+ queryParser = new QueryParser(defaultFieldName,
+ defaultAnalyzer);
+ }
+
+ updatedIndex = false;
+ isOpen = true;
+ }
+
+ /** This can be called to (re)create the index. It will destroy any
+ * previously existing index.
+ */
+ public void create() throws IndexException {
+ try {
+ if (!writeable) {
+ throw new IndexException(IndexException.noIdxCreateAccess);
+ }
+
+ close();
+
+ if (basePath == null) {
+ throw new IndexException(IndexException.noBasePath);
+ }
+
+ IndexWriter iw = new IndexWriter(basePath + indexDir, defaultAnalyzer, true);
+ iw.optimize();
+ iw.close();
+ iw = null;
+
+ open();
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** See if we need to call open
+ */
+ public boolean getIsOpen() {
+ return isOpen;
+ }
+
+ /** This gives a single keyword to identify the implementation.
+ *
+ * @return String An identifying key.
+ */
+ public String id() {
+ return "LUCENE";
+ }
+
+ /** This can be called to obtain some information about the index
+ * implementation. id gives a single keyword whereas this gives a more
+ * detailed description.
+ *
+ * @return String A descrptive string.
+ */
+ public String info() {
+ return "An implementation of an indexer using jakarta Lucene.";
+ }
+
+ /** Called to index a record
+ *
+ * @param rec The record to index
+ */
+ public void indexRec(Object rec) throws IndexException {
+ unindexRec(rec);
+ intIndexRec(rec);
+ closeWtr();
+ }
+
+ /** Called to unindex a record
+ *
+ * @param rec The record to unindex
+ */
+ public void unindexRec(Object rec) throws IndexException {
+ try {
+ checkOpen();
+ closeWtr();
+ intUnindexRec(rec);
+ } finally {
+ closeWtr(); // Just in case
+ closeRdr();
+ }
+ }
+
+ /** Called to (re)index a batch of records
+ *
+ * @param recs The records to index
+ */
+ public void indexRecs(Object[] recs) throws IndexException {
+ if (recs == null) {
+ return;
+ }
+
+ try {
+ unindexRecs(recs);
+
+ for (int i = 0; i < recs.length; i++) {
+ if (recs[i] != null) {
+ intIndexRec(recs[i]);
+ }
+ }
+ } finally {
+ closeWtr();
+ closeRdr(); // Just in case
+ }
+ }
+
+ /** Called to index a batch of new records. More efficient way of
+ * rebuilding the index.
+ *
+ * @param recs The records to index
+ */
+ public void indexNewRecs(Object[] recs) throws IndexException {
+ if (recs == null) {
+ return;
+ }
+
+ try {
+ closeRdr(); // Just in case
+
+ for (int i = 0; i < recs.length; i++) {
+ if (recs[i] != null) {
+ intIndexRec(recs[i]);
+ }
+ }
+ } finally {
+ closeWtr();
+ }
+ }
+
+ /** Called to unindex a batch of records
+ *
+ * @param recs The records to unindex
+ */
+ public void unindexRecs(Object[] recs) throws IndexException {
+ if (recs == null) {
+ return;
+ }
+
+ try {
+ checkOpen();
+ closeWtr();
+
+ for (int i = 0; i < recs.length; i++) {
+ if (recs[i] != null) {
+ intUnindexRec(recs[i]);
+ }
+ }
+ } finally {
+ closeWtr(); // Just in case
+ closeRdr();
+ }
+ }
+
+ /** Called to find entries that match the search string. This string may
+ * be a simple sequence of keywords or some sort of query the syntax of
+ * which is determined by the underlying implementation.
+ *
+ * @param query Query string
+ * @return int Number found. 0 means none found,
+ * -1 means indeterminate
+ */
+ public int search(String query) throws IndexException {
+ checkOpen();
+
+ try {
+ if (debug) {
+ log("About to search for " + query);
+ }
+
+ Query parsed = queryParser.parse(query);
+
+ if (debug) {
+ log(" with parsed query " + parsed.toString(null));
+ }
+
+ if (sch == null) {
+ sch = new IndexSearcher(getRdr());
+ }
+ lastResult = sch.search(parsed);
+
+ if (debug) {
+ log(" found " + lastResult.length());
+ }
+
+ return lastResult.length();
+ } catch (ParseException pe) {
+ throw new IndexException(pe);
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Called to retrieve record keys from the result.
+ *
+ * @param n Starting index
+ * @param keys Array for the record keys
+ * @return int Actual number of records
+ */
+ public int retrieve(int n, Index.Key[] keys) throws IndexException {
+ checkOpen();
+
+ if ((lastResult == null) ||
+ (keys == null) ||
+ (n >= lastResult.length())) {
+ return 0;
+ }
+
+ int i;
+
+ for (i = 0; i < keys.length; i++) {
+ int hi = i + n;
+ if (hi >= lastResult.length()) {
+ break;
+ }
+
+ try {
+ keys[i] = makeKey(keys[i], lastResult.doc(hi), lastResult.score(hi));
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ return i;
+ }
+
+ /** Called if we intend to run a batch of updates. endBatch MUST be
+ * called or manual intervention may be required to remove locks.
+ */
+ public void startBatch() throws IndexException {
+ //batchMode = true;
+ }
+
+ /** Called at the end of a batch of updates.
+ */
+ public void endBatch() throws IndexException {
+ //batchMode = false;
+ close();
+ }
+
+ /** Called to close at the end of a session.
+ */
+ public synchronized void close() throws IndexException {
+ closeWtr();
+ closeRdr();
+
+ isOpen = false;
+ }
+
+ /** Called if we need to close the writer
+ */
+ public synchronized void closeWtr() throws IndexException {
+ try {
+ if (wtr != null) {
+ if (updatedIndex) {
+ wtr.optimize();
+ updatedIndex = false;
+ }
+ wtr.close();
+ wtr = null;
+ }
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Called if we need to close the reader
+ */
+ public synchronized void closeRdr() throws IndexException {
+ try {
+ if (sch != null) {
+ try {
+ sch.close();
+ } catch (Exception e) {}
+ sch = null;
+ }
+
+ if (rdr != null) {
+ rdr.close();
+ rdr = null;
+ }
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Called to provide some debugging dump info.
+ */
+ public void dump() {
+ }
+
+ /** Called to provide some statistics.
+ */
+ public void stats() {
+ }
+
+ /** ===================================================================
+ Private methods
+ =================================================================== */
+
+ /** Ensure we're open
+ */
+ private void checkOpen() throws IndexException {
+ if (isOpen) {
+ return;
+ }
+
+ open();
+ }
+
+ /** Called to obtain the current or a new writer.
+ *
+ * @return IndexWriter writer to our index
+ */
+ private IndexWriter getWtr() throws IndexException {
+ if (!writeable) {
+ throw new IndexException(IndexException.noAccess);
+ }
+
+ try {
+ if (wtr == null) {
+ wtr = new IndexWriter(basePath + indexDir, defaultAnalyzer, false);
+ }
+
+ return wtr;
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Called to obtain the current or a new reader.
+ *
+ * @return IndexReader reader of our index
+ */
+ private IndexReader getRdr() throws IndexException {
+ if (basePath == null) {
+ throw new IndexException(IndexException.noBasePath);
+ }
+
+ try {
+ if (rdr == null) {
+ rdr = IndexReader.open(basePath + indexDir);
+ }
+
+ return rdr;
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+
+ /** Called to unindex a record. The reader will be left
+ * open. The writer must be closed and will stay closed.
+ *
+ * @param rec The record to unindex
+ */
+ private void intUnindexRec(Object rec) throws IndexException {
+ try {
+ Term t = makeKeyTerm(rec);
+
+ int numDeleted = getRdr().deleteDocuments(t);
+
+ if (numDeleted > 1) {
+ throw new IndexException(IndexException.dupKey, t.toString());
+ }
+
+ if (debug) {
+ log("removed " + numDeleted + " entries for " + t);
+ }
+
+ updatedIndex = true;
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** Called to index a record. The writer will be left open and the reader
+ * must be closed on entry and will stay closed.
+ *
+ * @param rec The record to index
+ */
+ private void intIndexRec(Object rec) throws IndexException {
+ Document doc = new Document();
+
+ addFields(doc, rec);
+
+ try {
+ closeRdr();
+ getWtr().addDocument(doc);
+
+ updatedIndex = true;
+ } catch (IOException e) {
+ throw new IndexException(e);
+ } catch (Throwable t) {
+ throw new IndexException(t);
+ }
+ }
+
+ /** ===================================================================
+ Some useful methods
+ =================================================================== */
+
+ /** Called to add an array of keys to a document
+ *
+ * @param doc Document object
+ * @param name String field name
+ * @param ss String array of keywords
+ */
+ protected void addKeyArray(Document doc, String name, String[] ss)
+ throws IndexException {
+ if (ss == null) {
+ return;
+ }
+
+ for (int i = 0; i < ss.length; i++) {
+ if (ss[i] != null) {
+ doc.add(new Field(name, ss[i], Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+ }
+ }
+
+ /** Called to add a timestamp date to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param dt The timestamp
+ */
+ protected void addTimestamp(Document doc, String name, Timestamp dt)
+ throws IndexException {
+ if (dt == null) {
+ return;
+ }
+
+ doc.add(new Field(name, dt.toString(), Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+
+ /** Called to add a String val to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The value
+ */
+ protected void addString(Document doc, String name, String val)
+ throws IndexException {
+ if (val == null) {
+ return;
+ }
+
+ doc.add(new Field(name, val, Field.Store.YES, Field.Index.TOKENIZED));
+ }
+
+ /** Called to add a cost to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param cost The cost in cents
+ */
+ protected void addCost(Document doc, String name, Long cost)
+ throws IndexException {
+ if (cost == null) {
+ return;
+ }
+
+ doc.add(new Field(name, cost.toString(), Field.Store.YES,
+ Field.Index.UN_TOKENIZED));
+ }
+
+ /** Called to add a long value to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The long value
+ */
+ protected void addLong(Document doc, String name, long val) {
+ doc.add(new Field(name, String.valueOf(val), Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+
+ /** Called to add an untokenized value to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The value
+ */
+ protected void addUntokenized(Document doc, String name, String val) {
+ doc.add(new Field(name, val, Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+
+ /** Called to add a keyword val to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The value
+ */
+ protected void addKey(Document doc, String name, String val)
+ throws IndexException {
+ if (val == null) {
+ return;
+ }
+
+ doc.add(new Field(name, val, Field.Store.YES, Field.Index.UN_TOKENIZED));
+ }
+
+ /** Called to add a long String val to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The value
+ */
+ protected void addLongStoredString(Document doc, String name, String val)
+ throws IndexException {
+ if (val == null) {
+ return;
+ }
+
+ doc.add(new Field(name, new StringReader(val)));
+ }
+
+ /** Called to add a long String val to a document
+ *
+ * @param doc The document
+ * @param name Field name
+ * @param val The value
+ */
+ protected void addLongString(Document doc, String name, String val)
+ throws IndexException {
+ if (val == null) {
+ return;
+ }
+
+ doc.add(new Field(name, val, Field.Store.NO, Field.Index.TOKENIZED));
+ }
+
+ protected void log(String msg) {
+ System.out.println(getClass().getName() + ": " + msg);
+ }
+}
+
Added: trunk/calendar3/lib/lucene-core-1.9.1.jar
===================================================================
(Binary files differ)
Property changes on: trunk/calendar3/lib/lucene-core-1.9.1.jar
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/calendar3/webclient/src/org/bedework/webclient/BwFreeBusyAction.java
===================================================================
--- trunk/calendar3/webclient/src/org/bedework/webclient/BwFreeBusyAction.java 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/webclient/src/org/bedework/webclient/BwFreeBusyAction.java 2006-04-13 13:35:10 UTC (rev 369)
@@ -157,7 +157,7 @@
BwFreeBusy fb = svci.getFreeBusy(null, user,
CalFacadeUtil.getDateTime(sdt, false, false, tzs),
CalFacadeUtil.getDateTime(edt, false, false, tzs),
- dur);
+ dur, true);
form.assignFreeBusy(fb);
Modified: trunk/calendar3/webclient/war/docs/freeBusy.jsp
===================================================================
--- trunk/calendar3/webclient/war/docs/freeBusy.jsp 2006-04-12 21:10:00 UTC (rev 368)
+++ trunk/calendar3/webclient/war/docs/freeBusy.jsp 2006-04-13 13:35:10 UTC (rev 369)
@@ -1,6 +1,7 @@
<%@ taglib uri='struts-bean' prefix='bean' %>
<%@ taglib uri='struts-logic' prefix='logic' %>
<%@ taglib uri='struts-genurl' prefix='genurl' %>
+<%@ taglib uri='bedework' prefix='bw' %>
<%@ include file="/docs/header.jsp" %>
@@ -16,9 +17,9 @@
toScope="request"/>
<freebusy>
- <who><bean:write name="freeBusyObj" property="who.account" /></who>
- <start><bean:write name="freeBusyObj" property="start" /></start>
- <end><bean:write name="freeBusyObj" property="end" /></end>
+ <bw:emitText name="freeBusyObj" property="who.account" tagName="who" />
+ <bw:emitText name="freeBusyObj" property="start.dtval" tagName="start" />
+ <bw:emitText name="freeBusyObj" property="end.dtval" tagName="end" />
<logic:iterate id="freeBusyComponent" name="freeBusyObj" property="times" >
<freeBusyComponent>
<fbtype><bean:write name="freeBusyComponent" property="type" /></fbtype>
More information about the Bedework-commit
mailing list