001/* Utility that checks the size of a model. 002 003 Copyright (c) 2006-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_3 025 COPYRIGHTENDKEY 026 */ 027package ptolemy.actor.gui; 028 029import java.io.File; 030import java.net.URL; 031import java.util.HashSet; 032import java.util.Iterator; 033import java.util.List; 034import java.util.Set; 035 036import ptolemy.actor.CompositeActor; 037import ptolemy.actor.TypedCompositeActor; 038import ptolemy.data.ArrayToken; 039import ptolemy.data.DoubleToken; 040import ptolemy.data.IntMatrixToken; 041import ptolemy.data.ScalarToken; 042import ptolemy.data.expr.ExpertParameter; 043import ptolemy.kernel.CompositeEntity; 044import ptolemy.kernel.util.IllegalActionException; 045import ptolemy.kernel.util.KernelException; 046import ptolemy.kernel.util.NamedObj; 047import ptolemy.moml.MoMLParser; 048import ptolemy.moml.filter.BackwardCompatibility; 049import ptolemy.moml.filter.RemoveGraphicalClasses; 050 051////////////////////////////////////////////////////////////////////////// 052//// CheckModelSize 053 054/** 055 Class that checks the size, zoom, and location of a model. 056 @author Rowland R Johnson 057 @version $Id$ 058 @since Ptolemy II 5.2 059 @Pt.ProposedRating Red (rowland) 060 @Pt.AcceptedRating Red (rowland) 061 */ 062public class CheckModelSize { 063 /** Check the size, zoom and location of the models named 064 * by the args. 065 * @param configuration The optional configuration to check. 066 * @param args An array of Strings naming the models to be checked. 067 * @return HTML that describes possible problems with the models. 068 * @exception Exception If there is a problem reading a model. 069 */ 070 public static String checkModelSize(Configuration configuration, 071 String[] args) throws Exception { 072 StringBuffer results = new StringBuffer(); 073 Set sizeProblemSet = new HashSet(); 074 if (configuration != null) { 075 List entityList = configuration.entityList(CompositeEntity.class); 076 Iterator entities = entityList.iterator(); 077 while (entities.hasNext()) { 078 Object entity = entities.next(); 079 if (entity instanceof TypedCompositeActor 080 && !sizeProblemSet.contains(entity)) { 081 String checkSizeOutput = _checkSize( 082 (TypedCompositeActor) entity, false); 083 if (!checkSizeOutput.equals("")) { 084 results.append( 085 "<tr>\n <td>" 086 + ((TypedCompositeActor) entity) 087 .getFullName() 088 + "</td>\n <td>" + checkSizeOutput 089 + "</td>\n"); 090 } 091 sizeProblemSet.add(entity); 092 } 093 } 094 095 List classList = configuration.classDefinitionList(); 096 entities = classList.iterator(); 097 while (entities.hasNext()) { 098 Object entity = entities.next(); 099 System.out.println("CheckModelSize: " + entity + " " 100 + (entity instanceof TypedCompositeActor)); 101 if (entity instanceof TypedCompositeActor 102 && !sizeProblemSet.contains(entity)) { 103 String checkSizeOutput = _checkSize( 104 (TypedCompositeActor) entity, false); 105 if (!checkSizeOutput.equals("")) { 106 results.append( 107 "<tr>\n <td><b>Class</b> " 108 + ((TypedCompositeActor) entity) 109 .getFullName() 110 + "</td>\n <td>" + checkSizeOutput 111 + "</td>\n"); 112 } 113 sizeProblemSet.add(entity); 114 } 115 } 116 117 } 118 119 for (String arg : args) { 120 String fileName = arg; 121 // if (fileName.endsWith("ENM_11_18_04.xml") 122 // || fileName.endsWith("IPCC_Base_Layers.xml") 123 // || fileName.endsWith("dataFrame_R.xml") 124 // || fileName.endsWith("eml_Table_as_Record_R.xml") 125 // || fileName.endsWith("emlToRecord_R.xml") 126 // || fileName.endsWith("eml-simple-linearRegression-R.xml") 127 // || fileName.endsWith("eml-pairs-R.xml")) { 128 // System.out.println("CheckModelSize: skipping " + fileName); 129 // continue; 130 // } 131 StringBuffer analysis = new StringBuffer(); 132 133 MoMLParser parser = new MoMLParser(); 134 MoMLParser.setMoMLFilters(BackwardCompatibility.allFilters()); 135 136 RemoveGraphicalClasses removeGraphicalClasses = new RemoveGraphicalClasses(); 137 138 // Remove StaticSchedulingCodeGenerator from Butterfly 139 // because during the nightly build the codegenerator is 140 // not yet built when the tests in actor.gui are run. 141 removeGraphicalClasses.put( 142 "ptolemy.codegen.kernel.StaticSchedulingCodeGenerator", 143 null); 144 // We need the _vergilSize attribute, which is removed by 145 // removeGraphicalClasses, so we modify removeGraphicalClasses 146 // so that it no longer removes SizeAttributes. 147 removeGraphicalClasses.remove("ptolemy.actor.gui.SizeAttribute"); 148 149 // Filter out any graphical classes. 150 MoMLParser.addMoMLFilter(removeGraphicalClasses); 151 152 if (!(fileName.endsWith(".xml") || fileName.endsWith(".moml"))) { 153 continue; 154 } 155 156 try { 157 NamedObj top = null; 158 try { 159 top = parser.parse(null, 160 new File(fileName).toURI().toURL()); 161 } catch (Exception ex) { 162 try { 163 top = parser.parse(null, new URL(fileName)); 164 } catch (Exception ex2) { 165 throw new Exception("Failed to parse \"" + fileName 166 + "\". First exception:\n" + ex, ex2); 167 } 168 } 169 String checkSizeOutput = _checkSize(top, false); 170 if (checkSizeOutput.equals("")) { 171 analysis.append(" seems to be OK."); 172 } else { 173 analysis.append(checkSizeOutput); 174 } 175 176 if (top instanceof CompositeEntity) { 177 List entityList = ((CompositeEntity) top).deepEntityList(); 178 Iterator entities = entityList.iterator(); 179 while (entities.hasNext()) { 180 Object entity = entities.next(); 181 if (entity instanceof TypedCompositeActor 182 && !sizeProblemSet.contains(entity)) { 183 checkSizeOutput = _checkSize( 184 (TypedCompositeActor) entity, false); 185 if (!checkSizeOutput.equals("")) { 186 sizeProblemSet.add(entity); 187 results.append("<tr>\n <td>" 188 + ((TypedCompositeActor) entity) 189 .getFullName() 190 + "</td>\n <td>" + checkSizeOutput 191 + "</td>\n"); 192 } 193 sizeProblemSet.add(entity); 194 } 195 } 196 } 197 198 } catch (Throwable throwable) { 199 analysis.append(" can't be parsed because "); 200 analysis.append(KernelException.stackTraceToString(throwable)); 201 } 202 String fileURL = new File(fileName).toURI().toURL().toString(); 203 results.append("<tr>\n <td><a href=\"" + fileURL + "\">" + fileURL 204 + "</a></td>\n <td>" + analysis + "</td>\n"); 205 206 } 207 208 return "<h1>Check Size</h1>\nBelow are the results from checking the " 209 + "sizes of and centering of models\n<table>\n" 210 + "<b>Note: after running review these results, be" 211 + " sure to exit, as the graphical elements of the " 212 + " models will have been removed</b>\n" + results.toString() 213 + "</table>\n"; 214 } 215 216 /** Check the size, zoom and location of the models named 217 * by the args. 218 * @param args An array of Strings naming the models to be checked. 219 * 220 */ 221 public static void main(String[] args) { 222 try { 223 System.out.println(CheckModelSize.checkModelSize(null, args)); 224 } catch (Throwable throwable) { 225 throwable.printStackTrace(); 226 } 227 } 228 229 /** Check the size and centering of the model. 230 * @param top The NamedObj to check 231 * @return A string describing size problems associated with the model. 232 */ 233 private static String _checkSize(NamedObj top, 234 boolean ignoreMissingVergilSize) { 235 StringBuffer analysis = new StringBuffer(); 236 if (top instanceof CompositeActor) { 237 SizeAttribute vergilSize = (SizeAttribute) top 238 .getAttribute("_vergilSize"); 239 ExpertParameter vergilZoom = (ExpertParameter) top 240 .getAttribute("_vergilZoomFactor"); 241 ExpertParameter vergilCenter = (ExpertParameter) top 242 .getAttribute("_vergilCenter"); 243 244 if (vergilSize != null) { 245 try { 246 IntMatrixToken vergilSizeToken; 247 vergilSizeToken = (IntMatrixToken) vergilSize.getToken(); 248 249 if (vergilSizeToken == null) { 250 throw new IllegalActionException(top, 251 "_vergilSize token was null?"); 252 } 253 int width = vergilSizeToken.getElementAt(0, 0); 254 int height = vergilSizeToken.getElementAt(0, 1); 255 256 if (width > 800) { 257 analysis.append(" width(" + width + ") > 800"); 258 } 259 260 if (height > 768) { 261 analysis.append(" height(" + height + ") > 768"); 262 } 263 264 if (vergilCenter != null) { 265 try { 266 ArrayToken vergilCenterToken = (ArrayToken) vergilCenter 267 .getToken(); 268 double x = ((ScalarToken) vergilCenterToken 269 .getElement(0)).doubleValue(); 270 double y = ((ScalarToken) vergilCenterToken 271 .getElement(1)).doubleValue(); 272 273 // Avoid comparing floats. 274 if (Math.abs(x - width / 2.0) > 0.1 275 || Math.abs(y - height / 2.0) > 0.1) { 276 analysis.append(" Center([" + x + ", " + y 277 + "]) is not centered, should be [" 278 + width / 2.0 + ", " + height / 2.0 279 + "]"); 280 } 281 } catch (IllegalActionException ex) { 282 analysis.append(" _vergilCenter malformed"); 283 analysis.append( 284 KernelException.stackTraceToString(ex)); 285 } 286 } 287 } catch (IllegalActionException ex) { 288 analysis.append(" _vergilSize malformed"); 289 analysis.append(KernelException.stackTraceToString(ex)); 290 } 291 292 if (vergilZoom != null) { 293 try { 294 DoubleToken vergilZoomToken = (DoubleToken) vergilZoom 295 .getToken(); 296 double zoom = vergilZoomToken.doubleValue(); 297 298 if (zoom != 1.0) { 299 analysis.append(" Zoom(" + zoom + ") != 1.0"); 300 } 301 } catch (IllegalActionException ex) { 302 analysis.append(" _vergilZoom malformed"); 303 analysis.append(KernelException.stackTraceToString(ex)); 304 } 305 } 306 } else { 307 if (!ignoreMissingVergilSize) { 308 analysis.append(" has no _vergilSize."); 309 } 310 } 311 } else { 312 analysis.append( 313 " is a " + top.getClassName() + " not a CompositeActor."); 314 } 315 316 return analysis.toString(); 317 } 318}