Author: kaiyi4
Date: Wed Aug 27 13:51:06 2008
New Revision: 2635

Added:
   trunk/src/ca/sqlpower/architect/swingui/olap/DimensionUsageEditPanel.java
Modified:
   trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java
   trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
   trunk/src/ca/sqlpower/architect/swingui/olap/HierarchyEditPanel.java
trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateDimensionUsageAction.java trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateHierarchyAction.java

Log:
New edit panel for dimensionUsage. When a dimUsage is created, its foreign key will be set, and the referring dimension's foreign key is also set.

Also erased out hierarchy primary key setting property introduced in the last commit.

Modified: trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java  (original)
+++ trunk/src/ca/sqlpower/architect/olap/OLAPUtil.java Wed Aug 27 13:51:06 2008
@@ -57,17 +57,18 @@
     }

     /**
-     * Finds the OLAPSession that owns the given OLAPObject, by following
-     * parent pointers successively until an ancestor of type OLAPSession
-     * is encountered. If there is no OLAPSession ancestor, returns null.
+ * Finds the OLAPSession that owns the given OLAPObject, by following parent
+     * pointers successively until an ancestor of type OLAPSession is
+     * encountered. If there is no OLAPSession ancestor, returns null.
      * <p>
* Note that when we say <i>ancestor</i> in this doc comment, we include - * the given <code>oo</code> object as an "ancestor" of itself. In other + * the given <code>oo</code> object as an "ancestor" of itself. In other * words, if you pass in an OLAPSession, you will get that same object back.
      *
-     * @param oo The object to start searching at
-     * @return The nearest ancestor of type OLAPObject, or null if there is
-     * no such ancestor.
+     * @param oo
+     *            The object to start searching at
+ * @return The nearest ancestor of type OLAPObject, or null if there is no
+     *         such ancestor.
      */
     public static OLAPSession getSession(OLAPObject oo) {
         while (oo != null && !(oo instanceof OLAPSession)) {
@@ -78,8 +79,8 @@

     /**
* Mondrian uses a single string as a table name qualifier, so this method - * helps by finding the parent schema and/or catalog and produces the correct
-     * Mondrian qualifier for the given table.
+     * helps by finding the parent schema and/or catalog and produces the
+     * correct Mondrian qualifier for the given table.
      */
     public static String getQualifier(SQLTable t) {
         SQLSchema schema = t.getSchema();
@@ -94,7 +95,7 @@
             return catalog.getName() + "." + schema.getName();
         }
     }
-
+
     /**
* Adds the given OLAPChildListener and optional PropertyChangeListener to
      * the given root object and all of its descendants.
@@ -133,9 +134,9 @@
* OLAPObjects rooted at root. It is not an error if the listener
      *            is not registered with any or all of the objects in the
* subtree, so it's safe to call this with the root of the tree - * if you want. If you weren't listening for property change events, - * you can leave this parameter as null. Note that this parameter
-     *            is pronounced "pockle," not "pickle."
+     *            if you want. If you weren't listening for property change
+ * events, you can leave this parameter as null. Note that this
+     *            parameter is pronounced "pockle," not "pickle."
      */
public static void unlistenToHierarchy(OLAPObject root, OLAPChildListener ocl, PropertyChangeListener pcl) {
         root.removeChildListener(ocl);
@@ -146,7 +147,7 @@
             unlistenToHierarchy(child, ocl, pcl);
         }
     }
-
+
     /**
* [EMAIL PROTECTED] OLAPObject#getName()} does not always return the correct name so * this method helps by finding the proper name for those exceptions and
@@ -158,8 +159,9 @@
* @return The name of the given object, null if the object is null itself.
      */
     public static String nameFor(OLAPObject obj) {
-        if (obj == null) return null;
-
+        if (obj == null)
+            return null;
+
         if (obj instanceof CubeUsage) {
             return ((CubeUsage) obj).getCubeName();
         } else if (obj instanceof Hierarchy) {
@@ -190,15 +192,17 @@
         OLAPSession session = getSession(hier);
         SQLDatabase database = session.getDatabase();
         RelationOrJoin relation = hier.getRelation();
-
- // If this hierarchy belongs to a shared dimension, its relation is all we can get. - // But if this hierarchy belongs to a private dimension, its cube's fact specifies
+
+ // If this hierarchy belongs to a shared dimension, its relation is all
+        // we can get.
+ // But if this hierarchy belongs to a private dimension, its cube's fact
+        // specifies
         // the default table.
if (relation == null && hier.getParent().getParent() instanceof Cube) {
             Cube owningCube = (Cube) hier.getParent().getParent();
             relation = owningCube.getFact();
         }
-
+
         return tableForRelationOrJoin(database, relation);
     }

@@ -234,22 +238,7 @@
         if (relation == null) {
             return null;
         } else if (relation instanceof Table) {
-            Table table = (Table) relation;
-            String qualifier = table.getSchema();
-            String name = table.getName();
-            if (qualifier == null || qualifier.length() == 0) {
-                return (SQLTable) database.getChildByName(name);
-            } else if (qualifier.contains(".")) {
- String cat = qualifier.substring(0, qualifier.indexOf('.')); - String schema = qualifier.substring(qualifier.indexOf('.') + 1);
-                return database.getTableByName(cat, schema, name);
- } else if (ArchitectUtils.isCompatibleWithHierarchy(database, qualifier, null, name)) {
-                return database.getTableByName(qualifier, null, name);
- } else if (ArchitectUtils.isCompatibleWithHierarchy(database, null, qualifier, name)) {
-                return database.getTableByName(null, qualifier, name);
-            } else {
-                return null;
-            }
+            return getSQLTableFromOLAPTable(database, (Table) relation);
         } else if (relation instanceof View) {
throw new UnsupportedOperationException("Views not implemented yet");
         } else if (relation instanceof InlineTable) {
@@ -257,7 +246,34 @@
         } else if (relation instanceof Join) {
throw new UnsupportedOperationException("Join not implemented yet");
         } else {
- throw new IllegalStateException("Can't produce SQLTable for unknown Relation type " + relation.getClass().getName()); + throw new IllegalStateException("Can't produce SQLTable for unknown Relation type " +
+                    relation.getClass().getName());
+        }
+    }
+
+    /**
+ * Search the database and retrieve the matching SQLTable(Relational) object
+     * thats logically equivalent to the given Table(OLAP representation)
+     *
+ * @param table Table object representing a table in a relational database
+     * @return a SQLTable in SQLDatabase representing the given table
+     * @throws ArchitectException
+     */
+ public static SQLTable getSQLTableFromOLAPTable(SQLDatabase database, Table table) throws ArchitectException {
+        String qualifier = table.getSchema();
+        String name = table.getName();
+        if (qualifier == null || qualifier.length() == 0) {
+            return (SQLTable) database.getChildByName(name);
+        } else if (qualifier.contains(".")) {
+            String cat = qualifier.substring(0, qualifier.indexOf('.'));
+ String schema = qualifier.substring(qualifier.indexOf('.') + 1);
+            return database.getTableByName(cat, schema, name);
+ } else if (ArchitectUtils.isCompatibleWithHierarchy(database, qualifier, null, name)) {
+            return database.getTableByName(qualifier, null, name);
+ } else if (ArchitectUtils.isCompatibleWithHierarchy(database, null, qualifier, name)) {
+            return database.getTableByName(null, qualifier, name);
+        } else {
+            return null;
         }
     }

@@ -270,8 +286,8 @@
* @return The list of all accessible tables. If the OLAP session doesn't
      *         have a database chosen, an empty list is returned.
      * @throws ArchitectException
- * If there is a problem populating the list of tables (for example,
-     *             the database might not be reachable).
+     *             If there is a problem populating the list of tables (for
+     *             example, the database might not be reachable).
      */
public static List<SQLTable> getAvailableTables(OLAPObject obj) throws ArchitectException {
         OLAPSession osession = OLAPUtil.getSession(obj);
@@ -284,7 +300,7 @@
         }
         return tables;
     }
-
+
     /**
      * Finds and returns the Cube that the given CubeUsage references.
      *
@@ -301,8 +317,8 @@
throw new IllegalArgumentException("Can't find OLAPSession ancestor: " + cu);
         }
         return olapSession.findCube(cu.getCubeName());
-    }
-
+    }
+
     /**
      * Finds and returns the base Dimension that the given CubeDimension
* references. It is safe to call this method with a Dimension as parameter,
@@ -319,7 +335,7 @@
         if (olapSession == null) {
throw new IllegalArgumentException("Can't find OLAPSession ancestor: " + cubeDim);
         }
-
+
         if (cubeDim instanceof Dimension) {
             return (Dimension) cubeDim;
         } else if (cubeDim instanceof DimensionUsage) {
@@ -331,7 +347,7 @@
                 return olapSession.findPublicDimension(vCubeDim.getName());
             } else {
CubeDimension cd = olapSession.findCubeDimension(vCubeDim.getCubeName(), vCubeDim.getName());
-
+
                 if (cd == null) {
                     return null;
                 } else if (cd instanceof Dimension) {
@@ -348,7 +364,7 @@
throw new UnsupportedOperationException("CubeDimension of type " + cubeDim.getClass() + " not recognized.");
         }
     }
-
+
     /**
      * Checks if the name is unique for an OLAPObject, relies on
      * [EMAIL PROTECTED] OLAPObject#getName()} for name comparisons, case 
insensitive.
@@ -367,7 +383,7 @@
         if (olapSession == null) {
throw new IllegalArgumentException("Can't find OLAPSession ancestor: " + parent);
         }
-
+
         if (type == Cube.class) {
             return olapSession.findCube(name) == null;
         } else if (type == Dimension.class && parent instanceof Schema) {

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java  (original)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/CubePane.java Wed Aug 27 13:51:06 2008
@@ -96,7 +96,9 @@
                 panel = new MeasureEditPanel((Measure) coord.getItem());
             } else if (coord.getItem() instanceof DimensionUsage) {
UsageComponent usageComp = (UsageComponent) getPlayPen().findPPComponent(coord.getItem()); - panel = new DimensionEditPanel((Dimension) usageComp.getPane1().getModel()); + Dimension dimension = (Dimension) usageComp.getPane1().getModel(); + DimensionUsage dimensionUsage = (DimensionUsage) usageComp.getModel(); + panel = new DimensionUsageEditPanel(dimensionUsage, dimension);
             } else {
throw new IllegalArgumentException("Edit dialog for type " + coord.getItem().getClass() + " cannot be created!");
             }

Added: trunk/src/ca/sqlpower/architect/swingui/olap/DimensionUsageEditPanel.java
==============================================================================
--- (empty file)
+++ trunk/src/ca/sqlpower/architect/swingui/olap/DimensionUsageEditPanel.java Wed Aug 27 13:51:06 2008
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2008, SQL Power Group Inc.
+ *
+ * This file is part of Power*Architect.
+ *
+ * Power*Architect is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Power*Architect is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package ca.sqlpower.architect.swingui.olap;
+
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.SQLColumn;
+import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.olap.OLAPUtil;
+import ca.sqlpower.architect.olap.MondrianModel.Cube;
+import ca.sqlpower.architect.olap.MondrianModel.Dimension;
+import ca.sqlpower.architect.olap.MondrianModel.DimensionUsage;
+import ca.sqlpower.architect.olap.MondrianModel.Table;
+import ca.sqlpower.swingui.DataEntryPanel;
+
+import com.jgoodies.forms.builder.DefaultFormBuilder;
+import com.jgoodies.forms.layout.FormLayout;
+
+public class DimensionUsageEditPanel implements DataEntryPanel{
+
+    private final DimensionUsage dimensionUsage;
+
+    private final JPanel panel;
+
+    private JTextField captionField;
+
+    private JComboBox foreignKeyChooser;
+
+    private final Dimension dimension;
+
+    /**
+     * Creates a new property editor for the given dimension usage.
+     *
+     * @param dimensionUsage
+     *            usage The data model of the dimension usage to edit
+     * @param dimension
+     *            The dimension this dimension usage is referring to
+     *
+     * @throws ArchitectException
+ * if digging up the source table results in a database error
+     */
+ public DimensionUsageEditPanel(DimensionUsage dimensionUsage, Dimension dimension) throws ArchitectException {
+        this.dimensionUsage = dimensionUsage;
+        this.dimension = dimension;
+
+ FormLayout layout = new FormLayout("left:max(40dlu;pref), 3dlu, 80dlu:grow", "");
+        DefaultFormBuilder builder = new DefaultFormBuilder(layout);
+        builder.setDefaultDialogBorder();
+ builder.append("Caption", captionField = new JTextField(dimensionUsage.getCaption()));
+        builder.append("Foreign Key", foreignKeyChooser = new JComboBox());
+
+        Cube cube = (Cube) dimensionUsage.getParent();
+ SQLTable factTable = OLAPUtil.getSQLTableFromOLAPTable(OLAPUtil.getSession(cube).getDatabase(), (Table) (cube.getFact()));
+        for (SQLColumn col : factTable.getColumns()) {
+            foreignKeyChooser.addItem(col);
+            if (col.getName().equals(dimensionUsage.getForeignKey())) {
+                foreignKeyChooser.setSelectedItem(col);
+            }
+        }
+        panel = builder.getPanel();
+    }
+
+    public boolean applyChanges() {
+ dimensionUsage.startCompoundEdit("Modify Dimension Usage Properties");
+        if (!(captionField.getText().equals(""))) {
+            dimensionUsage.setCaption(captionField.getText());
+        } else {
+            dimensionUsage.setCaption(null);
+        }
+ SQLColumn selectedCol = (SQLColumn) foreignKeyChooser.getSelectedItem();
+        String pk = selectedCol.getName();
+        dimensionUsage.setForeignKey(pk);
+        dimension.setForeignKey(pk);
+        dimensionUsage.endCompoundEdit();
+        return true;
+    }
+
+    public void discardChanges() {
+        // nothing to do
+    }
+
+    public JComponent getPanel() {
+        return panel;
+    }
+
+    public boolean hasUnsavedChanges() {
+        return true;
+    }
+}

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/HierarchyEditPanel.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/HierarchyEditPanel.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/HierarchyEditPanel.java Wed Aug 27 13:51:06 2008
@@ -19,7 +19,6 @@

 package ca.sqlpower.architect.swingui.olap;

-import java.util.ArrayList;
 import java.util.List;
 import java.util.Vector;

@@ -30,7 +29,6 @@
 import javax.swing.JTextField;

 import ca.sqlpower.architect.ArchitectException;
-import ca.sqlpower.architect.SQLColumn;
 import ca.sqlpower.architect.SQLTable;
 import ca.sqlpower.architect.olap.OLAPUtil;
 import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
@@ -53,7 +51,6 @@
     private final JComboBox tableChooser;
     private final JCheckBox hasAll;
     private final JTextField allLevelName;
-    private final JComboBox primaryKeyName;

     /**
      * Validation handler for errors in the dialog
@@ -83,22 +80,6 @@
builder.append("Table", tableChooser = new JComboBox(new Vector<SQLTable>(tables))); builder.append("All Level Name", allLevelName = new JTextField(hierarchy.getAllLevelName() != null ? hierarchy.getAllLevelName() : "(All)")); tableChooser.setSelectedItem(OLAPUtil.tableForHierarchy(hierarchy)); // XXX this isn't quite right.. it would set the default as the local value
-        SQLTable selectedTable = (SQLTable) tableChooser.getSelectedItem();
-        List<SQLColumn> pk = new ArrayList<SQLColumn>();
-        if (selectedTable != null) {
-            for (SQLColumn col : selectedTable.getColumns()) {
-                if (col.isPrimaryKey()) {
-                    pk.add(col);
-                }
-            }
-            if (pk.isEmpty()) {
- throw new IllegalStateException("Primary key in a hierarchy should always be " + - "specified from the selected table, but selected table contains no primary key");
-            }
-        } else {
- throw new NullPointerException("Selected source table must not be null");
-        }
- builder.append("Primary Key", primaryKeyName = new JComboBox(new Vector<SQLColumn>(pk)));

         handler = new FormValidationHandler(status);
Validator validator = new OLAPObjectNameValidator(hierarchy.getParent(), hierarchy, true);
@@ -127,8 +108,6 @@
             hierarchy.setRelation(table);
         }
         hierarchy.setAllLevelName(allLevelName.getText());
-        SQLColumn column = (SQLColumn) primaryKeyName.getSelectedItem();
-        hierarchy.setPrimaryKey(column.getName());
         hierarchy.endCompoundEdit();
         return true;
     }

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateDimensionUsageAction.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateDimensionUsageAction.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateDimensionUsageAction.java Wed Aug 27 13:51:06 2008
@@ -19,17 +19,35 @@

 package ca.sqlpower.architect.swingui.olap.action;

+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.swing.JDialog;
 import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;

 import org.apache.log4j.Logger;

+import ca.sqlpower.architect.ArchitectException;
+import ca.sqlpower.architect.ArchitectRuntimeException;
+import ca.sqlpower.architect.SQLColumn;
+import ca.sqlpower.architect.SQLRelationship;
+import ca.sqlpower.architect.SQLTable;
+import ca.sqlpower.architect.SQLRelationship.ColumnMapping;
 import ca.sqlpower.architect.olap.OLAPUtil;
+import ca.sqlpower.architect.olap.MondrianModel.Cube;
+import ca.sqlpower.architect.olap.MondrianModel.Dimension;
 import ca.sqlpower.architect.olap.MondrianModel.DimensionUsage;
+import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
+import ca.sqlpower.architect.olap.MondrianModel.Table;
 import ca.sqlpower.architect.swingui.ArchitectSwingSession;
 import ca.sqlpower.architect.swingui.PlayPen;
 import ca.sqlpower.architect.swingui.olap.CubePane;
 import ca.sqlpower.architect.swingui.olap.DimensionPane;
+import ca.sqlpower.architect.swingui.olap.DimensionUsageEditPanel;
 import ca.sqlpower.architect.swingui.olap.UsageComponent;
+import ca.sqlpower.swingui.DataEntryPanel;
+import ca.sqlpower.swingui.DataEntryPanelBuilder;

 /**
  * Creates a dimension usage after the user clicks a DimensionPane and a
@@ -46,15 +64,64 @@

     @Override
     protected void createUsage(DimensionPane dp, CubePane cp) {
- if (OLAPUtil.isNameUnique(cp.getModel(), DimensionUsage.class, dp.getModel().getName())) {
-            DimensionUsage du = new DimensionUsage();
-            du.setName(dp.getModel().getName());
-            du.setSource(dp.getModel().getName());
-            cp.getModel().addChild(du);
+        final Dimension dimension = dp.getModel();
+        final Cube cube = cp.getModel();
+ if (OLAPUtil.isNameUnique(cp.getModel(), DimensionUsage.class, dimension.getName())) {
+            final DimensionUsage du = new DimensionUsage();
+            du.setName(dimension.getName());
+            du.setSource(dimension.getName());
+            cube.addChild(du);
UsageComponent uc = new UsageComponent(playpen.getContentPane(), du, dp, cp); playpen.getContentPane().add(uc, playpen.getContentPane().getComponentCount());
+
+            try {
+ SQLTable factTable = OLAPUtil.getSQLTableFromOLAPTable(OLAPUtil.getSession(cube).getDatabase(), (Table) (cube.getFact()));
+                SQLColumn defaultFK;
+ // If there is a relationship between the fact table and the dimension table,
+                // by default, the usage takes the mapped foreign key.
+                if (!factTable.getExportedKeys().isEmpty()) {
+ SQLRelationship relationship = factTable.getExportedKeys().get(0); + List<ColumnMapping> mappings = relationship.getMappings();
+                    defaultFK = mappings.get(0).getFkColumn();
+                    du.setForeignKey(defaultFK.toString());
+                    dimension.setForeignKey(defaultFK.toString());
+ // Further set all the hierarchy primary key to default value. + for (Hierarchy hierarchy : dimension.getHierarchies()) {
+                        hierarchy.setPrimaryKey(defaultFK.toString());
+                    }
+                } else {
+
+ final DataEntryPanel mep = new DimensionUsageEditPanel(du, dimension);
+                    Callable<Boolean> okCall = new Callable<Boolean>() {
+                        public Boolean call() throws Exception {
+ // Further set all the hierarchy primary key to default value on the first run. + for (Hierarchy hierarchy : dimension.getHierarchies()) { + hierarchy.setPrimaryKey(dimension.getForeignKey());
+                            }
+                            return mep.applyChanges();
+                        }
+                    };
+ Callable<Boolean> cancelCall = new Callable<Boolean>() {
+                        public Boolean call() throws Exception {
+                            du.getParent().removeChild(du);
+                            return true;
+                        }
+                    };
+ JDialog d = DataEntryPanelBuilder.createDataEntryPanelDialog(
+                            mep,
+                            SwingUtilities.getWindowAncestor(playpen),
+                            "Dimension Usage Properties",
+                            "OK",
+                            okCall,
+                            cancelCall);
+                    d.setLocationRelativeTo(playpen);
+                    d.setVisible(true);
+                }
+            } catch (ArchitectException e) {
+                throw new ArchitectRuntimeException(e);
+            }
         } else {
- String errorMsg = "Cube Dimension \"" + dp.getModel().getName() + "\" already exists in \"" + + String errorMsg = "Cube Dimension \"" + dimension.getName() + "\" already exists in \"" + cp.getModel().getName() + "\".\nDimension Usage was not created."; JOptionPane.showMessageDialog(playpen, errorMsg, "Duplicate Cube Dimension", JOptionPane.INFORMATION_MESSAGE);
         }

Modified: trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateHierarchyAction.java
==============================================================================
--- trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateHierarchyAction.java (original) +++ trunk/src/ca/sqlpower/architect/swingui/olap/action/CreateHierarchyAction.java Wed Aug 27 13:51:06 2008
@@ -22,6 +22,7 @@
 import ca.sqlpower.architect.ArchitectException;
 import ca.sqlpower.architect.ArchitectRuntimeException;
 import ca.sqlpower.architect.olap.OLAPUtil;
+import ca.sqlpower.architect.olap.MondrianModel.Dimension;
 import ca.sqlpower.architect.olap.MondrianModel.Hierarchy;
 import ca.sqlpower.architect.swingui.ArchitectSwingSession;
 import ca.sqlpower.architect.swingui.PlayPen;
@@ -49,6 +50,16 @@
         h.setName("New Hierarchy " + count);

         pane.getModel().addHierarchy(h);
+        /*
+ * If parent dimension is a private dimension, then first default the + * parimaryKey value to the foreignKey value of the parent dimension. A
+         * user is still able to modify this property.
+         */
+        Dimension dimension = (Dimension) h.getParent();
+        if (dimension.getForeignKey() != null) {
+            h.setPrimaryKey(dimension.getForeignKey());
+        }
+
         return h;
     }

Reply via email to