1// BEGIN LICENSE BLOCK 2// Version: CMPL 1.1 3// 4// The contents of this file are subject to the Cisco-style Mozilla Public 5// License Version 1.1 (the "License"); you may not use this file except 6// in compliance with the License. You may obtain a copy of the License 7// at www.eclipse-clp.org/license. 8// 9// Software distributed under the License is distributed on an "AS IS" 10// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11// the License for the specific language governing rights and limitations 12// under the License. 13// 14// The Original Code is The ECLiPSe Constraint Logic Programming System. 15// The Initial Developer of the Original Code is Cisco Systems, Inc. 16// Portions created by the Initial Developer are 17// Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18// 19// Contributor(s): 20// 21// END LICENSE BLOCK 22 23package com.parctechnologies.eclipse.visualisation; 24 25import java.util.*; 26import java.beans.*; 27import javax.swing.table.*; 28import com.parctechnologies.eclipse.*; 29 30/** 31 * A SparseViewletStore is a recursive data structure intended to 32 * mirror the number, size and fixity of the dimensions of a certain 33 * elements within a viewable on the eclipse side. 34 * 35 * <p> Instead of viewable elements, it contains viewlet data. Each 36 * viewlet is produced from a ViewletFactory. 37 * 38 * <p> Note that ViewletArray is not responsible for maintaining 39 * location names, only for keeping references to them and providing 40 * access to them. 41 * */ 42public class SparseViewletStore extends AbstractViewletDataStore implements MultiViewletDataStore 43{ 44 /** 45 *Hold the individual ViewletDataStores on a per type basis 46 */ 47 private Map wrappedStoreMap; 48 49 /** 50 * lists the fixities of the viewable. 51 * */ 52 private List fixity; 53 54 /** 55 * elements is a map, going from indices represented as lists to 56 * ViewletData 57 * */ 58 private Map elements; 59 60 61 /** 62 * Construct a SparseViewletStore given a list of integers (size), a 63 * fixity list (fixity). 64 * */ 65 public SparseViewletStore(List size, 66 List fixity, 67 Viewable viewable) { 68 super(size, fixity, viewable, null); 69 this.fixity = fixity; 70 this.elements = new HashMap(); 71 } 72 73 74 /** 75 * Traverses the entire structure recursively to collect together all the 76 * element indices. 77 */ 78 public ViewletRange getEntireViewletRange() 79 { 80 //return super.getEntireViewletRange(); 81 return new ViewletRangeCollection(elements.keySet()); 82 } 83 84 /** 85 * Shrinks the ViewletArray to size newSize. Assumes the top-level fixity is 86 * flexible. 87 */ 88 public void shrinkTo(List newSize) { 89 super.shrinkTo(newSize); 90 // Indicate to the table that rows/columns have been removed 91 fireTableStructureChanged(); 92 } 93 94 /** 95 * Expand dimension nested at level <code>dimension</code> by one. 96 */ 97 public void startExpandDimension(int dimension) { 98 super.startExpandDimension(dimension); 99 } 100 101 102 /** 103 * Implements the abstract getViewletDataAt method 104 */ 105 public ViewletData getViewletDataAt(List index) { 106 if(index.size() != getSize().size()) { 107 throw(new IllegalArgumentException()); 108 } 109 return((ViewletData) getElement(index)); 110 } 111 112 /** 113 * Implements the abstract setViewletDataAt method 114 */ 115 public void setViewletDataAt(List index, ViewletData data) { 116 if(index.size() != getSize().size()) { 117 throw(new IllegalArgumentException()); 118 } 119 if (DebuggingSupport.logMessages) { 120 DebuggingSupport.logMessage(this, "SparseViewletStore setViewletDataAt index="+index+" data="+data); 121 } 122 if (data != null) { 123 setElement(index, data); 124 } else { 125 removeElement(index); 126 } 127 } 128 129 /** 130 * Get element with location index within the ViewletArray. Result may be a 131 * ViewletArray or a Viewlet, depending on the length of the index parameter. 132 */ 133 private Object getElement(List index) 134 { 135 Object result = elements.get(index); 136 return result; 137 } 138 139 /** 140 * Sets the element with location index within the ViewletArray. */ 141 private void setElement(List index, Object data) 142 { 143 elements.put(index, data); 144 } 145 146 /** 147 * Removes the element with location index within the ViewletArray. */ 148 private void removeElement(List index) 149 { 150 elements.remove(index); 151 } 152 153 /** 154 * Factory method for creating ViewletRange object from any given 155 * collection. 156 * 157 * <p>This defualt implementation will create a generic 158 * ViewletRange. Subclasses can override this if specialised 159 * structures make more sense. */ 160 public ViewletRange createRange(Collection indices) { 161 ViewletRange range = new ViewletRangeCollection(); 162 // filter the range to only include those indices in the current 163 // map 164 for(Iterator it = indices.iterator(); it.hasNext(); ) { 165 Object index = it.next(); 166 if (elements.get(index)!=null) { 167 range.add(index); 168 } 169 } 170 return range; 171 } 172 173 174 /** 175 * Factory method for creating ViewletRange objects to cover all 176 * elements between the given start and end indices. 177 * 178 * <p>This defualt implementation will create a generic 179 * ViewletRange. Subclasses can override this if specialised 180 * structures make more sense. */ 181 public ViewletRange createRange(List fromIndex, List toIndex) { 182 ViewletRange indices = super.createRange(fromIndex, toIndex); 183 ViewletRange range = new ViewletRangeCollection(); 184 // filter the range to only include those indices in the current 185 // map 186 for(Iterator it = indices.iterator(); it.hasNext(); ) { 187 Object index = it.next(); 188 if (elements.get(index)!=null) { 189 range.add(index); 190 } 191 } 192 return range; 193 } 194 195 /** 196 * Returns a wrapper store which intercedes whenever viewlet data 197 * is get or set. 198 * 199 * Implements method from the MultiViewletDataStore interface 200 * */ 201 public ViewletDataStore getViewletDataStore(ViewletType type) { 202 // Note the outer test is not synchronized to speed up normal code flow 203 // but the test is duplicated within 204 if (wrappedStoreMap == null) { 205 synchronized(this) { 206 if (wrappedStoreMap == null) { 207 wrappedStoreMap=new HashMap(); 208 } 209 } 210 } 211 ViewletDataStore result = (ViewletDataStore)wrappedStoreMap.get(type); 212 if (result == null) { 213 synchronized(this) { 214 if (result == null) { 215 result = 216 new WrappedMultiViewletDataStore(this, type); 217 result.setSymRef(new SymRef(result,this.getSymRef(),type.getClass().getName())); 218 wrappedStoreMap.put(type, result); 219 } 220 } 221 } 222 return result; 223 } 224 225} 226