Class EssPlanningDimensionFile

java.lang.Object
com.appliedolap.essbase.EssPlanningDimensionFile

public class EssPlanningDimensionFile extends Object
One dimension as EPM Cloud exports it, read from the .csv in an artifact snapshot.

This, rather than the batch-outline-edit XML in the same snapshot, is what an Essbase outline can be built from. The XML looks like the obvious candidate and is not: every member in it is addressed by a Planning GUID with isMbrId="true", and it carries no member names, no parents and no hierarchy at all. It is a property refresh for members Planning has already created - useful for replaying properties, useless for building a dimension. These files carry the names, the parents, the aliases and the properties, which is everything an outline needs.

Snapshot layout, for finding them: shared dimensions are under <app>/resource/Global Artifacts/Common Dimensions/Standard Dimensions and .../Attribute Dimensions, and a cube's own dimensions under <app>/resource/Cube/<cube>/Standard Dimensions.

The file is a CSV with an XML header block bolted on the front - a <DIMENSIONS> document describing the dimension, then #--!, then an ordinary header row and the members. Both halves are read: the XML says whether the dimension is dense or sparse and what type it is, the CSV says what is in it.

  • Method Details

    • read

      public static EssPlanningDimensionFile read(Path file) throws IOException
      Reads one dimension file.
      Parameters:
      file - the .csv from an artifact snapshot
      Returns:
      the dimension and its members, in the order the file lists them
      Throws:
      IOException - if the file cannot be read
      IllegalArgumentException - if it is not one of these files
    • getDimensionName

      public String getDimensionName()
      The dimension's name, taken from the first column's header.
    • getDensity

      public String getDensity()
      Returns:
      "Sparse" or "Dense" as the file declares it, or empty if it did not
    • getDimensionType

      public String getDimensionType()
      Returns:
      Planning's dimension type, e.g. "None", "Account", "Time"
    • getDimensionAttributes

      public Map<String,String> getDimensionAttributes()
    • getMembers

      public List<EssPlanningDimensionFile.Member> getMembers()
    • memberNamesById

      public Map<String,String> memberNamesById()
      Planning member ids to member names, for every member in the file.

      The map that makes the batch-outline-edit XML in the same snapshot readable: it addresses every member by the id in the UUID column here, and carries the name nowhere at all.

      Returns:
      id to name, skipping members the file gave no id
    • toBatchOutlineEdit

      public EssBatchOutlineEdit toBatchOutlineEdit(String planType)
      The members of this dimension as a batch outline edit, ready to apply to a cube.

      Every member is a mbrAddOrUpdate, so applying the same file twice is how you refresh a dimension rather than how you get errors. Parents come before their children, because the server applies actions in order and a member cannot be added under a parent that does not exist yet - the file is usually in that order already, and this does not assume it.

      The dimension member itself is not added: an outline's dimension root comes from the cube's definition, and the rows whose parent is the dimension attach to it. A dimension the cube does not have will fail loudly on its first member, which is the right way round.

      Parameters:
      planType - which cube's columns to read, for the properties Planning records per plan type
      Returns:
      the edit, which the caller can add to before applying
    • toStorageRefinement

      public EssBatchOutlineEdit toStorageRefinement(String planType)
      The storage types that could not be set while the dimension was being built, as a second edit.

      Label-only and dynamic-calc describe a member that aggregates something, so neither is valid on a member with no children - and every member is childless at the instant it is added. They can only be set once the hierarchy exists, which means a second document and a second call: a single document mixing mbrAddOrUpdate and mbrUpdate for the members it is creating is refused outright, the server resolving mbrUpdate against the outline as it was before the document ran.

      Best effort. Whether Essbase accepts a given storage on a given member depends on rules this cannot fully know from the file - two are handled here, that a member which lost all its children to plan-type filtering is now a leaf, and that an ancestor of a shared member cannot be dynamic calc - and there are others, each of which fails the whole document rather than the one action. Apply this separately from toBatchOutlineEdit(java.lang.String), and treat a failure as "the dimension is built, some storage types are not set" rather than as the build having failed.

      Parameters:
      planType - which cube's columns to read
      Returns:
      an edit setting the remaining storage types, which may be empty
    • ambiguousMemberNames

      public List<String> ambiguousMemberNames(String planType)
      The names this file cannot set every property on, because they appear more than once.

      A shared member repeats its prototype's name, and a repeated name cannot be the target of an mbrUpdate. Both members are still created; what cannot be set afterwards is anything toStorageRefinement(java.lang.String) would have set on them.

      Parameters:
      planType - the plan type whose members to consider
      Returns:
      the duplicated names, in file order
    • toString

      public String toString()
      Overrides:
      toString in class Object