2004-11-24 02:40:06 +03:00
|
|
|
/* -*- Mode: javascript; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Oracle Corporation code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Oracle Corporation
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
//
|
|
|
|
// calCompositeCalendar.js
|
|
|
|
//
|
|
|
|
|
|
|
|
const calIOperationListener = Components.interfaces.calIOperationListener;
|
|
|
|
|
2005-04-19 10:49:50 +04:00
|
|
|
function calCompositeCalendarObserverHelper (compCalendar) {
|
|
|
|
this.compCalendar = compCalendar;
|
|
|
|
}
|
|
|
|
|
|
|
|
calCompositeCalendarObserverHelper.prototype = {
|
|
|
|
QueryInterface: function (aIID) {
|
|
|
|
if (!aIID.equals(Components.interfaces.calIObserver) &&
|
|
|
|
!aIID.equals(Components.interfaces.nsISupports))
|
|
|
|
{
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
onStartBatch: function() {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onStartBatch();
|
|
|
|
},
|
|
|
|
|
|
|
|
onEndBatch: function() {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onEndBatch();
|
|
|
|
},
|
|
|
|
|
|
|
|
onLoad: function() {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onLoad();
|
|
|
|
},
|
|
|
|
|
|
|
|
onAddItem: function(aItem) {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onAddItem(aItem);
|
|
|
|
},
|
|
|
|
|
|
|
|
onModifyItem: function(aNewItem, aOldItem) {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onAddItem(aNewItem, aOldItem);
|
|
|
|
},
|
|
|
|
|
|
|
|
onDeleteItem: function(aDeletedItem) {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onAddItem(aDeletedItem);
|
|
|
|
},
|
|
|
|
|
|
|
|
onAlarm: function(aAlarmItem) {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onAddItem(aAlarmItem);
|
|
|
|
},
|
|
|
|
|
|
|
|
onError: function(aErrNo, aMessage) {
|
|
|
|
for each (obs in this.compCalendar.mObservers)
|
|
|
|
obs.onAddItem(aErrNo, aMessage);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2004-11-24 02:40:06 +03:00
|
|
|
function calCompositeCalendar () {
|
2005-04-19 10:49:50 +04:00
|
|
|
this.mObserverHelper = new calCompositeCalendarObserverHelper();
|
2004-11-24 02:40:06 +03:00
|
|
|
this.wrappedJSObject = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
calCompositeCalendar.prototype = {
|
|
|
|
//
|
|
|
|
// private members
|
|
|
|
//
|
|
|
|
mCalendars: Array(),
|
|
|
|
mDefaultCalendar: null,
|
|
|
|
|
|
|
|
//
|
|
|
|
// nsISupports interface
|
|
|
|
//
|
|
|
|
QueryInterface: function (aIID) {
|
|
|
|
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
|
|
|
!aIID.equals(Components.interfaces.calICalendar) &&
|
|
|
|
!aIID.equals(Components.interfaces.calICompositeCalendar))
|
|
|
|
{
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
//
|
|
|
|
// calICompositeCalendar interface
|
|
|
|
//
|
|
|
|
|
|
|
|
mCalendars: Array(),
|
|
|
|
mDefaultCalendar: null,
|
|
|
|
|
2005-03-21 20:55:24 +03:00
|
|
|
addCalendar: function (aCalendar) {
|
2004-11-24 02:40:06 +03:00
|
|
|
// check if the calendar already exists
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (cal in this.mCalendars) {
|
|
|
|
if (aCalendar.uri.equals(cal.uri)) {
|
2004-11-24 02:40:06 +03:00
|
|
|
// throw exception if calendar already exists?
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-19 10:49:50 +04:00
|
|
|
// add our observer helper
|
|
|
|
aCalendar.addObserver(this.mObserverHelper);
|
|
|
|
|
2005-03-21 20:55:24 +03:00
|
|
|
this.mCalendars.push(aCalendar);
|
2004-11-24 02:40:06 +03:00
|
|
|
|
2005-03-21 20:55:24 +03:00
|
|
|
this.observeCalendarAdded(aCalendar);
|
2004-11-24 02:40:06 +03:00
|
|
|
|
|
|
|
// if we have no default calendar, we need one here
|
|
|
|
if (this.mDefaultCalendar == null) {
|
2005-03-21 20:55:24 +03:00
|
|
|
this.mDefaultCalendar = aCalendar;
|
|
|
|
this.observeDefaultCalendarChanged(aCalendar);
|
2004-11-24 02:40:06 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
removeCalendar: function (aServer) {
|
|
|
|
var newCalendars = Array();
|
|
|
|
var calToRemove = null;
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (cal in this.mCalendars) {
|
|
|
|
if (!aServer.equals(cal.uri))
|
2004-11-24 02:40:06 +03:00
|
|
|
newCalendars.push(cal);
|
|
|
|
else
|
|
|
|
calToRemove = cal;
|
|
|
|
}
|
|
|
|
|
2005-04-19 10:49:50 +04:00
|
|
|
if (calToRemove) {
|
|
|
|
this.mCalendars = newCalendars;
|
|
|
|
calToRemove.removeObserver(this.mObserverHelper);
|
|
|
|
this.observeCalendarRemoved(calToRemove);
|
|
|
|
}
|
2004-11-24 02:40:06 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
getCalendar: function (aServer) {
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (cal in this.mCalendars) {
|
|
|
|
if (aServer.equals(cal.uri))
|
2004-11-24 02:40:06 +03:00
|
|
|
return cal;
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
get calendars() {
|
|
|
|
// return a nsISimpleEnumerator of this array. This sucks.
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
|
|
|
|
get defaultCalendar() {
|
|
|
|
return this.mDefaultCalendar;
|
|
|
|
},
|
|
|
|
|
|
|
|
set defaultCalendar(v) {
|
|
|
|
if (this.mDefaultCalendar != v) {
|
|
|
|
this.mDefaultCalendar = v;
|
|
|
|
this.observeDefaultCalendarChanged (v);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
//
|
|
|
|
// calICalendar interface
|
|
|
|
//
|
|
|
|
// Write operations here are forwarded to either the item's
|
|
|
|
// parent calendar, or to the default calendar if one is set.
|
|
|
|
// Get operations are sent to each calendar.
|
|
|
|
//
|
|
|
|
|
|
|
|
// this could, at some point, return some kind of URI identifying
|
|
|
|
// all the child calendars, thus letting us create nifty calendar
|
|
|
|
// trees.
|
|
|
|
get uri() {
|
|
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
},
|
|
|
|
set uri(v) {
|
|
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
},
|
|
|
|
|
2005-04-15 22:51:47 +04:00
|
|
|
// void addObserver( in calIObserver observer );
|
2004-11-24 02:40:06 +03:00
|
|
|
mCompositeObservers: Array(),
|
2005-04-19 10:49:50 +04:00
|
|
|
mObservers: Array(),
|
|
|
|
addObserver: function (aObserver) {
|
2004-11-24 02:40:06 +03:00
|
|
|
const calICompositeObserver = Components.interfaces.calICompositeObserver;
|
2005-03-23 01:37:54 +03:00
|
|
|
if (aObserver instanceof calICompositeObserver) {
|
2005-04-19 10:49:50 +04:00
|
|
|
if (this.mCompositeObservers.indexOf(aObserver) == -1) {
|
|
|
|
var compobs = aObserver.QueryInterface (calICompositeObserver);
|
|
|
|
this.mCompositeObservers.push(compobs);
|
2004-11-24 02:40:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-19 10:49:50 +04:00
|
|
|
if (this.mObservers.indexOf(aObserver) == -1)
|
|
|
|
this.mObservers.push(aObserver);
|
2004-11-24 02:40:06 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
// void removeObserver( in calIObserver observer );
|
|
|
|
removeObserver: function (aObserver) {
|
|
|
|
const calICompositeObserver = Components.interfaces.calICompositeObserver;
|
2005-04-19 10:49:50 +04:00
|
|
|
if (aObserver instanceof calICompositeObserver)
|
|
|
|
this.mCompositeObservers = this.mCompositeObservers.filter( function (v) { return v != aObserver; } );
|
2004-11-24 02:40:06 +03:00
|
|
|
|
2005-04-19 10:49:50 +04:00
|
|
|
this.mObservers = this.mObservers.filter( function (v) { return v != aObserver; } );
|
2004-11-24 02:40:06 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
// void modifyItem( in calIItemBase aItem, in calIOperationListener aListener );
|
|
|
|
modifyItem: function (aItem, aListener) {
|
|
|
|
if (aItem.parent == null) {
|
|
|
|
// XXX Can't modify item with NULL parent
|
|
|
|
throw Components.results.NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
aItem.parent.modifyItem (aItem, aListener);
|
|
|
|
},
|
|
|
|
|
|
|
|
// void deleteItem( in string id, in calIOperationListener aListener );
|
|
|
|
deleteItem: function (aItem, aListener) {
|
|
|
|
if (aItem.parent == null) {
|
|
|
|
// XXX Can't delete item with NULL parent
|
|
|
|
throw Components.results.NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
aItem.parent.deleteItem (aItem, aListener);
|
|
|
|
},
|
|
|
|
|
|
|
|
// void addItem( in calIItemBase aItem, in calIOperationListener aListener );
|
|
|
|
addItem: function (aItem, aListener) {
|
|
|
|
this.mDefaultCalendar.addItem (aItem, aListener);
|
|
|
|
},
|
|
|
|
|
|
|
|
// void getItem( in string aId, in calIOperationListener aListener );
|
|
|
|
getItem: function (aId, aListener) {
|
|
|
|
var cmpListener = new calCompositeGetListenerHelper(this.mCalendars.length, aListener);
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (cal in this.mCalendars) {
|
2004-11-24 02:40:06 +03:00
|
|
|
cal.getItem (aId, cmpListener);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// void getItems( in unsigned long aItemFilter, in unsigned long aCount,
|
|
|
|
// in calIDateTime aRangeStart, in calIDateTime aRangeEnd,
|
|
|
|
// in calIOperationListener aListener );
|
|
|
|
getItems: function (aItemFilter, aCount, aRangeStart, aRangeEnd, aListener) {
|
|
|
|
var cmpListener = new calCompositeGetListenerHelper(this.mCalendars.length, aListener, aCount);
|
|
|
|
for (cal in this.mCalendars) {
|
2005-03-21 20:55:24 +03:00
|
|
|
this.mCalendars[cal].getItems (aItemFilter, aCount, aRangeStart, aRangeEnd, cmpListener);
|
2004-11-24 02:40:06 +03:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
//
|
|
|
|
// observer helpers
|
|
|
|
//
|
|
|
|
observeCalendarAdded: function (aCalendar) {
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (obs in this.mCompositeObservers)
|
2004-11-24 02:40:06 +03:00
|
|
|
obs.onCalendarAdded (aCalendar);
|
|
|
|
},
|
|
|
|
|
|
|
|
observeCalendarRemoved: function (aCalendar) {
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (obs in this.mCompositeObservers)
|
2004-11-24 02:40:06 +03:00
|
|
|
obs.onCalendarRemoved (aCalendar);
|
|
|
|
},
|
|
|
|
|
|
|
|
observeDefaultCalendarChanged: function (aCalendar) {
|
2005-04-09 00:57:34 +04:00
|
|
|
for each (obs in this.mCompositeObservers)
|
2004-11-24 02:40:06 +03:00
|
|
|
obs.onDefaultCalendarChanged (aCalendar);
|
2005-03-21 20:55:24 +03:00
|
|
|
}
|
2004-11-24 02:40:06 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
// composite listener helper
|
|
|
|
function calCompositeGetListenerHelper(aNumQueries, aRealListener, aMaxItems) {
|
|
|
|
this.wrappedJSObject = this;
|
|
|
|
this.mNumQueries = aNumQueries;
|
|
|
|
this.mRealListener = aRealListener;
|
|
|
|
this.mMaxItems = aMaxItems;
|
|
|
|
}
|
|
|
|
|
|
|
|
calCompositeGetListenerHelper.prototype = {
|
|
|
|
mNumQueries: 0,
|
|
|
|
mRealListener: null,
|
|
|
|
mReceivedCompletes: 0,
|
|
|
|
mFinished: false,
|
|
|
|
mMaxItems: 0,
|
|
|
|
mItemsReceived: 0,
|
|
|
|
|
|
|
|
QueryInterface: function (aIID) {
|
|
|
|
if (!aIID.equals(Components.interfaces.nsISupports) &&
|
|
|
|
!aIID.equals(Components.interfaces.calIOperationListener))
|
|
|
|
{
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this;
|
|
|
|
},
|
|
|
|
|
|
|
|
onOperationComplete: function (aCalendar, aStatus, aOperationType, aId, aDetail) {
|
|
|
|
if (this.mFinished) {
|
|
|
|
dump ("+++ calCompositeGetListenerHelper.onOperationComplete: called with mFinished == true!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Components.isSuccessCode(aStatus)) {
|
|
|
|
// proxy this to a onGetResult
|
|
|
|
// XXX - do we want to give the real calendar? or this?
|
|
|
|
this.mRealListener.onGetResult (aCalendar, aStatus, null, aDetail, 0, []);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.mReceivedCompletes++;
|
|
|
|
|
|
|
|
if (this.mReceivedCompletes == this.mNumQueries) {
|
|
|
|
// we're done here.
|
|
|
|
this.mRealListener.onOperationComplete (this,
|
|
|
|
aOperationType,
|
|
|
|
calIOperationListener.GET,
|
|
|
|
null,
|
|
|
|
null);
|
|
|
|
this.mFinished = true;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
onGetResult: function (aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
|
|
|
|
if (this.mFinished) {
|
|
|
|
dump ("+++ calCompositeGetListenerHelper.onGetResult: called with mFinished == true!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ignore if we have a max and we're past it
|
|
|
|
if (this.mMaxItems && this.mItemsReceived >= this.mMaxItems)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Components.isSuccessCode(aStatus) &&
|
|
|
|
this.mMaxItems &&
|
|
|
|
((this.mItemsReceived + aCount) > this.mMaxItems))
|
|
|
|
{
|
|
|
|
// this will blow past the limit
|
|
|
|
aCount = this.mMaxItems - this.mItemsReceived;
|
|
|
|
aItems = aItems.slice(0, numToSend);
|
|
|
|
}
|
|
|
|
|
|
|
|
// send GetResults to the real listener
|
2005-03-21 20:55:24 +03:00
|
|
|
this.mRealListener.onGetResult (aCalendar, aStatus, aItemType, aDetail, aCount, aItems);
|
2004-11-24 02:40:06 +03:00
|
|
|
this.mItemsReceived += aCount;
|
2005-03-21 20:55:24 +03:00
|
|
|
}
|
2004-11-24 02:40:06 +03:00
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****
|
|
|
|
**** module registration
|
|
|
|
****/
|
|
|
|
|
|
|
|
var calCompositeCalendarModule = {
|
|
|
|
mCID: Components.ID("{aeff788d-63b0-4996-91fb-40a7654c6224}"),
|
|
|
|
mContractID: "@mozilla.org/calendar/calendar;1?type=composite",
|
|
|
|
|
|
|
|
registerSelf: function (compMgr, fileSpec, location, type) {
|
|
|
|
compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
|
|
|
compMgr.registerFactoryLocation(this.mCID,
|
|
|
|
"Calendar composite provider",
|
|
|
|
this.mContractID,
|
|
|
|
fileSpec,
|
|
|
|
location,
|
|
|
|
type);
|
|
|
|
},
|
|
|
|
|
|
|
|
getClassObject: function (compMgr, cid, iid) {
|
|
|
|
if (!cid.equals(this.mCID))
|
|
|
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
|
|
|
|
|
|
|
if (!iid.equals(Components.interfaces.nsIFactory))
|
|
|
|
throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
|
|
|
|
return this.mFactory;
|
|
|
|
},
|
|
|
|
|
|
|
|
mFactory: {
|
|
|
|
createInstance: function (outer, iid) {
|
|
|
|
if (outer != null)
|
|
|
|
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
|
|
|
return (new calCompositeCalendar()).QueryInterface(iid);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
canUnload: function(compMgr) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
function NSGetModule(compMgr, fileSpec) {
|
|
|
|
return calCompositeCalendarModule;
|
|
|
|
}
|