gt:             final List<Position> positionList = slicerAxis.getPositions();
context: /*
  // $Id$
  // This software is subject to the terms of the Eclipse Public License v1.0
  // Agreement, available at the following URL:
  // http://www.eclipse.org/legal/epl-v10.html.
  // Copyright (C) 2001-2002 Kana Software, Inc.
  // Copyright (C) 2001-2009 Julian Hyde and others
  // All Rights Reserved.
  // You must accept the terms of that agreement to use this software.
  //
  // jhyde, 10 August, 2001
  */
  
  package mondrian.rolap;
  
  import mondrian.calc.*;
  import mondrian.calc.impl.ValueCalc;
  import mondrian.calc.impl.GenericCalc;
  import mondrian.olap.*;
  import mondrian.olap.DimensionType;
  import mondrian.olap.fun.*;
  import mondrian.olap.type.*;
  import mondrian.resource.MondrianResource;
  import mondrian.rolap.agg.AggregationManager;
  import mondrian.util.ConcatenableList;
  import mondrian.util.Format;
  import mondrian.util.ObjectPool;
  import mondrian.mdx.*;
  
  import org.apache.log4j.Logger;
  
  import java.util.*;
  
  /**
   * A <code>RolapResult</code> is the result of running a query.
   *
   * @author jhyde
   * @since 10 August, 2001
   * @version $Id$
   */
  public class RolapResult extends ResultBase {
  
      static final Logger LOGGER = Logger.getLogger(ResultBase.class);
  
      private RolapEvaluator evaluator;
      private final CellKey point;
  
      private CellInfoContainer cellInfos;
      private FastBatchingCellReader batchingReader;
      private final CellReader aggregatingReader =
          AggregationManager.instance().getCacheCellReader();
      private Modulos modulos = null;
      private final int maxEvalDepth =
              MondrianProperties.instance().MaxEvalDepth.get();
  
      private final Map<Integer, Boolean> positionsHighCardinality =
          new HashMap<Integer, Boolean>();
      private final Map<Integer, Iterator<Position>> positionsIterators =
          new HashMap<Integer, Iterator<Position>>();
      private final Map<Integer, Integer> positionsIndexes =
          new HashMap<Integer, Integer>();
      private final Map<Integer, List<Position>> positionsCurrent =
          new HashMap<Integer, List<Position>>();
  
      /**
       * Creates a RolapResult.
       *
       * @param query Query
       * @param execute Whether to execute the query
       */
      RolapResult(final Query query, boolean execute) {
          super(query, new Axis[query.axes.length]);
  
          this.point = CellKey.Generator.newCellKey(query.axes.length);
          final int expDeps =
              MondrianProperties.instance().TestExpDependencies.get();
          if (expDeps > 0) {
              this.evaluator = new RolapDependencyTestingEvaluator(this, expDeps);
          } else {
              final RolapEvaluatorRoot root =
                  new RolapResultEvaluatorRoot(this);
              this.evaluator = new RolapEvaluator(root);
          }
          RolapCube cube = (RolapCube) query.getCube();
          this.batchingReader = new FastBatchingCellReader(cube);
  
          this.cellInfos =
              (query.axes.length > 4)
                  ? new CellInfoMap(point)
                  : new CellInfoPool(query.axes.length);
  
          if (!execute) {
              return;
          }
  
          boolean normalExecution = true;
          try {
              // This call to clear the cube's cache only has an
              // effect if caching has been disabled, otherwise
              // nothing happens.
              // Clear the local cache before a query has run
              cube.clearCachedAggregations();
              // Check if there are modifications to the global aggregate cache
              cube.checkAggregateModifications();
  
  
              /////////////////////////////////////////////////////////////////
              //
              // Evaluation Algorithm
              //
              // There are three basic steps to the evaluation algorithm:
              // 1) Determine all Members for each axis but do not save
              // information (do not build the RolapAxis),
              // 2) Save all Members for each axis (build RolapAxis).
              // 3) Evaluate and store each Cell determined by the Members
              // of the axes.
              // Step 1 converges on the stable set of Members pre axis.
              // Steps 1 and 2 make sure that the data has been loaded.
              //
              // More detail follows.
              //
              // Explicit and Implicit Members:
              // A Member is said to be 'explicit' if it appears on one of
              // the Axes (one of the RolapAxis Position List of Members).
              // A Member is 'implicit' if it is in the query but does not
              // end up on any Axes (its usage, for example, is in a function).
              // When for a Dimension none of its Members are explicit in the
              // query, then the default Member is used which is like putting
              // the Member in the Slicer.
              //
              // Special Dimensions:
              // There are 2 special dimensions.
              // The first is the Time dimension. If in a schema there is
              // no ALL Member, then Whatever happens to be the default
              // Member is used if Time Members are not explicitly set
              // in the query.
              // The second is the Measures dimension. This dimension
              // NEVER has an ALL Member. A cube's default Measure is set
              // by convention - its simply the first Measure defined in the
              // cube.
              //
              // First a RolapEvaluator is created. During its creation,
              // it gets a Member from each Hierarchy. Each Member is the
              // default Member of the Hierarchy. For most Hierarchies this
              // Member is the ALL Member, but there are cases where 1)
              // a Hierarchy does not have an ALL Member or 2) the Hierarchy
              // has an ALL Member but that Member is not the default Member.
              // In these cases, the default Member is still used, but its
              // use can cause evaluation issues (seemingly strange evaluation
              // results).
              //
              // Next, load all root Members for Hierarchies that have no ALL
              // Member and load ALL Members that are not the default Member.
              //
              // Determine the Members of the Slicer axis (Step 1 above).  Any
              // Members found are added to the AxisMember object. If one of these
              // Members happens to be a Measure, then the Slicer is explicitly
              // specifying the query's Measure and this should be put into the
              // evaluator's context (replacing the default Measure which just
              // happens to be the first Measure defined in the cube).  Other
              // Members found in the AxisMember object are also placed into the
              // evaluator's context since these also are explicitly specified.
              // Also, any other Members in the AxisMember object which have the
              // same Hierarchy as Members in the list of root Members for
              // Hierarchies that have no ALL Member, replace those Members - they
              // Slicer has explicitly determined which ones to use. The
              // AxisMember object is now cleared.
              // The Slicer does not depend upon the other Axes, but the other
              // Axes depend upon both the Slicer and each other.
              //
              // The AxisMember object also checks if the number of Members
              // exceeds the ResultLimit property throwing a
              // TotalMembersLimitExceeded Exception if it does.
              //
              // For all non-Slicer axes, the Members are determined (Step 1
              // above). If a Measure is found in the AxisMember, then an
              // Axis is explicitly specifying a Measure.
              // If any Members in the AxisMember object have the same Hierarchy
              // as a Member in the set of root Members for Hierarchies that have
              // no ALL Member, then replace those root Members with the Member
              // from the AxisMember object. In this case, again, a Member
              // was explicitly specified in an Axis. If this replacement
              // occurs, then one must redo this step with the new Members.
              //
              // Now Step 3 above is done. First to the Slicer Axis and then
              // to the other Axes. Here the Axes are actually generated.
              // If a Member of an Axis is an Calculated Member (and the
              // Calculated Member is not a Member of the Measure Hierarchy),
              // then find the Dimension associated with the Calculated
              // Member and remove Members with the same Dimension in the set of
              // root Members for Hierarchies that have no ALL Member.
              // This is done because via the Calculated Member the Member
              // was implicitly specified in the query. If this removal occurs,
              // then the Axes must be re-evaluated repeating Step 3.
              //
              /////////////////////////////////////////////////////////////////
  
  
              // The AxisMember object is used to hold Members that are found
              // during Step 1 when the Axes are determined.
              final AxisMember axisMembers = new AxisMember();
  
  
              // list of ALL Members that are not default Members
              final List<Member> nonDefaultAllMembers = new ArrayList<Member>();
  
              // List of Members of Hierarchies that do not have an ALL Member
              List<List<Member>> nonAllMembers = new ArrayList<List<Member>>();
  
              // List of Measures
              final List<Member> measureMembers = new ArrayList<Member>();
  
              // load all root Members for Hierarchies that have no ALL
              // Member and load ALL Members that are not the default Member.
              // Also, all Measures are are gathered.
              loadSpecialMembers(
                  nonDefaultAllMembers, nonAllMembers, measureMembers);
  
              // clear evaluation cache
              query.clearEvalCache();
  
              // Save, may be needed by some Expression Calc's
              query.putEvalCache("ALL_MEMBER_LIST", nonDefaultAllMembers);
  
  
              final List<List<Member>> emptyNonAllMembers =
                  Collections.emptyList();
  
              /////////////////////////////////////////////////////////////////
              // Determine Slicer
              //
              axisMembers.setSlicer(true);
              loadMembers(
                  emptyNonAllMembers,
                  evaluator,
                  query.slicerAxis,
                  query.slicerCalc,
                  axisMembers);
              axisMembers.setSlicer(false);
  
              // Save unadulterated context for the next time we need to evaluate
              // the slicer.
              final RolapEvaluator savedEvaluator = evaluator.push();
  
              if (!axisMembers.isEmpty()) {
                  for (Member m : axisMembers) {
                      if (m == null) {
                          break;
                      }
                      evaluator.setSlicerContext(m);
                      if (m.isMeasure()) {
                          // A Measure was explicitly declared in the
                          // Slicer, don't need to worry about Measures
                          // for this query.
                          measureMembers.clear();
                      }
                  }
                  replaceNonAllMembers(nonAllMembers, axisMembers);
                  axisMembers.clearMembers();
              }
  
              /////////////////////////////////////////////////////////////////
              // Determine Axes
              //
              boolean changed = false;
  
              // reset to total member count
              axisMembers.clearTotalCellCount();
  
              for (int i = 0; i < axes.length; i++) {
                  final QueryAxis axis = query.axes[i];
                  final Calc calc = query.axisCalcs[i];
                  loadMembers(
                      emptyNonAllMembers, evaluator, axis, calc, axisMembers);
              }
  
              if (!axisMembers.isEmpty()) {
                  for (Member m : axisMembers) {
                      if (m.isMeasure()) {
                          // A Measure was explicitly declared on an
                          // axis, don't need to worry about Measures
                          // for this query.
                          measureMembers.clear();
                      }
                  }
                  changed = replaceNonAllMembers(nonAllMembers, axisMembers);
                  axisMembers.clearMembers();
              }
  
              if (changed) {
                  // only count number of members, do not collect any
                  axisMembers.countOnly(true);
                  // reset to total member count
                  axisMembers.clearTotalCellCount();
  
                  for (int i = 0; i < axes.length; i++) {
                      final QueryAxis axis = query.axes[i];
                      final Calc calc = query.axisCalcs[i];
                      loadMembers(
                          nonAllMembers,
                          evaluator.push(),
                          axis, calc, axisMembers);
                  }
              }
  
              // throws exception if number of members exceeds limit
              axisMembers.checkLimit();
  
              /////////////////////////////////////////////////////////////////
              // Execute Slicer
              //
              this.slicerAxis =
                  evalExecute(
                      nonAllMembers,
                      nonAllMembers.size() - 1,
                      savedEvaluator,
                      query.slicerAxis,
                      query.slicerCalc);
  
              // Use the context created by the slicer for the other
              // axes.  For example, "select filter([Customers], [Store
              // Sales] > 100) on columns from Sales where
              // ([Time].[1998])" should show customers whose 1998 (not
              // total) purchases exceeded 100.
  
              // Getting the Position list's size and the Position
              // at index == 0 will, in fact, cause an Iterable-base
              // Axis Position List to become a List-base Axis
              // Position List (and increase memory usage), but for
              // the slicer axis, the number of Positions is (generally) very
              // small, so who cares.
  