001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2002-2005 Julian Hyde 008// Copyright (C) 2005-2010 Pentaho and others 009// Copyright (C) 2006-2007 CINCOM SYSTEMS, INC. 010// All Rights Reserved. 011*/ 012package mondrian.gui; 013 014import mondrian.util.CompositeList; 015 016import java.util.*; 017import javax.swing.tree.*; 018 019/** 020 * @author sean 021 */ 022public class SchemaTreeModel extends DefaultTreeModel { 023 /** 024 * Creates a SchemaTreeModel. 025 */ 026 public SchemaTreeModel() { 027 super(null); 028 // TODO Auto-generated constructor stub 029 } 030 031 MondrianGuiDef.Schema schema; 032 033 /** 034 * Creates a new instance of SchemaTreeModel 035 */ 036 public SchemaTreeModel(MondrianGuiDef.Schema s) { 037 super(new DefaultMutableTreeNode(s.name)); 038 this.schema = s; 039 } 040 041 042 /** 043 * Returns the child of <code>parent</code> at index <code>index</code> 044 * in the parent's 045 * child array. <code>parent</code> must be a node previously obtained 046 * from this data source. This should not return <code>null</code> 047 * if <code>index</code> 048 * is a valid index for <code>parent</code> (that is <code>index >= 0 && 049 * index < getChildCount(parent</code>)). 050 * 051 * @param parent a node in the tree, obtained from this data source 052 * @return the child of <code>parent</code> at index <code>index</code> 053 */ 054 public Object getChild(Object parent, int index) { 055 return getChildList(parent).get(index); 056 } 057 058 /** 059 * Returns an immutable list of child elements of a given element. 060 * 061 * @param parent Parent element 062 * @return List of children 063 */ 064 private List<Object> getChildList(Object parent) { 065 if (parent instanceof MondrianGuiDef.Cube) { 066 MondrianGuiDef.Cube c = (MondrianGuiDef.Cube) parent; 067 // Return children in this order: fact table, dimensions, measures, 068 // calculatedMembers, namedSets 069 return new CompositeList<Object>( 070 ifList(c.fact), 071 Arrays.asList(c.dimensions), 072 Arrays.asList(c.measures), 073 Arrays.asList(c.calculatedMembers), 074 Arrays.asList(c.namedSets), 075 ifList(c.annotations)); 076 } else if (parent instanceof MondrianGuiDef.Dimension) { 077 MondrianGuiDef.Dimension d = (MondrianGuiDef.Dimension) parent; 078 return new CompositeList<Object>( 079 Arrays.asList((Object[]) d.hierarchies), 080 ifList(d.annotations)); 081 } else if (parent instanceof MondrianGuiDef.UserDefinedFunction) { 082 MondrianGuiDef.UserDefinedFunction udf = 083 (MondrianGuiDef.UserDefinedFunction) parent; 084 return new CompositeList<Object>( 085 ifList(udf.script)); 086 } else if (parent instanceof MondrianGuiDef.ExpressionView) { 087 MondrianGuiDef.ExpressionView ev = 088 (MondrianGuiDef.ExpressionView) parent; 089 return Arrays.asList((Object[]) ev.expressions); 090 } else if (parent instanceof MondrianGuiDef.Hierarchy) { 091 MondrianGuiDef.Hierarchy h = (MondrianGuiDef.Hierarchy) parent; 092 return new CompositeList<Object>( 093 Arrays.asList(h.levels), 094 Arrays.asList(h.memberReaderParameters), 095 ifList(h.relation), 096 ifList(h.annotations)); 097 } else if (parent instanceof MondrianGuiDef.Join) { 098 MondrianGuiDef.Join j = (MondrianGuiDef.Join) parent; 099 return Arrays.<Object>asList( 100 j.left, 101 j.right); 102 } else if (parent instanceof MondrianGuiDef.Level) { 103 MondrianGuiDef.Level level = (MondrianGuiDef.Level) parent; 104 return new CompositeList<Object>( 105 Arrays.asList(level.properties), 106 ifList(level.keyExp), 107 ifList(level.nameExp), 108 ifList(level.ordinalExp), 109 ifList(level.captionExp), 110 ifList(level.parentExp), 111 ifList(level.closure), 112 ifList(level.memberFormatter), 113 ifList(level.annotations)); 114 } else if (parent instanceof MondrianGuiDef.CellFormatter) { 115 MondrianGuiDef.CellFormatter f = 116 (MondrianGuiDef.CellFormatter) parent; 117 return new CompositeList<Object>( 118 ifList(f.script)); 119 } else if (parent instanceof MondrianGuiDef.MemberFormatter) { 120 MondrianGuiDef.MemberFormatter f = 121 (MondrianGuiDef.MemberFormatter) parent; 122 return new CompositeList<Object>( 123 ifList(f.script)); 124 } else if (parent instanceof MondrianGuiDef.PropertyFormatter) { 125 MondrianGuiDef.PropertyFormatter f = 126 (MondrianGuiDef.PropertyFormatter) parent; 127 return new CompositeList<Object>( 128 ifList(f.script)); 129 } else if (parent instanceof MondrianGuiDef.Property) { 130 MondrianGuiDef.Property property = 131 (MondrianGuiDef.Property) parent; 132 return new CompositeList<Object>( 133 ifList(property.propertyFormatter)); 134 } else if (parent instanceof MondrianGuiDef.CalculatedMember) { 135 MondrianGuiDef.CalculatedMember c = 136 (MondrianGuiDef.CalculatedMember) parent; 137 return new CompositeList<Object>( 138 ifList(c.formulaElement), 139 arrayList(c.memberProperties), 140 ifList(c.annotations), 141 ifList(c.cellFormatter)); 142 } else if (parent instanceof MondrianGuiDef.Measure) { 143 MondrianGuiDef.Measure m = (MondrianGuiDef.Measure) parent; 144 return new CompositeList<Object>( 145 ifList(m.measureExp), 146 arrayList(m.memberProperties), 147 ifList(m.annotations), 148 ifList(m.cellFormatter)); 149 } else if (parent instanceof MondrianGuiDef.NamedSet) { 150 MondrianGuiDef.NamedSet m = (MondrianGuiDef.NamedSet) parent; 151 return new CompositeList<Object>( 152 ifList((Object) m.formulaElement), 153 ifList(m.annotations)); 154 } else if (parent instanceof MondrianGuiDef.Schema) { 155 MondrianGuiDef.Schema s = (MondrianGuiDef.Schema) parent; 156 // Return children in this order: cubes, dimensions, namedSets, 157 // userDefinedFunctions, virtual cubes, roles 158 return new CompositeList<Object>( 159 Arrays.asList(s.cubes), 160 Arrays.asList(s.dimensions), 161 Arrays.asList(s.namedSets), 162 Arrays.asList(s.namedSets), 163 Arrays.asList(s.userDefinedFunctions), 164 Arrays.asList(s.virtualCubes), 165 Arrays.asList(s.roles), 166 Arrays.asList(s.parameters), 167 ifList(s.annotations)); 168 } else if (parent instanceof MondrianGuiDef.Table) { 169 MondrianGuiDef.Table t = (MondrianGuiDef.Table) parent; 170 return new CompositeList<Object>( 171 arrayList(t.aggTables), 172 arrayList(t.aggExcludes)); 173 } else if (parent instanceof MondrianGuiDef.AggTable) { 174 MondrianGuiDef.AggTable t = (MondrianGuiDef.AggTable) parent; 175 return new CompositeList<Object>( 176 ifList(t.factcount), 177 Arrays.asList(t.ignoreColumns), 178 Arrays.asList(t.foreignKeys), 179 Arrays.asList(t.measures), 180 Arrays.asList(t.levels), 181 (t instanceof MondrianGuiDef.AggPattern) 182 ? Arrays.asList(((MondrianGuiDef.AggPattern) t).excludes) 183 : Collections.emptyList()); 184 } else if (parent instanceof MondrianGuiDef.View) { 185 MondrianGuiDef.View v = (MondrianGuiDef.View) parent; 186 return Arrays.asList((Object[]) v.selects); 187 } else if (parent instanceof MondrianGuiDef.VirtualCube) { 188 MondrianGuiDef.VirtualCube c = (MondrianGuiDef.VirtualCube) parent; 189 return new CompositeList<Object>( 190 Arrays.asList(c.dimensions), 191 Arrays.asList(c.measures), 192 Arrays.asList(c.calculatedMembers), 193 ifList(c.annotations)); 194 } else if (parent instanceof MondrianGuiDef.VirtualCubeDimension) { 195 MondrianGuiDef.VirtualCubeDimension d = 196 (MondrianGuiDef.VirtualCubeDimension) parent; 197 return ifList((Object)d.annotations); 198 } else if (parent instanceof MondrianGuiDef.VirtualCubeMeasure) { 199 MondrianGuiDef.VirtualCubeMeasure m = 200 (MondrianGuiDef.VirtualCubeMeasure) parent; 201 return ifList((Object)m.annotations); 202 } else if (parent instanceof MondrianGuiDef.Role) { 203 MondrianGuiDef.Role c = (MondrianGuiDef.Role) parent; 204 return new CompositeList<Object>( 205 Arrays.asList((Object[]) c.schemaGrants), 206 ifList((Object)c.annotations)); 207 } else if (parent instanceof MondrianGuiDef.SchemaGrant) { 208 MondrianGuiDef.SchemaGrant c = (MondrianGuiDef.SchemaGrant) parent; 209 return Arrays.asList((Object[]) c.cubeGrants); 210 } else if (parent instanceof MondrianGuiDef.CubeGrant) { 211 MondrianGuiDef.CubeGrant c = (MondrianGuiDef.CubeGrant) parent; 212 return new CompositeList<Object>( 213 Arrays.asList(c.dimensionGrants), 214 Arrays.asList(c.hierarchyGrants)); 215 } else if (parent instanceof MondrianGuiDef.HierarchyGrant) { 216 MondrianGuiDef.HierarchyGrant c = 217 (MondrianGuiDef.HierarchyGrant) parent; 218 return Arrays.asList((Object[]) c.memberGrants); 219 } else if (parent instanceof MondrianGuiDef.Closure) { 220 MondrianGuiDef.Closure c = (MondrianGuiDef.Closure) parent; 221 return ifList((Object) c.table); 222 } else if (parent instanceof MondrianGuiDef.Annotations) { 223 MondrianGuiDef.Annotations annotations = 224 (MondrianGuiDef.Annotations) parent; 225 return Arrays.asList((Object[]) annotations.array); 226 } else { 227 // In particular: Column, SQL, DimensionUsage have no children. 228 return Collections.emptyList(); 229 } 230 } 231 232 /** 233 * Returns a list with zero or one elements. 234 * 235 * @param e Element 236 * @param <T> Element type 237 * @return List containing element if it is not null, otherwise empty list 238 */ 239 private <T> List<T> ifList(T e) { 240 return e == null 241 ? Collections.<T>emptyList() 242 : Collections.singletonList(e); 243 } 244 245 /** 246 * Returns a list with a given set of elements, or an empty list if the 247 * array is null. 248 * 249 * @param e Element 250 * @param <T> Element type 251 * @return List containing element if it is not null, otherwise empty list 252 */ 253 private <T> List<T> arrayList(T... e) { 254 return e == null || e.length == 0 255 ? Collections.<T>emptyList() 256 : e.length == 1 257 ? Collections.singletonList(e[0]) 258 : Arrays.asList(e); 259 } 260 261 /** 262 * Returns the number of children of <code>parent</code>. 263 * Returns 0 if the node 264 * is a leaf or if it has no children. <code>parent</code> must be a node 265 * previously obtained from this data source. 266 * 267 * @param parent a node in the tree, obtained from this data source 268 * @return the number of children of the node <code>parent</code> 269 */ 270 public int getChildCount(Object parent) { 271 return getChildList(parent).size(); 272 } 273 274 /** 275 * Returns the index of child in parent. If <code>parent</code> 276 * is <code>null</code> or <code>child</code> is <code>null</code>, 277 * returns -1. 278 * 279 * @param parent a note in the tree, obtained from this data source 280 * @param child the node we are interested in 281 * @return the index of the child in the parent, or -1 if either 282 * <code>child</code> or <code>parent</code> are <code>null</code> 283 */ 284 public int getIndexOfChild(Object parent, Object child) { 285 if (parent == null) { 286 return -1; 287 } 288 final List<Object> list = getChildList(parent); 289 int i = 0; 290 for (Object o : list) { 291 if (equal(o, child)) { 292 return i; 293 } 294 ++i; 295 } 296 return -1; 297 } 298 299 /** 300 * Returns whether two XML objects are equal. 301 * 302 * @param o1 First object 303 * @param o2 Second object 304 * @return Whether objects are equal 305 */ 306 private boolean equal(Object o1, Object o2) { 307 if (o1 == null) { 308 return o2 == null; 309 } else if (o1 instanceof MondrianGuiDef.Hierarchy 310 || o1 instanceof MondrianGuiDef.SQL) 311 { 312 return o1 == o2; 313 } else { 314 return o1.equals(o2); 315 } 316 } 317 318 /** 319 * Returns the root of the tree. Returns <code>null</code> 320 * only if the tree has no nodes. 321 * 322 * @return the root of the tree 323 */ 324 public Object getRoot() { 325 return schema; 326 } 327 328 /** 329 * Returns <code>true</code> if <code>node</code> is a leaf. 330 * It is possible for this method to return <code>false</code> 331 * even if <code>node</code> has no children. 332 * A directory in a filesystem, for example, 333 * may contain no files; the node representing 334 * the directory is not a leaf, but it also has no children. 335 * 336 * @param node a node in the tree, obtained from this data source 337 * @return true if <code>node</code> is a leaf 338 */ 339 public boolean isLeaf(Object node) { 340 return getChildCount(node) == 0; 341 } 342 343 public void valueForPathChanged(TreePath path, Object newValue) { 344 //super.valueForPathChanged(path, newValue); 345 } 346 347} 348 349// End SchemaTreeModel.java