Hierarchy builder

Overview

With the fluent interface it’s not possible to define the cube hierarchies by hierarchy, but only by dimension. To avoid this limitation you can define your hierarchies with the Hierarchy Builder Helper.

Hierarchy definition

The HierarchyBuilder is defined in the package com.activeviam.accelerator.common.utils.

Standard hierarchy and store-based analysis hierarchy

Standard hierarchy:

hierarchyBuilder.toDimension(DATES_DIMENSION, builder ->
        builder.withHierarchy(DATE_HIERARCHY)
            .slicing()
            .withLevel(AS_OF_DATE_LEVEL)
            .withType(ILevelInfo.LevelType.TIME)
            .withComparator(type));

Store-based analysis hierarchy:

hierarchyBuilder.toDimension(RISK_DIMENSION, builder ->
        builder.withHierarchy(MATURITY_STORE_NAME)
                .fromStore(StoreConstants.MARKET_DATA_STORE_NAME)
                .withLevel(MATURITY_LEVEL)
                    .withFieldName(StoreFieldConstants.MATURITY_LABELS)
                    .withComparator(BucketComparator.PLUGIN_KEY)
                .withLevel(MATURITY_DATE_LEVEL)
                    .withFieldName(StoreFieldConstants.MATURITY_DATES)
                    .withComparator(ReverseOrderComparator.type));

Custom analysis hierarchy

For a custom analysis hierarchy, the following shorthand allows you to pass the AnalysisHierarchyDescription object directly:

hierarchyBuilder.toDimension(CURRENCY_DIMENSION,
        FxHierarchy.hierarchy(SRC_FX_HIERARCHY)
                .withLevel(SRC_FX_LEVEL)
                .withCurrenciesOrder(firstDisplayCcy));

Dimension properties

Properties at dimension level can also be defined:

hierarchyBuilder.withDimensionProperty(UNDERLYINGS_HIERARCHY, XMLA_DESCRIPTION, "Dimension of underlyings");

The dimension type:

hierarchyBuilder.withType(DATES_DIMENSION, TIME);

To hide a dimension:

hierarchyBuilder.isVisible(UNDERLYINGS_HIERARCHY, false);
// or
hierarchyBuilder.hidden(UNDERLYINGS_HIERARCHY);

Epoch dimension

The epoch dimension uses specific fluent types, so it is defined with a specific API call:

hierarchyBuilder.withEpochDimension(builder -> builder
        .withEpochLevel()
            .withComparator(TYPE)
            .withFormatter("EPOCH[HH:mm:ss]")
            .end()
        .withBranchLevel()
            .end()
);

Spring integration

To inverse the dependency between the Hierarchy Builder and the hierarchy definitions, at Spring level we generate a hierarchy consumer. The beans exchanged by Spring are typed HierarchyBuilderConsumer and there is a consumer of the Hierarchy Builder.

Cube setup

The HierarchyBuilderConsumer beans can be easily converted into the core dimension builder lambda DimensionsAdder:

private  @NonNull DimensionsAdder dimensions(@Autowired @NonNull List<HierarchyBuilderConsumer> consumers) {
    HierarchyBuilder hierarchyBuilder = new HierarchyBuilder();
    consumers.forEach(c -> c.accept(hierarchyBuilder));
    return hierarchyBuilder.getDimensionsAdder();
}

The class ADataCubeConfigurer that can be used as a template to create a cube, can aggregate hierarchy definitions of type HierarchyBuilderConsumer and dimension definitions of type DimensionsAdder (with the restriction that a dimension can only be defined with one of the two methodologies). The list of beans is provided in its constructor.

Hierarchy Bean definition

Here is how a hierarchy bean is defined:

    // The return object will be consumed at cube creation
    @Bean
    @Qualifier("commonDimension")
    public HierarchyBuilderConsumer bookingDimension() {
        return BookingDimensionConfig::getBookingDimension;
    }

    // We can group the declaration inside the bean
    public static void getBookingDimension(@NonNull HierarchyBuilder hierarchyBuilder) {
        // Each call for a hierarchy setup is independent
        getDesksHierarchy(hierarchyBuilder);
        getSrcCurrencyHierarchy(hierarchyBuilder);
        getDateHierarchy(hierarchyBuilder);
    }

    // This is a vanilla hierarchy
    public static void getDesksHierarchy(@NonNull HierarchyBuilder hierarchyBuilder) {
        hierarchyBuilder.toDimension(BOOKING_DIMENSION, builder -> builder.withHierarchy(DESKS_HIERARCHY).withLevel(DESK_LEVEL));
    }

    // This is an analysis hierarchy with a shorthand compared to the previous syntax
    public static void getSrcCurrencyHierarchy(@NonNull HierarchyBuilder hierarchyBuilder) {
        hierarchyBuilder.toDimension(CURRENCY_DIMENSION, FxHierarchy.hierarchy(SRC_FX_HIERARCHY).withLevel(SRC_FX_LEVEL));
    }

    // Here you can see the setting of an extra property at dimension level
    public static void getDateHierarchy(@NonNull HierarchyBuilder hierarchyBuilder) {
        hierarchyBuilder.withType(DATES_DIMENSION, TIME);
        hierarchyBuilder.toDimension(DATES_DIMENSION, b -> b.withHierarchy(DATE_HIERARCHY).withLevel(AS_OF_DATE_LEVEL).withType(ILevelInfo.LevelType.TIME));
    }