ヘッダーをスキップ
Oracle OLAP Java API開発者ガイド
11g リリース1(11.1)
E05733-01
  目次へ
目次
索引へ
索引

前へ
前へ
 
次へ
次へ
 

10 動的問合せの作成

この章では、動的問合せの作成に使用するOracle OLAP Java APIのTemplateクラスおよびその関連クラスについて説明します。また、それらのクラスの実装例を示します。

この章では、次の項目について説明します。

Templateオブジェクトの概要

Templateクラスは、Oracle OLAP Java APIの強力な機能の基礎となります。Templateオブジェクトを使用して、変更可能なSourceオブジェクトを作成します。これらのSourceオブジェクトを使用すると、エンド・ユーザーの選択に応じて変更可能な動的問合せを作成できます。Templateオブジェクトを使用すると、ユーザー・インタフェース要素をOLAP Java APIの操作およびオブジェクトに簡単に変換できます。

次の項では、これらの機能について概説します。この章の後半では、動的Sourceオブジェクトの作成に使用するTemplateクラスおよびその他のクラスについて説明します。動的Sourceへの変更、およびこれらの変更の保存や廃棄に使用するTransactionオブジェクトの詳細は、第7章「TransactionProviderの使用方法」を参照してください。

動的Sourceの作成

Templateの主な特徴は、動的Sourceを作成できる点にあります。この機能は、Templateによって使用される他のオブジェクトのうち、DynamicDefinitionクラスおよびMetadataStateクラスのインスタンスに基づいています。

Sourceを作成すると、SourceDefinitionが自動的に関連付けられます。SourceDefinitionには、そのSourceに関する情報が含まれています。Sourceは、作成後はSourceDefinitionに永続的に関連付けられます。SourceDefinitiongetSourceメソッドを使用すると、関連付けられているSourceが戻されます。

DynamicDefinitionは、SourceDefinitionのサブクラスです。Templateは、Templateによって作成されたSourceSourceDefinitionのプロキシとして機能するDynamicDefinitionを作成します。これは、DynamicDefinitiongetSourceメソッドが、永続的に関連付けられている同じSourceを常に取得するのではなく、Templateによって現在作成されているSourceを取得することを意味します。取得されたSourceが異なる場合でも、DynamicDefinitionのインスタンスは変更されません。

Templateによって作成されたSourceは変更可能です。これは、TemplateSourceの作成に使用された値(他のSourceオブジェクトを含む)が変更可能であるためです。Templateは、これらの値をMetadataStateに格納します。Templateには、MetadataStateの現在の状態の取得、値の取得または設定、および状態の設定を行うメソッドが含まれています。これらのメソッドを使用して、MetadataStateに格納されたデータ値を変更します。

DynamicDefinitionを使用して、Templateによって作成されたSourceを取得します。アプリケーションがTemplateSourceの作成に使用された値の状態を(たとえばエンド・ユーザーの選択に応じて)変更した場合、新しいSourceで以前のSourceとは異なる結果セットが定義されている場合でも、同じDynamicDefinitionを使用してSourceを再度取得します。

Templateによって作成されたSourceは、他のSourceオブジェクトを作成する一連のSourceの操作(たとえば、選択、ソート、計算および結合の一連の操作)の結果になる可能性があります。これらの操作のコードを、Template用のSourceGeneratorgenerateSourceメソッドに格納します。このメソッドは、Templateによって作成されたSourceを戻します。この操作では、MetadataStateに格納されたデータが使用されます。

様々なTemplateオブジェクトによって作成された動的Sourceオブジェクトが相互に作用する複雑な問合せを作成する場合があります。この問合せを作成すると、複雑な問合せ全体を定義するSourceが作成されます。最終のSourceの作成に使用したTemplateオブジェクトのいずれかの状態を変更する場合、最終のSourceは以前のSourceとは異なる結果セットを表します。これによって、問合せを定義するために行ったすべての操作を繰り返さずに、最終の問合せを変更できます。

ユーザー・インタフェース要素のOLAP Java APIオブジェクトへの変換

Templateオブジェクトを設計して、アプリケーションのユーザー・インタフェースの要素を表します。このTemplateオブジェクトによって、エンド・ユーザーの選択が、Sourceを作成するOLAP Java APIの問合せ作成の操作に変換されます。その後、Cursorを作成して、Sourceで定義される結果セットをOracle OLAPからフェッチします。Cursorから値を取得し、それらの値をエンド・ユーザーに表示します。エンド・ユーザーによって選択が変更された場合は、Templateの状態を変更します。その後、Templateによって作成されたSourceを取得して、新しいCursorを作成し、取得した新しい値を表示します。

Templateおよび関連クラスの概要

OLAP Java APIでは、いくつかのクラスが連携して動作して、動的Sourceを作成します。Templateの設計では、次のクラスおよびインタフェースを実装または拡張する必要があります。

これらの3つのクラスのインスタンスと、DataProviderおよびDynamicDefinitionクラスのインスタンスが連携して動作して、Templateによって定義されたSourceを作成します。

動的Sourceを作成するクラス間の関連

動的Sourceを作成するクラスは、次のように連携して動作します。

  • Templateには、DynamicDefinitionを作成し、MetadataStateの現在の状態を取得および設定するメソッドが含まれています。Template抽象クラスの拡張では、MetadataStateのフィールドの値を取得および設定するメソッドを追加します。

  • MetadataStateの実装には、Template用のSourceの作成に使用されるデータを格納するためのフィールドが存在します。新しいTemplateを作成する場合、MetadataStateTemplateのコンストラクタに渡します。DynamicDefinitiongetSourceメソッドをコールすると、MetadataStateSourceGeneratorgenerateSourceメソッドに渡されます。

  • DataProviderは、Templateの作成に使用され、SourceGeneratorによって新しいSourceオブジェクトの作成に使用されます。

  • SourceGeneratorの実装には、MetadataStateのデータの現在の状態を使用してTemplate用のSourceを作成するgenerateSourceメソッドが含まれています。SourceGeneratorTemplatecreateDynamicDefinitionメソッドに渡して、DynamicDefinitionを作成します。

  • DynamicDefinitionには、SourceGeneratorによって作成されたSourceを取得するgetSourceメソッドが含まれています。DynamicDefinitionは、Sourceに永続的に関連付けられたSourceDefinitionのプロキシとして機能します。

Templateクラス

変更可能なSourceを作成するには、Templateを使用します。Templateには、DynamicDefinitionを作成し、Templateの現在の状態を取得および設定するメソッドが含まれています。Templateクラスの拡張では、Template用のMetadataStateのフィールドにアクセスするためのメソッドを追加します。TemplateによってDynamicDefinitionが作成され、これを使用してTemplate用のSourceGeneratorによって作成されたSourceを取得します。

Templateの実装例については、例10-1を参照してください。

MetadataStateインタフェース

MetadataStateインタフェースの実装は、Templateの値の現在の状態を格納します。MetadataStateには、現在の状態のコピーを作成するcloneメソッドが含まれる必要があります。

新しいTemplateをインスタンス化する場合、MetadataStateTemplateコンストラクタに渡します。Templateには、MetadataStateによって格納された値を取得および設定するためのメソッドが含まれています。Template用のSourceGeneratorgenerateSourceメソッドは、Template用のSourceを作成する際に、MetadataStateを使用します。

MetadataStateの実装例については、例10-2を参照してください。

SourceGeneratorインタフェース

SourceGeneratorの実装には、Template用のSourceを作成するgenerateSourceメソッドが含まれている必要があります。SourceGeneratorが作成する必要があるSourceは1種類のみです(BooleanSourceNumberSourceStringSourceなど)。generateSourceメソッドは、Sourceを作成する際に、Template用のMetadataStateによって表されるデータの現在の状態を使用します。

generateSourceメソッドによって作成されたSourceを取得するには、TemplatecreateDynamicDefinitionメソッドにSourceGeneratorを渡して、DynamicDefinitionを作成します。その後、DynamicDefinitiongetSourceメソッドをコールして、Sourceを取得します。

Templateは、それぞれ異なるSourceGeneratorを実装した複数のDynamicDefinitionを作成できます。異なるSourceGeneratorオブジェクトのgenerateSourceメソッドで、Template用のMetadataStateの現在の状態によって定義された同じデータが使用され、異なる問合せを定義するSourceオブジェクトが作成されます。

SourceGeneratorの実装例については、例10-3を参照してください。

DynamicDefinitionクラス

DynamicDefinitionは、SourceDefinitionのサブクラスです。TemplatecreateDynamicDefinitionメソッドをコールして、それにSourceGeneratorを渡すことによって、DynamicDefinitionを作成します。DynamicDefinitiongetSourceメソッドをコールして、SourceGeneratorによって作成されたSourceを取得します。

Templateによって作成されたDynamicDefinitionは、SourceGeneratorによって作成されたSourceSourceDefinitionのプロキシです。SourceDefinitionは、そのSourceと永続的に関連付けられます。Templateの状態が変更された場合、SourceGeneratorによって作成されるSourceは異なります。DynamicDefinitionはプロキシであるため、SourceSourceDefinitionが異なる場合でも、同じDynamicDefinitionを使用して新しいSourceを取得できます。

DynamicDefinitiongetCurrentメソッドは、generateSourceメソッドによって現在戻されているSourceに永続的に関連付けられているSourceDefinitionを戻します。DynamicDefinitionの使用例については、例10-4を参照してください。

Templateの設計および実装

Templateの設計には、アプリケーションのユーザー・インタフェースの問合せ作成要素が反映されます。たとえば、エンド・ユーザーが値リストから多くの値を要求する問合せを作成可能なアプリケーションを開発すると想定します。値は、メジャーの1つのディメンションの値です。そのメジャーの他のディメンションは、単一の値に制限されます。

アプリケーションのユーザー・インタフェースでは、エンド・ユーザーがダイアログ・ボックスを使用して次の操作を実行できます。

最初のダイアログ・ボックスでエンド・ユーザーが作成する問合せを表すSourceを作成するには、TopBottomTemplateという名前のTemplateを設計します。また、SingleSelectionTemplateという名前のTemplateも設計し、エンド・ユーザーによるベース・ディメンション以外のディメンションに対する単一の値の選択を表すSourceを作成します。Templateオブジェクトの設計には、ダイアログ・ボックスのユーザー・インタフェース要素が反映されます。

TopBottomTemplateおよびそのMetadataStateSourceGeneratorを設計するには、次の操作を実行します。

エンド・ユーザーは、このアプリケーションを使用して、最初のダイアログ・ボックスで販売台数をメジャーとして選択し、製品をベース・ディメンションとして選択します。また、エンド・ユーザーは、残りの各ディメンションの単一の値としてAsia Pacific地域、2001年の第1四半期および直販チャネルも選択します。

エンド・ユーザーが作成した問合せは、2001年にAsia Pacific地域の顧客に対して直販チャネルで販売された製品のうち、販売台数の総数が高い上位10の製品を要求します。

TopBottomTemplateTopBottomTemplateStateおよびTopBottomTemplateGeneratorクラスの実装例、およびこれらのクラスを使用するアプリケーションの例については、例10-1例10-2例10-3および例10-4を参照してください。TopBottomTemplateStateおよびTopBottomTemplateGeneratorクラスは、外部クラスTopBottomTemplateの内部クラスとして実装されます。

Templateのクラスの実装

例10-1に、TopBottomTemplateクラスの実装例を示します。

例10-1 Templateの実装

import oracle.olapi.data.source.DataProvider;
import oracle.olapi.data.source.DynamicDefinition;
import oracle.olapi.data.source.Source;
import oracle.olapi.data.source.SourceGenerator;
import oracle.olapi.data.source.Template;
import oracle.olapi.transaction.metadataStateManager.MetadataState;

/**
 * Creates a TopBottomTemplateState, a TopBottomTemplateGenerator,
 * and a DynamicDefinition.
 * Gets the current state of the TopBottomTemplateState and the values
 * that it stores.
 * Sets the data values stored by the TopBottomTemplateState and sets the
 * changed state as the current state.
 */
public class TopBottomTemplate extends Template
{
// Constants for specifying the selection of elements from the
// beginning or the end of the result set.
  public static final int TOP_BOTTOM_TYPE_TOP = 0;
  public static final int TOP_BOTTOM_TYPE_BOTTOM = 1;

  // Variable to store the DynamicDefinition.
  private DynamicDefinition dynamicDef;

  /**
   * Creates a TopBottomTemplate with a default type and number values
   * and the specified base dimension.
   */
  public TopBottomTemplate(Source base, DataProvider dataProvider)
  {
    super(new TopBottomTemplateState(base, TOP_BOTTOM_TYPE_TOP, 0),
                                     dataProvider);
    // Create the DynamicDefinition for this Template. Create the
    // TopBottomTemplateGenerator that the DynamicDefinition uses.
    dynamicDef =
    createDynamicDefinition(new TopBottomTemplateGenerator(dataProvider));
  }

  /**
   * Gets the Source produced by the TopBottomTemplateGenerator
   * from the DynamicDefinition.
   */
  public final Source getSource()
  {
    return dynamicDef.getSource();
  }

  /**
   * Gets the Source that is the base of the elements in the result set.
   * Returns null if the state has no base.
   */
  public Source getBase()
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    return state.base;
  }

  /**
   * Sets a Source as the base.
   */
  public void setBase(Source base)
  {
     TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    state.base = base;
    setCurrentState(state);
  }

  /**
   * Gets the Source that specifies the measure and the single
   * selections from the dimensions other than the base.
   */
  public Source getCriterion()
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    return state.criterion;
  }

  /**
   * Specifies a Source that defines the measure and the single values
   * selected from the dimensions other than the base.
   * The SingleSelectionTemplate produces such a Source.
   */
  public void setCriterion(Source criterion)
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    state.criterion = criterion;
    setCurrentState(state);
  }

  /**
   * Gets the type, which is either TOP_BOTTOM_TYPE_TOP or
   * TOP_BOTTOM_TYPE_BOTTOM.
   */
  public int getTopBottomType()
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    return state.topBottomType;
  }

  /**
   * Sets the type.
   */
  public void setTopBottomType(int topBottomType)
  {
    if ((topBottomType < TOP_BOTTOM_TYPE_TOP) ||
        (topBottomType > TOP_BOTTOM_TYPE_BOTTOM  ))
      throw new IllegalArgumentException("InvalidTopBottomType");
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    state.topBottomType = topBottomType;
    setCurrentState(state);
  }

  /**
   * Gets the number of values selected.
   */
  public float getN()
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    return state.N;
  }

  /**
   * Sets the number of values to select.
   */
  public void setN(float N)
  {
    TopBottomTemplateState state = (TopBottomTemplateState) getCurrentState();
    state.N = N;
    setCurrentState(state);
  }
}

例10-2に、内部クラスTopBottomTemplateStateの実装例を示します。

例10-2 MetadataStateの実装

/**
 * Stores data that can be changed by its TopBottomTemplate.
 * The data is used by a TopBottomTemplateGenerator in producing
 * a Source for the TopBottomTemplate.
 */
private static final class TopBottomTemplateState
     implements Cloneable, MetadataState
{
  public int topBottomType;
  public float N;
  public Source criterion;
  public Source base;

  /**
   * Creates a TopBottomTemplateState.
   */
  public TopBottomTemplateState(Source base, int topBottomType, float N)
  {
    this.base = base;
    this.topBottomType = topBottomType;
    this.N = N;
  }

  /**
   * Creates a copy of this TopBottomTemplateState.
   */
  public final Object clone()
  {
    try
    {
      return super.clone();
    }
    catch(CloneNotSupportedException e)
    {
      return null;
    }
  }
}

例10-3に、内部クラスTopBottomTemplateGeneratorの実装例を示します。

例10-3 SourceGeneratorの実装

/**
 * Produces a Source for a TopBottomTemplate based on the data
 * values of a TopBottomTemplateState.
 */
private final class TopBottomTemplateGenerator
      implements SourceGenerator
{
  // Store the DataProvider.
  private DataProvider _dataProvider;

  /**
   * Creates a TopBottomTemplateGenerator.
   */
  public TopBottomTemplateGenerator(DataProvider dataProvider)
  {
    _dataProvider = dataProvider;
  }

  /**
   * Generates a Source for a TopBottomTemplate using the current
   * state of the data values stored by the TopBottomTemplateState.
   */
  public Source generateSource(MetadataState state)
  {
    TopBottomTemplateState castState = (TopBottomTemplateState) state;
    if (castState.criterion == null)
      throw new NullPointerException("CriterionParameterMissing");
    Source sortedBase = null;
    if (castState.topBottomType == TOP_BOTTOM_TYPE_TOP)
      sortedBase = castState.base.sortDescending(castState.criterion);
    else
      sortedBase = castState.base.sortAscending(castState.criterion);
    return sortedBase.interval(1, Math.round(castState.N));
  }
}

Templateを使用するアプリケーションの実装

エンド・ユーザーが行った選択をTemplate用のMetadataStateに格納した後、DynamicDefinitiongetSourceメソッドを使用して、Templateによって作成された動的Sourceを取得します。この項では、例10-1で説明したTopBottomTemplateを使用するアプリケーションの例を示します。便宜上、このコードでは多くの例外処理を省略しています。

BaseExample11gクラスはContext11gクラスのインスタンスを作成および格納します。このクラスには次の操作を行うメソッドがあります。

  • コマンドライン引数のユーザーとしてのOracle Databaseインスタンスへの接続

  • Cursorオブジェクトの作成およびその値の表示

例10-4では、次の処理を実行します。

  • MdmMetadataProviderおよびMdmRootSchemaの取得。

  • DataProviderの取得。

  • ユーザーのMdmDatabaseSchemaの取得。

  • UNITSおよびSALESメジャーを持つMdmCubeの取得。この例では、キューブからメジャーおよびディメンションを取得します。

  • メジャーのいくつかのディメンションから単一の値を選択するためのSingleSelectionTemplateの作成。この例で使用するSingleSelectionTemplateクラスのコードは、付録Bを参照してください。

  • TopBottomTemplateの作成およびエンド・ユーザーが行った選択の格納。

  • TopBottomTemplateによって作成されたSourceの取得。

  • Context11gオブジェクトを使用したそのSource用のCursorの作成および値の表示。

第7章例7-3を使用するには、runメソッドの行(次のコメントからメソッド末尾まで)を置き換えます。

// Replace from here on for the Using Child Transaction example.

例10-4 Templateによって作成されたSourceの取得

import oracle.olapi.data.source.DataProvider;
import oracle.olapi.data.source.Source;
import oracle.olapi.examples.*;
import oracle.olapi.metadata.mdm.MdmAttribute;
import oracle.olapi.metadata.mdm.MdmBaseMeasure;
import oracle.olapi.metadata.mdm.MdmCube;
import oracle.olapi.metadata.mdm.MdmDatabaseSchema;
import oracle.olapi.metadata.mdm.MdmDimensionLevel;
import oracle.olapi.metadata.mdm.MdmDimensionMemberInfo;
import oracle.olapi.metadata.mdm.MdmHierarchyLevel;
import oracle.olapi.metadata.mdm.MdmLevelHierarchy;
import oracle.olapi.metadata.mdm.MdmMetadataProvider;
import oracle.olapi.metadata.mdm.MdmPrimaryDimension;
import oracle.olapi.metadata.mdm.MdmRootSchema;

/**
 * Creates a query that specifies a number of elements from the top
 * or bottom of a selection of dimension members, creates a Cursor
 * for the query, and displays the values of the Cursor.
 * The selected dimension members are those that have measure values
 * that are specified by selected members of the other dimensions of
 * the measure.
 */
public class TopBottomTest extends BaseExample11g
{
  /**
   * Gets the UNITS_CUBE_AWJ MdmCube.
   * From the cube, gets the MdmPrimaryDimension objects and the
   * MdmMeasure objects for the UNITS and SALES.
   * Gets the default hierarchies for the dimensions and then gets the Source
   * object for the base of the query.
   * Creates a SingleSelectionTemplate and adds selections to it.
   * Creates a TopBottomTemplate and sets its properties.
   * Gets the Source produced by the TopBottomTemplate, creates a Cursor
   * for it, and displays the values of the Cursor.
   * Changes the state of the SingleSelectionTemplate and the
   * TopBottomTemplate, creates a new Cursor for the Source produced by the
   * TopBottomTemplate, and displays the values of that Cursor.
   */
  public void run() throws Exception
  {
    // Get the MdmMetadataProvider from the superclass.
    MdmMetadataProvider metadataProvider = getMdmMetadataProvider();
    // Get the DataProvider from the Context11g object of the superclass.
    DataProvider dp = getContext().getDataProvider();

    // Get the MdmRootSchema and the MdmDatabaseSchema for the user.
    MdmRootSchema mdmRootSchema =
                               (MdmRootSchema)metadataProvider.getRootSchema();
    MdmDatabaseSchema mdmDBSchema =
                       mdmRootSchema.getDatabaseSchema(getContext().getUser());

    MdmCube unitsCube =
           (MdmCube)mdmDBSchema.getTopLevelObject("UNITS_CUBE_AWJ");
    MdmBaseMeasure mdmUnits = (MdmBaseMeasure)unitsCube.getMeasure("UNITS");
    MdmBaseMeasure mdmSales = (MdmBaseMeasure)unitsCube.getMeasure("SALES");


    // Get the Source objects for the measures.
    Source units = mdmUnits.getSource();
    Source sales = mdmSales.getSource();

    // Get the MdmPrimaryDimension objects for the dimensions of the cube.
    List<MdmPrimaryDimension> cubeDims = unitsCube.getDimensions();
    MdmPrimaryDimension mdmTimeDim = null;
    MdmPrimaryDimension mdmProdDim = null;
    MdmPrimaryDimension mdmCustDim = null;
    MdmPrimaryDimension mdmChanDim = null;

    for(MdmPrimaryDimension mdmPrimDim : cubeDims)
    {
      if (mdmPrimDim.getName().startsWith("TIME"))
        mdmTimeDim = mdmPrimDim;
      else if (mdmPrimDim.getName().startsWith("PROD"))
        mdmProdDim = mdmPrimDim;
      else if (mdmPrimDim.getName().startsWith("CUST"))
        mdmCustDim = mdmPrimDim;
      else if (mdmPrimDim.getName().startsWith("CHAN"))
        mdmChanDim = mdmPrimDim;
    }

    // Get the default hierarchy of the Product dimension.
    MdmLevelHierarchy mdmProdHier = (MdmLevelHierarchy)
                                     mdmProdDim.getDefaultHierarchy();

    // Get the detail dimenson level of the Product dimension.
    MdmDimensionLevel mdmItemDimLevel =
                                mdmProdDim.findOrCreateDimensionLevel("ITEM");
    // Get the default hierarchy of the Product dimension.
    MdmLevelHierarchy mdmProdHier = (MdmLevelHierarchy)
                                    mdmProdDim.getDefaultHierarchy();
    // Get the hierarchy level of the dimension level.
    MdmHierarchyLevel mdmItemHierLevel =
                       mdmProdHier.findOrCreateHierarchyLevel(mdmItemDimLevel);
    // Get the Source for the hierarchy level.
    Source itemLevel = mdmItemHierLevel.getSource();

    // Get the short description attribute for the Product dimension and
    // the Source for the attribute.
    MdmAttribute mdmProdShortDescrAttr =
                           mdmProdDim.getShortValueDescriptionAttribute();
    Source prodShortDescrAttr = mdmProdShortDescrAttr.getSource();

    // Create a SingleSelectionTemplate to produce a Source that
    // represents the measure values specified by single members of each of
    // the dimensions of the measure other than the base dimension.
    SingleSelectionTemplate singleSelections =
                        new SingleSelectionTemplate(units, dp);

    // Create MdmDimensionMemberInfo objects for single members of the
    // other dimensions of the measure.
    MdmDimensionMemberInfo timeMemInfo =
         new MdmDimensionMemberInfo(mdmTimeDim,
                                    "CALENDAR_YEAR::YEAR::CY2001");
    MdmDimensionMemberInfo custMemInfo =
         new MdmDimensionMemberInfo(mdmCustDim,
                                    "SHIPMENTS::REGION::APAC");
    MdmDimensionMemberInfo chanMemInfo =
         new MdmDimensionMemberInfo(mdmChanDim,
                                    "CHANNEL_PRIMARY::CHANNEL::DIR");

    // Add the dimension member information objects to the
    // SingleSelectionTemplate.
    singleSelections.addDimMemberInfo(custMemInfo);
    singleSelections.addDimMemberInfo(chanMemInfo);
    singleSelections.addDimMemberInfo(timeMemInfo);

    // Create a TopBottomTemplate specifying, as the base, the Source for a
    // a level of a hierarchy.
    TopBottomTemplate topNBottom = new TopBottomTemplate(itemLevel, dp);

    // Specify whether to retrieve the elements from the beginning (top) or the
    // end (bottom) of the selected elements of the base dimension.
    topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_TOP);

    // Set the number of elements of the base dimension to retrieve.
    topNBottom.setN(10);
    // Get the Source produced by the SingleSelectionTemplate and specify it as
    // the criterion object.
    topNBottom.setCriterion(singleSelections.getSource());

    // Replace from here on for the Using Child Transaction Objects example.

    // Get the short value descriptions of the dimension members from the
    // SingleSelectionTemplate.
    StringBuffer shortDescrsForMemberVals =
                               singleSelections.getMemberShortDescrs(dp);
    println("\nThe " + Math.round(topNBottom.getN()) +
                    " products with the most units sold \nfor" +
                    shortDescrsForMemberVals + " are:\n");

    // Get the Source produced by the TopBottomTemplate, create a Cursor
    // for it, and display the values of the Cursor.
    Source result = topNBottom.getSource();

    // Join the Source produced by the TopBottomTemplate with the short
    // value descriptions. Use the joinHidden method so that the
    // dimension member values do not appear in the result.
    Source result = prodShortDescrAttr.joinHidden(topNBottomResult);

    // Commit the current transaction.
    getContext().commit();  // Method of ContextExample11g.

    // Create a Cursor for the result and display the values of the Cursor.
    getContext().displayTopBottomResult(result);

    // Change a dimension member selection of the SingleSelectionTemplate.
    timeMemInfo.setUniqueValue("CALENDAR_YEAR::YEAR::CY2000");
    singleSelections.changeSelection(timeMemInfo);

    // After changing the selection of a dimension member, get the short value
    // descriptions of the dimension members again.
    StringBuffer shortDescrsForMemberValsAfter =
                                singleSelections.getMemberShortDescrs(dp);

    // Change the number of elements selected and the type of selection.
    topNBottom.setN(5);
    topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_BOTTOM);

    // Join the Source produced by the TopBottomTemplate to the short
    // description attribute.
    result = prodShortDescrAttr.joinHidden(topNBottomResult);

    // Commit the current transaction.
    getContext().commit();

    println("\nThe " + Math.round(topNBottom.getN()) + " products " +
                  "with the fewest units sold \nfor" +
                    shortDescrsForMemberValsAfter + " are:\n");

    // Create a new Cursor for the Source produced by the TopBottomTemplate
    // and display the Cursor values.
    getContext().displayTopBottomResult(result);

    // Now change the measure to Sales, and get the top and bottom products by
    // Sales.
    singleSelections.setMeasure(sales);
    // Change the number of elements selected.
    topNBottom.setN(7);
    // Change the type of selection back to the top.
    topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_TOP);

    println("\nThe " + Math.round(topNBottom.getN()) +
            " products with the highest sales amounts \nfor" +
            shortDescrsForMemberVals +" are:\n");

    topNBottomResult = topNBottom.getSource();
    result = prodShortDescrAttr.joinHidden(topNBottomResult);

    // Commit the current transaction.
    getContext().commit();

    // Change the type of selection back to the bottom.
    topNBottom.setTopBottomType(TopBottomTemplate.TOP_BOTTOM_TYPE_BOTTOM);

    println("\nThe " + Math.round(topNBottom.getN()) +
            " products with the lowest sales amounts \nfor" +
            shortDescrsForMemberVals +" are:\n");

    topNBottomResult = topNBottom.getSource();
    result = prodShortDescrAttr.joinHidden(topNBottomResult);

    // Commit the current transaction.
    getContext().commit();

  }

  /**
   * Runs the TopBottomTest application.
   *
   * @param args An array of String objects that provides the arguments
   *             required to connect to an Oracle Database instance, as
   *             specified in the Context11g class.
   */
  public static void main(String[] args)
  {
    new TopBottomTest().execute(args);
  }

}

TopBottomTestプログラムの出力は、次のようになります。

The 10 products with the most units sold
for Asia Pacific, Direct Sales, 2001 are:

 1. Mouse Pad
 2. Unix/Windows 1-user pack
 3. Deluxe Mouse
 4. Laptop carrying case
 5. 56Kbps V.90 Type II Modem
 6. 56Kbps V.92 Type II Fax/Modem
 7. Keyboard Wrist Rest
 8. Internal - DVD-RW - 6X
 9. O/S Documentation Set - English
10. External - DVD-RW - 8X

The 5 products with the fewest units sold
for Asia Pacific, Direct Sales, 2000 are:

 1. O/S Documentation Set - Italian
 2. External 48X CD-ROM
 3. O/S Documentation Set - Spanish
 4. Internal 48X CD-ROM USB
 5. Monitor- 19"Super VGA

The 7 products with the highest sales amounts
for Asia Pacific, Direct Sales, 2001 are:

 1. Sentinel Financial
 2. Sentinel Standard
 3. Envoy Executive
 4. Sentinel Multimedia
 5. Envoy Standard
 6. Envoy Ambassador
 7. 56Kbps V.90 Type II Modem

The 7 products with the lowest sales amounts
for Asia Pacific, Direct Sales, 2001 are:

 1. Keyboard Wrist Rest
 2. Mouse Pad
 3. O/S Documentation Set - Italian
 4. O/S Documentation Set - Spanish
 5. Standard Mouse
 6. O/S Documentation Set - French
 7. Internal 48X CD-ROM USB