1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent tw=79 ft=cpp: */
4 * Copyright (C) 2007 Sergey Yanovich <ynvich@gmail.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 #include "xpcom-config.h"
26 #include "nsArrayUtils.h"
28 /* Project includes */
29 #include "aaAmountUtils.h"
33 #include "aaIResource.h"
35 #include "aaITransaction.h"
36 #include "aaIStorager.h"
41 :mSide(0), mAmount(0.0), mValue(0.0), mCreditRate(0.0), mDebitRate(0.0),
42 mStatus(PR_FALSE
), mStart(LL_MININT
), mHasPrevTime(PR_FALSE
), mEventId(0),
43 mRate(1.0), mDiff0(0.0), mDiff1(0.0)
51 NS_IMPL_ISUPPORTS3(aaState
,
57 aaState::GetId(PRInt64
*aId
)
59 NS_ENSURE_ARG_POINTER(aId
);
64 aaState::SetId(PRInt64 aId
)
71 aaState::Accept(aaIHandler
* aQuery
)
73 NS_ENSURE_ARG_POINTER(aQuery
);
74 return NS_ERROR_NOT_AVAILABLE
;
78 aaState::GetEdited(PRBool
* aEdited
)
80 NS_ENSURE_ARG_POINTER(aEdited
);
81 return NS_ERROR_NOT_AVAILABLE
;
85 aaState::Sync(aaIStorager
*aStorager
, aaISqliteChannel
*aChannel
)
89 NS_ENSURE_TRUE(mStatus
>= NEW
, NS_ERROR_NOT_INITIALIZED
);
91 return NS_ERROR_NOT_INITIALIZED
;
93 if (mStatus
== REPLACE
) {
94 rv
= aStorager
->Close(aChannel
);
95 NS_ENSURE_SUCCESS(rv
, rv
);
97 else if (mStatus
== UPDATE
) {
98 if (isZero(PickAmount())) {
99 rv
= aStorager
->Delete(aChannel
);
100 NS_ENSURE_SUCCESS(rv
, rv
);
105 rv
= aStorager
->Update(aChannel
);
106 NS_ENSURE_SUCCESS(rv
, rv
);
112 if (!isZero(PickAmount())) {
113 rv
= aStorager
->Insert(aChannel
);
114 NS_ENSURE_SUCCESS(rv
, rv
);
122 aaState::GetFlow(aaIFlow
* *aFlow
)
124 NS_ENSURE_ARG_POINTER(aFlow
);
125 NS_IF_ADDREF(*aFlow
= mFlow
);
129 aaState::SetFlow(aaIFlow
* aFlow
)
141 aaState::GetResource(aaIResource
* *aResource
)
143 NS_ENSURE_TRUE(mFlow
, NS_ERROR_NOT_INITIALIZED
);
145 return mFlow
->GetTakeResource(aResource
);
147 return mFlow
->GetGiveResource(aResource
);
151 aaState::GetSide(PRBool
*aSide
)
153 NS_ENSURE_ARG_POINTER(aSide
);
158 aaState::SetSide(PRBool aSide
)
170 aaState::GetAmount(double *aAmount
)
172 NS_ENSURE_ARG_POINTER(aAmount
);
177 aaState::SetAmount(double aAmount
)
183 aaState::PickAmount()
189 aaState::GetStart(PRTime
*aStart
)
191 NS_ENSURE_ARG_POINTER(aStart
);
196 aaState::SetStart(PRTime aStart
)
209 aaState::GetEnd(PRTime
*aEnd
)
211 NS_ENSURE_ARG_POINTER(aEnd
);
216 aaState::SetEnd(PRTime aEnd
)
218 NS_ENSURE_TRUE(mStatus
== LOADED
, NS_ERROR_NOT_INITIALIZED
);
230 aaState::GetIsPaid(PRBool
*aIsPaid
)
232 NS_ENSURE_ARG_POINTER(aIsPaid
);
233 *aIsPaid
= PickIsPaid();
237 aaState::PickIsPaid()
239 return (mStatus
== PAID
);
243 aaState::GetPrevTime(PRTime
*aPrevTime
)
245 NS_ENSURE_ARG_POINTER(aPrevTime
);
246 NS_ENSURE_TRUE(mHasPrevTime
, NS_ERROR_NOT_INITIALIZED
);
247 *aPrevTime
= mPrevTime
;
252 aaState::ApplyFact(aaIFact
*aFact
)
254 NS_ENSURE_TRUE(mFlow
&& mFlow
->PickId(), NS_ERROR_NOT_INITIALIZED
);
258 rv
= setFactSide(aFact
);
259 NS_ENSURE_SUCCESS(rv
, rv
);
261 rv
= updateTime(aFact
->PickTime());
262 NS_ENSURE_SUCCESS(rv
, rv
);
264 mEventId
= aFact
->PickEventId();
265 mFactId
= aFact
->PickId();
267 rv
= useRules(aFact
);
268 NS_ENSURE_SUCCESS(rv
, rv
);
273 aaState::GetEventId(PRInt64
*aEventId
)
275 NS_ENSURE_ARG_POINTER(aEventId
);
276 NS_ENSURE_TRUE(mEventId
, NS_ERROR_NOT_INITIALIZED
);
277 *aEventId
= mEventId
;
281 aaState::GetFactId(PRInt64
*aFactId
)
283 NS_ENSURE_ARG_POINTER(aFactId
);
284 NS_ENSURE_TRUE(mEventId
, NS_ERROR_NOT_INITIALIZED
);
289 aaState::GetFactSide(PRBool
*aFactSide
)
291 NS_ENSURE_ARG_POINTER(aFactSide
);
292 NS_ENSURE_TRUE(mEventId
, NS_ERROR_NOT_INITIALIZED
);
293 *aFactSide
= mFactSide
;
298 aaState::GetValue(double *aValue
)
300 NS_ENSURE_ARG_POINTER(aValue
);
301 *aValue
= PickValue();
305 aaState::SetInitValue(double aValue
)
313 if (!mFlow
|| !mFlow
->PickId())
317 return mDebitRate
? normVal(mAmount
* mDebitRate
) : mValue
;
319 return mCreditRate
? normVal(mAmount
* mCreditRate
) : mValue
;
323 aaState::GetCreditDiff(double *aDiff
)
325 NS_ENSURE_ARG_POINTER(aDiff
);
326 NS_ENSURE_TRUE(mFlow
, NS_ERROR_NOT_INITIALIZED
);
327 *aDiff
= PickCreditDiff();
331 aaState::PickCreditDiff()
335 if (!mFlow
->PickId())
337 return (!mSide
&& mCreditRate
) ? normVal(mAmount
* mCreditRate
) - mValue
: 0.0;
341 aaState::GetDebitDiff(double *aDiff
)
343 NS_ENSURE_ARG_POINTER(aDiff
);
344 NS_ENSURE_TRUE(mFlow
, NS_ERROR_NOT_INITIALIZED
);
345 *aDiff
= PickDebitDiff();
349 aaState::PickDebitDiff()
353 if (!mFlow
->PickId())
355 return (mSide
&& mDebitRate
) ? normVal(mAmount
* mDebitRate
) - mValue
: 0.0;
359 aaState::ApplyQuote(aaIQuote
*aQuote
)
361 NS_ENSURE_ARG_POINTER(aQuote
);
362 NS_ENSURE_TRUE(mFlow
, NS_ERROR_NOT_INITIALIZED
);
363 NS_ENSURE_ARG_POINTER(aQuote
->PickResource());
366 PRInt64 quoteId
= aQuote
->PickResource()->PickId();
367 nsCOMPtr
<aaIResource
> resource
;
368 rv
= mFlow
->GetTakeResource(getter_AddRefs(resource
));
369 NS_ENSURE_SUCCESS(rv
, rv
);
370 NS_ENSURE_TRUE(resource
, NS_ERROR_NOT_INITIALIZED
);
372 if (quoteId
== resource
->PickId()) {
373 mDebitRate
= aQuote
->PickRate();
377 rv
= mFlow
->GetGiveResource(getter_AddRefs(resource
));
378 NS_ENSURE_SUCCESS(rv
, rv
);
379 NS_ENSURE_TRUE(resource
, NS_ERROR_NOT_INITIALIZED
);
381 NS_ENSURE_TRUE(quoteId
== resource
->PickId(), NS_ERROR_INVALID_ARG
);
383 mCreditRate
= aQuote
->PickRate();
388 aaState::ApplyTransaction(aaITransaction
*aTransaction
, double *aChange
,
391 NS_ENSURE_ARG_POINTER(aTransaction
);
392 NS_ENSURE_TRUE(mFlow
&& mFlow
->PickId(), NS_ERROR_NOT_INITIALIZED
);
393 NS_ENSURE_TRUE(aTransaction
->PickFact(), NS_ERROR_INVALID_ARG
);
396 rv
= setFactSide(aTransaction
->PickFact());
397 NS_ENSURE_SUCCESS(rv
, rv
);
399 rv
= updateTime(aTransaction
->PickFact()->PickTime());
400 NS_ENSURE_SUCCESS(rv
, rv
);
403 rv
= updateValue(aTransaction
->PickValue(), &change
);
404 NS_ENSURE_SUCCESS(rv
, rv
);
406 PRBool hasChange
= !isZero(change
);
407 if (!mFactSide
&& mDebitRate
&& mFlow
->PickTakeResource()->PickId() !=
408 mFlow
->PickGiveResource()->PickId())
415 *aHasChange
= hasChange
;
420 /* Private methods */
422 aaState::setFactSide(aaIFact
*aFact
)
424 NS_ENSURE_ARG_POINTER(aFact
);
426 if (aFact
->PickTakeFrom() &&
427 mFlow
->PickId() == aFact
->PickTakeFrom()->PickId())
431 else if (aFact
->PickGiveTo() &&
432 mFlow
->PickId() == aFact
->PickGiveTo()->PickId())
437 return NS_ERROR_INVALID_ARG
;
441 mOldAmount
= mAmount
; mOldValue
= PickValue();
443 rv
= mFlow
->GetRate(&mRate
);
444 NS_ENSURE_SUCCESS(rv
, rv
);
446 if (mSide
== mFactSide
) {
447 mDiff0
= aFact
->PickAmount();
451 mDiff1
= aFact
->PickAmount() * (mSide
? mRate
: 1 / mRate
);
455 if (!isZero(mAmount
) && mAmount
< 0.0) {
457 mAmount
*= -1 * (mSide
? mRate
: 1 / mRate
);
460 mOldValue
= -mOldValue
;
463 mAmount
= normVal(mAmount
);
464 mDiff0
= normVal(mDiff0
);
465 mDiff1
= normVal(mDiff1
);
471 aaState::updateTime(PRTime time
)
473 NS_ENSURE_TRUE(mStatus
!= PAID
, NS_ERROR_NOT_AVAILABLE
);
474 NS_ENSURE_TRUE(!mStatus
|| mStart
<= time
, NS_ERROR_INVALID_ARG
);
480 else if (mStart
== time
) {
486 mHasPrevTime
= PR_TRUE
;
494 aaState::updateValue(double param
, double *_retval
)
499 mValue
= normVal(mAmount
* mDebitRate
);
502 NS_ENSURE_TRUE(mOldValue
>= 0.0, NS_ERROR_NOT_AVAILABLE
);
503 NS_ENSURE_TRUE(mOldAmount
!= 0.0, NS_ERROR_FAILURE
);
504 mValue
= normVal(mOldValue
* mAmount
/ mOldAmount
);
506 *_retval
= mOldValue
- mValue
;
510 mValue
= normVal(mAmount
* mCreditRate
);
513 NS_ENSURE_TRUE(mDebitRate
, NS_ERROR_INVALID_ARG
);
514 mValue
= normVal(mAmount
* mDebitRate
* mRate
);
516 *_retval
= mValue
- mOldValue
;
522 mValue
= normVal(mAmount
* mDebitRate
);
523 *_retval
= mValue
- mOldValue
- param
;
526 NS_ENSURE_TRUE(param
!= 0.0, NS_ERROR_INVALID_ARG
);
527 mValue
= mOldValue
+ param
;
532 mValue
= normVal(mAmount
* mCreditRate
);
535 NS_ENSURE_TRUE(mOldValue
> 0.0, NS_ERROR_NOT_AVAILABLE
);
536 NS_ENSURE_TRUE(mOldAmount
!= 0.0, NS_ERROR_FAILURE
);
537 mValue
= normVal(mOldValue
* mAmount
/ mOldAmount
);
539 *_retval
= mOldValue
- mValue
- param
;
547 aaState::useRules(aaIFact
*aFact
)
549 if (aFact
->PickAmount() < 0.0)
553 nsCOMPtr
<nsIArray
> ruleSet
= do_QueryInterface(mFlow
, &rv
);
554 NS_ENSURE_SUCCESS(rv
, rv
);
557 rv
= ruleSet
->GetLength(&count
);
558 NS_ENSURE_SUCCESS(rv
, rv
);
560 nsCOMPtr
<aaIRule
> rule
;
561 for (i
= 0; i
< count
; i
++) {
562 rule
= do_QueryElementAt(ruleSet
, i
, &rv
);
563 NS_ENSURE_SUCCESS(rv
, rv
);
565 PRBool factSide
, changeSide
;
566 rv
= rule
->GetFactSide(&factSide
);
567 NS_ENSURE_SUCCESS(rv
, rv
);
569 rv
= rule
->GetChangeSide(&changeSide
);
570 NS_ENSURE_SUCCESS(rv
, rv
);
572 if (factSide
== mFactSide
) {
573 if (!isZero(mDiff0
) && !changeSide
) {
574 rv
= aFact
->UseRule(rule
, mDiff0
);
575 NS_ENSURE_SUCCESS(rv
, rv
);
577 else if (!isZero(mDiff1
) && changeSide
) {
578 rv
= aFact
->UseRule(rule
, mDiff1
);
579 NS_ENSURE_SUCCESS(rv
, rv
);