001/** 002 * AbstractAccumulator.java 003 * 004 * Copyright (c) 2004-2012, Nicole C. Tedesco. All rights reserved. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 007 * use this file except in compliance with the License. You may obtain a copy of 008 * the License at: 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 015 * License for the specific language governing permissions and limitations under 016 * the License. 017 */ 018 019package net.sf.jaccumulator; 020 021import java.math.BigDecimal; 022import java.math.BigInteger; 023import java.util.Arrays; 024import java.util.Iterator; 025import java.util.NoSuchElementException; 026 027import net.sf.jaccumulator.lex.To; 028import net.sf.jaccumulator.primitives.AbstractPrimitiveWrapper; 029import net.sf.jaccumulator.primitives.Constant; 030import net.sf.jaccumulator.primitives.Primitive; 031import net.sf.jaccumulator.primitives.SealedPrimitive; 032import net.sf.jaccumulator.reals.SealedReal; 033import net.sf.jaccumulator.scalars.SealedScalar; 034import net.sf.jupperware.association.AssociativeList; 035import net.sf.jupperware.association.RandomAccessAssociativeList; 036 037/** 038 * Common {@link Accumulator} behavior 039 * 040 * @param <ACCUMULATOR> 041 * this {@link Accumulator} type 042 * 043 * @since JAccumulator 4.0 044 * @author Nicole Tedesco (<a 045 * href="mailto:nicole@tedesco.name">nicole@tedesco.name</a>) 046 */ 047public abstract class AbstractAccumulator<ACCUMULATOR extends Accumulator<ACCUMULATOR>> 048 extends 049 AbstractPrimitiveWrapper<ACCUMULATOR> 050 implements 051 Accumulator<ACCUMULATOR> 052{ 053 private static final long serialVersionUID = 1510282328430649540L; 054 055 private final AssociativeList<Accumulator<?>,Accumulator<?>> _theMembers; 056 057 public AbstractAccumulator() 058 { 059 this(new RandomAccessAssociativeList<Accumulator<?>,Accumulator<?>>()); 060 } 061 062 public AbstractAccumulator( final Accumulator<?> anAccumulator ) 063 { 064 this(); 065 this.replaceRelationshipsUsing(anAccumulator); 066 } 067 068 public AbstractAccumulator( 069 final AssociativeList<Accumulator<?>,Accumulator<?>> members ) 070 { 071 this._theMembers = members; 072 } 073 074 @Override 075 public ControlIntention apply( final Accumulator<?> aStack ) 076 { 077 return ControlIntention.SUCCESS; 078 } 079 080 @Override 081 public void clear() throws UnsupportedOperationException 082 { 083 this.members().clear(); 084 } 085 086 @Override 087 @SuppressWarnings( "unchecked" ) 088 public ACCUMULATOR clearContents() throws UnsupportedOperationException 089 { 090 this.clear(); 091 return (ACCUMULATOR)this; 092 } 093 094 @Override 095 public ACCUMULATOR copy() 096 { 097 final Primitive<?> aTarget = this.getTarget().copy(); 098 final AssociativeList<Accumulator<?>,Accumulator<?>> assoc = new RandomAccessAssociativeList<Accumulator<?>,Accumulator<?>>( 099 this.members()); 100 return this.copySharing(aTarget, assoc); 101 } 102 103 @Override 104 public ACCUMULATOR copySharing( final Accumulator<?> anAccumulator ) 105 { 106 return this.copySharing(anAccumulator.getTarget(), 107 anAccumulator.members()); 108 } 109 110 @Override 111 public ACCUMULATOR copySharing( 112 final AssociativeList<Accumulator<?>,Accumulator<?>> members ) 113 { 114 final Primitive<?> aTarget = this.getTarget().copy(); 115 return this.copySharing(aTarget, members); 116 } 117 118 @Override 119 public ACCUMULATOR copySharing( final Primitive<?> aTarget ) 120 { 121 final AssociativeList<Accumulator<?>,Accumulator<?>> assoc = new RandomAccessAssociativeList<Accumulator<?>,Accumulator<?>>( 122 this.members()); 123 return this.copySharing(aTarget, assoc); 124 } 125 126 @Override 127 public ACCUMULATOR copyUsing( final BigDecimal aValue ) 128 { 129 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 130 return this.copySharing(aTarget); 131 } 132 133 @Override 134 public ACCUMULATOR copyUsing( final BigInteger aValue ) 135 { 136 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 137 return this.copySharing(aTarget); 138 } 139 140 @Override 141 public ACCUMULATOR copyUsing( final boolean aValue ) 142 { 143 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 144 return this.copySharing(aTarget); 145 } 146 147 @Override 148 public ACCUMULATOR copyUsing( final byte aValue ) 149 { 150 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 151 return this.copySharing(aTarget); 152 } 153 154 @Override 155 public ACCUMULATOR copyUsing( final char aValue ) 156 { 157 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 158 return this.copySharing(aTarget); 159 } 160 161 @Override 162 public ACCUMULATOR copyUsing( final double aValue ) 163 { 164 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 165 return this.copySharing(aTarget); 166 } 167 168 @Override 169 public ACCUMULATOR copyUsing( final float aValue ) 170 { 171 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 172 return this.copySharing(aTarget); 173 } 174 175 @Override 176 public ACCUMULATOR copyUsing( final int aValue ) 177 { 178 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 179 return this.copySharing(aTarget); 180 } 181 182 @Override 183 public ACCUMULATOR copyUsing( final long aValue ) 184 { 185 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 186 return this.copySharing(aTarget); 187 } 188 189 @Override 190 public ACCUMULATOR copyUsing( final short aValue ) 191 { 192 final Primitive<?> aTarget = this.getTarget().copyUsing(aValue); 193 return this.copySharing(aTarget); 194 } 195 196 @Override 197 public ACCUMULATOR copyUsingAccumulator( 198 final SealedAccumulator<?> anAccumulator ) 199 { 200 final Primitive<?> aTarget = anAccumulator.getTarget().copy(); 201 final AssociativeList<Accumulator<?>,Accumulator<?>> assoc = new RandomAccessAssociativeList<Accumulator<?>,Accumulator<?>>( 202 anAccumulator.members()); 203 return this.copySharing(aTarget, assoc); 204 } 205 206 @Override 207 public ACCUMULATOR copyUsingPrimitive( final SealedPrimitive<?> aValue ) 208 { 209 final Primitive<?> aTarget = this.getTarget().copyUsingPrimitive(aValue); 210 return this.copySharing(aTarget); 211 } 212 213 @Override 214 public ACCUMULATOR copyUsingReal( final SealedReal<?> aValue ) 215 { 216 final Primitive<?> aTarget = this.getTarget().copyUsingReal(aValue); 217 return this.copySharing(aTarget); 218 } 219 220 @Override 221 public ACCUMULATOR copyUsingScalar( final SealedScalar<?> aValue ) 222 { 223 final Primitive<?> aTarget = this.getTarget().copyUsingScalar(aValue); 224 return this.copySharing(aTarget); 225 } 226 227 @Override 228 public ACCUMULATOR copyUsingText( final CharSequence aValue ) 229 { 230 final Primitive<?> aTarget = this.getTarget().copyUsingText(aValue); 231 return this.copySharing(aTarget); 232 } 233 234 @Override 235 public boolean equals( final Object anObject ) 236 { 237 if (this == anObject) return true; 238 try { 239 final Accumulator<?> anAccumulator = (Accumulator<?>)anObject; 240 return this.isEqualToAccumulator(anAccumulator); 241 } catch (final ClassCastException ex) { 242 } 243 return false; 244 } 245 246 @Override 247 public Accumulator<?> first() throws NoSuchElementException 248 { 249 if (this.members().isEmpty()) throw new NoSuchElementException(); 250 return this.members().get(0); 251 } 252 253 @Override 254 public Domain getDomain() 255 { 256 return Domain.ALGEBRAIC; 257 } 258 259 @Override 260 public StructureStrategy getStructureStrategy() 261 { 262 return StructureStrategy.ALGEBRAIC; 263 } 264 265 @Override 266 public int hashCode() 267 { 268 final Object[] a = { this.getTarget(), this.members() }; 269 return Arrays.hashCode(a); 270 } 271 272 @Override 273 public boolean isConfigurable() 274 { 275 return true; 276 } 277 278 @Override 279 public boolean isCountable() 280 { 281 return true; 282 } 283 284 @Override 285 public boolean isElastic() 286 { 287 return true; 288 } 289 290 @Override 291 public boolean isEmpty() 292 { 293 return this.members().isEmpty(); 294 } 295 296 @Override 297 public boolean isEqualToAccumulator( 298 final SealedAccumulator<?> anAccumulator ) 299 { 300 if (this == anAccumulator) return true; 301 if (this.isEqualToPrimitive(anAccumulator)) 302 return this.members().equals(anAccumulator.members()); 303 return false; 304 } 305 306 @Override 307 public boolean isExpandable() 308 { 309 return true; 310 } 311 312 @Override 313 public boolean isOrdered() 314 { 315 return false; 316 } 317 318 @Override 319 public boolean isReducible() 320 { 321 return true; 322 } 323 324 @Override 325 public boolean isUnique() 326 { 327 return false; 328 } 329 330 @Override 331 public Iterator<Accumulator<?>> iterator() 332 { 333 return this.members().iterator(); 334 } 335 336 @Override 337 public Accumulator<?> last() throws NoSuchElementException 338 { 339 final int lastIndex = this.members().size() - 1; 340 if (lastIndex < 0) throw new NoSuchElementException(); 341 return this.members().get(lastIndex); 342 } 343 344 @Override 345 public long longSize() 346 { 347 return this.size(); 348 } 349 350 @Override 351 public final AssociativeList<Accumulator<?>,Accumulator<?>> members() 352 { 353 return this._theMembers; 354 } 355 356 @Override 357 public Accumulator<?> peek() throws NoSuchElementException 358 { 359 return this.last(); 360 } 361 362 @Override 363 public Accumulator<?> pop() 364 throws UnsupportedOperationException, 365 IllegalStateException, 366 NoSuchElementException 367 { 368 if (this.members().isEmpty()) throw new NoSuchElementException(); 369 final int lastIndex = this.members().size() - 1; 370 final Accumulator<?> acc = this.members().remove(lastIndex); 371 return acc; 372 } 373 374 @Override 375 @SuppressWarnings( "unchecked" ) 376 public ACCUMULATOR push( final Accumulator<?> aMember ) 377 throws UnsupportedOperationException, 378 NullPointerException, 379 IllegalStateException 380 { 381 this.members().add(aMember); 382 return (ACCUMULATOR)this; 383 } 384 385 @Override 386 @SuppressWarnings( "unchecked" ) 387 public ACCUMULATOR push( 388 final Accumulator<?> aKey, 389 final Accumulator<?> aMember ) 390 throws UnsupportedOperationException, 391 NullPointerException, 392 IllegalStateException 393 { 394 final int lastIndex = this.members().size(); 395 this.members().putAt(lastIndex, aKey, aMember); 396 return (ACCUMULATOR)this; 397 } 398 399 @Override 400 public ACCUMULATOR push( final BigDecimal aMember ) 401 throws UnsupportedOperationException, 402 NullPointerException, 403 IllegalStateException 404 { 405 return this.push(new SimpleAccumulator(aMember)); 406 } 407 408 @Override 409 public ACCUMULATOR push( final BigInteger aMember ) 410 throws UnsupportedOperationException, 411 NullPointerException, 412 IllegalStateException 413 { 414 return this.push(new SimpleAccumulator(aMember)); 415 } 416 417 @Override 418 public ACCUMULATOR push( final boolean aMember ) 419 throws UnsupportedOperationException, 420 NullPointerException, 421 IllegalStateException 422 { 423 return this.push(new SimpleAccumulator(aMember)); 424 } 425 426 @Override 427 public ACCUMULATOR push( final byte aMember ) 428 throws UnsupportedOperationException, 429 NullPointerException, 430 IllegalStateException 431 { 432 return this.push(new SimpleAccumulator(aMember)); 433 } 434 435 @Override 436 public ACCUMULATOR push( final char aMember ) 437 throws UnsupportedOperationException, 438 NullPointerException, 439 IllegalStateException 440 { 441 return this.push(new SimpleAccumulator(aMember)); 442 } 443 444 @Override 445 public ACCUMULATOR push( final double aMember ) 446 throws UnsupportedOperationException, 447 NullPointerException, 448 IllegalStateException 449 { 450 return this.push(new SimpleAccumulator(aMember)); 451 } 452 453 @Override 454 public ACCUMULATOR push( final float aMember ) 455 throws UnsupportedOperationException, 456 NullPointerException, 457 IllegalStateException 458 { 459 return this.push(new SimpleAccumulator(aMember)); 460 } 461 462 @Override 463 public ACCUMULATOR push( final int aMember ) 464 throws UnsupportedOperationException, 465 NullPointerException, 466 IllegalStateException 467 { 468 return this.push(new SimpleAccumulator(aMember)); 469 } 470 471 @Override 472 public ACCUMULATOR push( final long aMember ) 473 throws UnsupportedOperationException, 474 NullPointerException, 475 IllegalStateException 476 { 477 return this.push(new SimpleAccumulator(aMember)); 478 } 479 480 @Override 481 public ACCUMULATOR push( final short aMember ) 482 throws UnsupportedOperationException, 483 NullPointerException, 484 IllegalStateException 485 { 486 return this.push(new SimpleAccumulator(aMember)); 487 } 488 489 @Override 490 public ACCUMULATOR push( final String aKey, final Accumulator<?> aMember ) 491 throws UnsupportedOperationException, 492 NullPointerException, 493 IllegalStateException 494 { 495 return this.push(new SimpleAccumulator(Constant.valueOfText(aKey)), 496 aMember); 497 } 498 499 @Override 500 public ACCUMULATOR pushPrimitive( final Primitive<?> aMember ) 501 throws UnsupportedOperationException, 502 NullPointerException, 503 IllegalStateException 504 { 505 return this.push(new SimpleAccumulator(aMember)); 506 } 507 508 @Override 509 public ACCUMULATOR pushText( final CharSequence aMember ) 510 throws UnsupportedOperationException, 511 NullPointerException, 512 IllegalStateException 513 { 514 return this.push(new SimpleAccumulator(aMember.toString())); 515 } 516 517 @Override 518 @SuppressWarnings( "unchecked" ) 519 public ACCUMULATOR replaceRelationshipsUsing( 520 final Accumulator<?> anAccumulator ) 521 throws UnsupportedOperationException, 522 NullPointerException, 523 IllegalStateException, 524 IllegalArgumentException 525 { 526 final AssociativeList<Accumulator<?>,Accumulator<?>> myMembers = this.members(); 527 final AssociativeList<Accumulator<?>,Accumulator<?>> m = anAccumulator.members(); 528 myMembers.clear(); 529 final int mSize = m.size(); 530 for (int i = 0; i < mSize; i++) { 531 final Accumulator<?> aKey = m.getKeyAt(i); 532 final Accumulator<?> aValue = m.get(i); 533 myMembers.put(aKey, aValue); 534 } 535 return (ACCUMULATOR)this; 536 } 537 538 @Override 539 @SuppressWarnings( "unchecked" ) 540 public ACCUMULATOR setAccumulator( final Accumulator<?> anAccumulator ) 541 throws UnsupportedOperationException, 542 NullPointerException, 543 IllegalStateException, 544 IllegalArgumentException 545 { 546 final Primitive<?> myTarget = this.getTarget(); 547 this.shareTarget(anAccumulator.getTarget()); 548 try { 549 this.replaceRelationshipsUsing(anAccumulator); 550 } catch (final Exception ex) { 551 this.shareTarget(myTarget); 552 throw ex; 553 } 554 return (ACCUMULATOR)this; 555 } 556 557 @Override 558 public ACCUMULATOR shareTargetWith( final Accumulator<?> anAccumulator ) 559 throws UnsupportedOperationException, 560 NullPointerException, 561 IllegalStateException, 562 IllegalArgumentException 563 { 564 return this.shareTarget(anAccumulator.getTarget()); 565 } 566 567 @Override 568 public int size() 569 { 570 return this.members().size(); 571 } 572 573 @Override 574 public Accumulator<?> toAccumulator() 575 { 576 return this.copy(); 577 } 578 579 @Override 580 public String toFunctionName() 581 { 582 return "nop"; 583 } 584 585 @Override 586 public String toString() 587 { 588 final StringBuilder sb = new StringBuilder(this.toFunctionName()); 589 sb.append('('); 590 sb.append(To.toExternalString(this.getTarget())); 591 sb.append(", "); 592 sb.append(this.members()); 593 sb.append(')'); 594 595 return sb.toString(); 596 } 597}