transport: empty test for sqlite converter
[abstract.git] / base / aaState.cpp
blob1a53aa97078771db8095d69efb2fd05b010713d2
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: */
3 /*
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"
24 #include "nsCOMPtr.h"
25 #include "nsIArray.h"
26 #include "nsArrayUtils.h"
28 /* Project includes */
29 #include "aaAmountUtils.h"
30 #include "aaIFlow.h"
31 #include "aaIFact.h"
32 #include "aaIRule.h"
33 #include "aaIResource.h"
34 #include "aaIQuote.h"
35 #include "aaITransaction.h"
36 #include "aaIStorager.h"
38 #include "aaState.h"
40 aaState::aaState()
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)
47 aaState::~aaState()
51 NS_IMPL_ISUPPORTS3(aaState,
52 aaIDataNode,
53 aaIState,
54 aaIBalance)
55 /* aaIDataNode */
56 NS_IMETHODIMP
57 aaState::GetId(PRInt64 *aId)
59 NS_ENSURE_ARG_POINTER(aId);
60 *aId = mId;
61 return NS_OK;
63 NS_IMETHODIMP
64 aaState::SetId(PRInt64 aId)
66 mId = aId;
67 return NS_OK;
70 NS_IMETHODIMP
71 aaState::Accept(aaIHandler* aQuery)
73 NS_ENSURE_ARG_POINTER(aQuery);
74 return NS_ERROR_NOT_AVAILABLE;
77 NS_IMETHODIMP
78 aaState::GetEdited(PRBool* aEdited)
80 NS_ENSURE_ARG_POINTER(aEdited);
81 return NS_ERROR_NOT_AVAILABLE;
84 NS_IMETHODIMP
85 aaState::Sync(aaIStorager *aStorager, aaISqliteChannel *aChannel)
87 nsresult rv;
89 NS_ENSURE_TRUE(mStatus >= NEW, NS_ERROR_NOT_INITIALIZED);
90 if (mStatus < NEW)
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);
102 return NS_OK;
104 else {
105 rv = aStorager->Update(aChannel);
106 NS_ENSURE_SUCCESS(rv, rv);
108 return NS_OK;
112 if (!isZero(PickAmount())) {
113 rv = aStorager->Insert(aChannel);
114 NS_ENSURE_SUCCESS(rv, rv);
117 return NS_OK;
120 /* aaIState */
121 NS_IMETHODIMP
122 aaState::GetFlow(aaIFlow* *aFlow)
124 NS_ENSURE_ARG_POINTER(aFlow);
125 NS_IF_ADDREF(*aFlow = mFlow);
126 return NS_OK;
128 NS_IMETHODIMP
129 aaState::SetFlow(aaIFlow* aFlow)
131 mFlow = aFlow;
132 return NS_OK;
134 aaIFlow*
135 aaState::PickFlow()
137 return mFlow;
140 NS_IMETHODIMP
141 aaState::GetResource(aaIResource* *aResource)
143 NS_ENSURE_TRUE(mFlow, NS_ERROR_NOT_INITIALIZED);
144 if (mSide)
145 return mFlow->GetTakeResource(aResource);
147 return mFlow->GetGiveResource(aResource);
150 NS_IMETHODIMP
151 aaState::GetSide(PRBool *aSide)
153 NS_ENSURE_ARG_POINTER(aSide);
154 *aSide = mSide;
155 return NS_OK;
157 NS_IMETHODIMP
158 aaState::SetSide(PRBool aSide)
160 mSide = aSide;
161 return NS_OK;
163 PRBool
164 aaState::PickSide()
166 return mSide;
169 NS_IMETHODIMP
170 aaState::GetAmount(double *aAmount)
172 NS_ENSURE_ARG_POINTER(aAmount);
173 *aAmount = mAmount;
174 return NS_OK;
176 NS_IMETHODIMP
177 aaState::SetAmount(double aAmount)
179 mAmount = aAmount;
180 return NS_OK;
182 double
183 aaState::PickAmount()
185 return mAmount;
188 NS_IMETHODIMP
189 aaState::GetStart(PRTime *aStart)
191 NS_ENSURE_ARG_POINTER(aStart);
192 *aStart = mStart;
193 return NS_OK;
195 NS_IMETHODIMP
196 aaState::SetStart(PRTime aStart)
198 mStart = aStart;
199 mStatus = LOADED;
200 return NS_OK;
202 PRTime
203 aaState::PickStart()
205 return mStart;
208 NS_IMETHODIMP
209 aaState::GetEnd(PRTime *aEnd)
211 NS_ENSURE_ARG_POINTER(aEnd);
212 *aEnd = mEnd;
213 return NS_OK;
215 NS_IMETHODIMP
216 aaState::SetEnd(PRTime aEnd)
218 NS_ENSURE_TRUE(mStatus == LOADED, NS_ERROR_NOT_INITIALIZED);
219 mEnd = aEnd;
220 mStatus = PAID;
221 return NS_OK;
223 PRTime
224 aaState::PickEnd()
226 return mEnd;
229 NS_IMETHODIMP
230 aaState::GetIsPaid(PRBool *aIsPaid)
232 NS_ENSURE_ARG_POINTER(aIsPaid);
233 *aIsPaid = PickIsPaid();
234 return NS_OK;
236 PRBool
237 aaState::PickIsPaid()
239 return (mStatus == PAID);
242 NS_IMETHODIMP
243 aaState::GetPrevTime(PRTime *aPrevTime )
245 NS_ENSURE_ARG_POINTER(aPrevTime);
246 NS_ENSURE_TRUE(mHasPrevTime, NS_ERROR_NOT_INITIALIZED);
247 *aPrevTime = mPrevTime;
248 return NS_OK;
251 NS_IMETHODIMP
252 aaState::ApplyFact(aaIFact *aFact)
254 NS_ENSURE_TRUE(mFlow && mFlow->PickId(), NS_ERROR_NOT_INITIALIZED);
256 nsresult rv;
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);
270 return NS_OK;
272 NS_IMETHODIMP
273 aaState::GetEventId(PRInt64 *aEventId)
275 NS_ENSURE_ARG_POINTER(aEventId);
276 NS_ENSURE_TRUE(mEventId, NS_ERROR_NOT_INITIALIZED);
277 *aEventId = mEventId;
278 return NS_OK;
280 NS_IMETHODIMP
281 aaState::GetFactId(PRInt64 *aFactId)
283 NS_ENSURE_ARG_POINTER(aFactId);
284 NS_ENSURE_TRUE(mEventId, NS_ERROR_NOT_INITIALIZED);
285 *aFactId = mFactId;
286 return NS_OK;
288 NS_IMETHODIMP
289 aaState::GetFactSide(PRBool *aFactSide)
291 NS_ENSURE_ARG_POINTER(aFactSide);
292 NS_ENSURE_TRUE(mEventId, NS_ERROR_NOT_INITIALIZED);
293 *aFactSide = mFactSide;
294 return NS_OK;
297 NS_IMETHODIMP
298 aaState::GetValue(double *aValue)
300 NS_ENSURE_ARG_POINTER(aValue);
301 *aValue = PickValue();
302 return NS_OK;
304 NS_IMETHODIMP
305 aaState::SetInitValue(double aValue)
307 mValue = aValue;
308 return NS_OK;
310 double
311 aaState::PickValue()
313 if (!mFlow || !mFlow->PickId())
314 return mValue;
316 if (mSide)
317 return mDebitRate ? normVal(mAmount * mDebitRate) : mValue;
319 return mCreditRate ? normVal(mAmount * mCreditRate) : mValue;
322 NS_IMETHODIMP
323 aaState::GetCreditDiff(double *aDiff)
325 NS_ENSURE_ARG_POINTER(aDiff);
326 NS_ENSURE_TRUE(mFlow, NS_ERROR_NOT_INITIALIZED);
327 *aDiff = PickCreditDiff();
328 return NS_OK;
330 double
331 aaState::PickCreditDiff()
333 if (!mFlow)
334 return 0.0;
335 if (!mFlow->PickId())
336 return mCreditRate;
337 return (!mSide && mCreditRate) ? normVal(mAmount * mCreditRate) - mValue : 0.0;
340 NS_IMETHODIMP
341 aaState::GetDebitDiff(double *aDiff)
343 NS_ENSURE_ARG_POINTER(aDiff);
344 NS_ENSURE_TRUE(mFlow, NS_ERROR_NOT_INITIALIZED);
345 *aDiff = PickDebitDiff();
346 return NS_OK;
348 double
349 aaState::PickDebitDiff()
351 if (!mFlow)
352 return 0.0;
353 if (!mFlow->PickId())
354 return mDebitRate;
355 return (mSide && mDebitRate) ? normVal(mAmount * mDebitRate) - mValue : 0.0;
358 NS_IMETHODIMP
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());
365 nsresult rv;
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();
374 return NS_OK;
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();
384 return NS_OK;
387 NS_IMETHODIMP
388 aaState::ApplyTransaction(aaITransaction *aTransaction, double *aChange,
389 PRBool *aHasChange)
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);
395 nsresult rv;
396 rv = setFactSide(aTransaction->PickFact());
397 NS_ENSURE_SUCCESS(rv, rv);
399 rv = updateTime(aTransaction->PickFact()->PickTime());
400 NS_ENSURE_SUCCESS(rv, rv);
402 double change = 0.0;
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())
409 hasChange = PR_TRUE;
411 if (aChange)
412 *aChange = change;
414 if (aHasChange)
415 *aHasChange = hasChange;
417 return NS_OK;
420 /* Private methods */
421 nsresult
422 aaState::setFactSide(aaIFact *aFact)
424 NS_ENSURE_ARG_POINTER(aFact);
426 if (aFact->PickTakeFrom() &&
427 mFlow->PickId() == aFact->PickTakeFrom()->PickId())
429 mFactSide = 1;
431 else if (aFact->PickGiveTo() &&
432 mFlow->PickId() == aFact->PickGiveTo()->PickId())
434 mFactSide = 0;
436 else {
437 return NS_ERROR_INVALID_ARG;
440 nsresult rv;
441 mOldAmount = mAmount; mOldValue = PickValue();
443 rv = mFlow->GetRate(&mRate);
444 NS_ENSURE_SUCCESS(rv, rv);
446 if (mSide == mFactSide) {
447 mDiff0 = aFact->PickAmount();
448 mAmount -= mDiff0;
450 else {
451 mDiff1 = aFact->PickAmount() * (mSide ? mRate : 1 / mRate);
452 mAmount += mDiff1;
455 if (!isZero(mAmount) && mAmount < 0.0) {
456 mSide = !mSide;
457 mAmount *= -1 * (mSide ? mRate : 1 / mRate);
458 mDiff0 = mOldAmount;
459 mDiff1 = mAmount;
460 mOldValue = -mOldValue;
463 mAmount = normVal(mAmount);
464 mDiff0 = normVal(mDiff0);
465 mDiff1 = normVal(mDiff1);
467 return NS_OK;
470 nsresult
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);
476 if (!mStatus) {
477 mStatus = NEW;
478 mStart = time;
480 else if (mStart == time) {
481 mStatus = UPDATE;
483 else {
484 mStatus = REPLACE;
485 mPrevTime = mStart;
486 mHasPrevTime = PR_TRUE;
487 mStart = time;
490 return NS_OK;
493 nsresult
494 aaState::updateValue(double param, double *_retval)
496 if (mFactSide) {
497 if (mSide) {
498 if (mDebitRate) {
499 mValue = normVal(mAmount * mDebitRate);
501 else {
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;
508 else {
509 if (mCreditRate) {
510 mValue = normVal(mAmount * mCreditRate);
512 else {
513 NS_ENSURE_TRUE(mDebitRate, NS_ERROR_INVALID_ARG);
514 mValue = normVal(mAmount * mDebitRate * mRate);
516 *_retval = mValue - mOldValue;
519 else {
520 if (mSide) {
521 if (mDebitRate) {
522 mValue = normVal(mAmount * mDebitRate);
523 *_retval = mValue - mOldValue - param;
525 else {
526 NS_ENSURE_TRUE(param != 0.0, NS_ERROR_INVALID_ARG);
527 mValue = mOldValue + param;
530 else {
531 if (mCreditRate) {
532 mValue = normVal(mAmount * mCreditRate);
534 else {
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;
543 return NS_OK;
546 nsresult
547 aaState::useRules(aaIFact *aFact)
549 if (aFact->PickAmount() < 0.0)
550 return NS_OK;
552 nsresult rv;
553 nsCOMPtr<nsIArray> ruleSet = do_QueryInterface(mFlow, &rv);
554 NS_ENSURE_SUCCESS(rv, rv);
556 PRUint32 i, count;
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);
584 return NS_OK;