1 /* 2 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.oracle.javafx.scenebuilder.kit.fxom; 33 34 import com.oracle.javafx.scenebuilder.kit.fxom.glue.GlueElement; 35 import com.oracle.javafx.scenebuilder.kit.metadata.util.PrefixedValue; 36 import com.oracle.javafx.scenebuilder.kit.metadata.util.PropertyName; 37 import com.oracle.javafx.scenebuilder.kit.util.JavaLanguage; 38 import java.net.URL; 39 import java.util.ArrayList; 40 import java.util.Collections; 41 import java.util.Iterator; 42 import java.util.LinkedHashMap; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.Set; 46 import javafx.fxml.FXMLLoader; 47 48 /** 49 * 50 * 51 */ 52 public class FXOMInstance extends FXOMObject { 53 54 private final Map<PropertyName, FXOMProperty> properties = new LinkedHashMap<>(); 55 private Class<?> declaredClass; 56 57 58 FXOMInstance( 59 FXOMDocument fxomDocument, 60 GlueElement glueElement, 61 Class<?> declaredClass, 62 Object sceneGraphObject, 63 List<FXOMProperty> properties) { 64 super(fxomDocument, glueElement, sceneGraphObject); 65 66 assert declaredClass != null; 67 assert glueElement.getTagName().equals("fx:root") 68 || glueElement.getTagName().equals(PropertyName.makeClassFullName(declaredClass)) 69 || glueElement.getTagName().equals(declaredClass.getCanonicalName()); 70 assert sceneGraphObject != null; 71 assert properties != null; 72 73 this.declaredClass = declaredClass; 74 for (FXOMProperty p : properties) { 75 this.properties.put(p.getName(), p); 76 p.setParentInstance(this); 77 } 78 } 79 80 FXOMInstance( 81 FXOMDocument fxomDocument, 82 GlueElement glueElement, 83 List<FXOMProperty> properties) { 84 super(fxomDocument, glueElement, null); 85 86 assert properties != null; 87 88 this.declaredClass = null; 89 for (FXOMProperty p : properties) { 90 this.properties.put(p.getName(), p); 91 p.setParentInstance(this); 92 } 93 } 94 95 public FXOMInstance(FXOMDocument fxomDocument, Class<?> declaredClass) { 96 super(fxomDocument, PropertyName.makeClassFullName(declaredClass)); 97 this.declaredClass = declaredClass; 98 } 99 100 public FXOMInstance(FXOMDocument fxomDocument, String tagName) { 101 super(fxomDocument, tagName); 102 this.declaredClass = null; // This is an unresolved instance 103 } 104 105 public Class<?> getDeclaredClass() { 106 return declaredClass; 107 } 108 109 public void setDeclaredClass(Class<?> declaredClass) { 110 this.declaredClass = declaredClass; 111 } 112 113 public Map<PropertyName, FXOMProperty> getProperties() { 114 return Collections.unmodifiableMap(properties); 115 } 116 117 public boolean isFxRoot() { 118 return getGlueElement().getTagName().equals("fx:root"); 119 } 120 121 public void toggleFxRoot() { 122 123 if (isFxRoot()) { 124 assert getType() != null; 125 getGlueElement().setTagName(getType()); 126 getGlueElement().getAttributes().remove(FXMLLoader.ROOT_TYPE_ATTRIBUTE); 127 } else { 128 assert getType() == null; 129 getGlueElement().getAttributes().put(FXMLLoader.ROOT_TYPE_ATTRIBUTE, getGlueElement().getTagName()); 130 getGlueElement().setTagName("fx:root"); 131 } 132 } 133 134 public String getType() { 135 return getGlueElement().getAttributes().get(FXMLLoader.ROOT_TYPE_ATTRIBUTE); 136 } 137 138 /* 139 * FXOMObject 140 */ 141 142 @Override 143 public void addToParentCollection(int index, FXOMCollection newParentCollection) { 144 super.addToParentCollection(index, newParentCollection); 145 146 // May be this object was root : fx:root, type properties must be reset. 147 resetRootProperties(); 148 } 149 150 @Override 151 public void addToParentProperty(int index, FXOMPropertyC newParentProperty) { 152 super.addToParentProperty(index, newParentProperty); //To change body of generated methods, choose Tools | Templates. 153 154 // May be this object was root : fx:root, type properties must be reset. 155 resetRootProperties(); 156 } 157 158 159 @Override 160 public List<FXOMObject> getChildObjects() { 161 final List<FXOMObject> result = new ArrayList<>(); 162 163 for (FXOMProperty p : properties.values()) { 164 if (p instanceof FXOMPropertyC) { 165 final FXOMPropertyC pc = (FXOMPropertyC) p; 166 result.addAll(pc.getValues()); 167 } 168 } 169 return result; 170 } 171 172 173 @Override 174 public FXOMObject searchWithSceneGraphObject(Object sceneGraphObject) { 175 FXOMObject result; 176 177 result = super.searchWithSceneGraphObject(sceneGraphObject); 178 if (result == null) { 179 final Iterator<FXOMProperty> it = properties.values().iterator(); 180 while ((result == null) && it.hasNext()) { 181 final FXOMProperty property = it.next(); 182 if (property instanceof FXOMPropertyC) { 183 FXOMPropertyC propertyC = (FXOMPropertyC) property; 184 final Iterator<FXOMObject> itValue = propertyC.getValues().iterator(); 185 while ((result == null) && itValue.hasNext()) { 186 final FXOMObject value = itValue.next(); 187 result = value.searchWithSceneGraphObject(sceneGraphObject); 188 } 189 } 190 } 191 } 192 193 return result; 194 } 195 196 @Override 197 public FXOMObject searchWithFxId(String fxId) { 198 FXOMObject result; 199 200 result = super.searchWithFxId(fxId); 201 if (result == null) { 202 final Iterator<FXOMProperty> it = properties.values().iterator(); 203 while ((result == null) && it.hasNext()) { 204 final FXOMProperty property = it.next(); 205 if (property instanceof FXOMPropertyC) { 206 FXOMPropertyC propertyC = (FXOMPropertyC) property; 207 final Iterator<FXOMObject> itValue = propertyC.getValues().iterator(); 208 while ((result == null) && itValue.hasNext()) { 209 final FXOMObject value = itValue.next(); 210 result = value.searchWithFxId(fxId); 211 } 212 } 213 } 214 } 215 216 return result; 217 } 218 219 @Override 220 protected void collectDeclaredClasses(Set<Class<?>> result) { 221 assert result != null; 222 223 if (declaredClass != null) { 224 result.add(declaredClass); 225 } 226 227 for (FXOMProperty p : properties.values()) { 228 if (p instanceof FXOMPropertyC) { 229 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 230 v.collectDeclaredClasses(result); 231 } 232 } 233 } 234 } 235 236 @Override 237 protected void collectProperties(PropertyName propertyName, List<FXOMProperty> result) { 238 assert propertyName != null; 239 assert result != null; 240 241 for (FXOMProperty p : properties.values()) { 242 if (p.getName().equals(propertyName)) { 243 result.add(p); 244 } 245 if (p instanceof FXOMPropertyC) { 246 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 247 v.collectProperties(propertyName, result); 248 } 249 } 250 } 251 } 252 253 @Override 254 protected void collectNullProperties(List<FXOMPropertyT> result) { 255 assert result != null; 256 257 for (FXOMProperty p : properties.values()) { 258 if (p instanceof FXOMPropertyT) { 259 final FXOMPropertyT tp = (FXOMPropertyT) p; 260 if (tp.getValue().equals("$null")) { 261 result.add(tp); 262 } 263 } else { 264 assert p instanceof FXOMPropertyC; 265 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 266 v.collectNullProperties(result); 267 } 268 } 269 } 270 } 271 272 @Override 273 protected void collectPropertiesT(List<FXOMPropertyT> result) { 274 assert result != null; 275 276 for (FXOMProperty p : properties.values()) { 277 if (p instanceof FXOMPropertyT) { 278 final FXOMPropertyT tp = (FXOMPropertyT) p; 279 result.add(tp); 280 } else { 281 assert p instanceof FXOMPropertyC; 282 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 283 v.collectPropertiesT(result); 284 } 285 } 286 } 287 } 288 289 @Override 290 protected void collectReferences(String source, List<FXOMIntrinsic> result) { 291 for (FXOMProperty p : properties.values()) { 292 if (p instanceof FXOMPropertyC) { 293 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 294 v.collectReferences(source, result); 295 } 296 } 297 } 298 } 299 300 @Override 301 protected void collectReferences(String source, FXOMObject scope, List<FXOMNode> result) { 302 if ((scope == null) || (scope != this)) { 303 for (FXOMProperty p : properties.values()) { 304 if (p instanceof FXOMPropertyC) { 305 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 306 v.collectReferences(source, scope, result); 307 } 308 } else if (p instanceof FXOMPropertyT) { 309 final FXOMPropertyT pt = (FXOMPropertyT) p; 310 final PrefixedValue pv = new PrefixedValue(pt.getValue()); 311 if (pv.isExpression()) { 312 final String suffix = pv.getSuffix(); 313 if (JavaLanguage.isIdentifier(suffix)) { 314 if ((source == null) || source.equals(suffix)) { 315 result.add(pt); 316 } 317 } 318 } 319 } 320 } 321 } 322 } 323 324 @Override 325 protected void collectIncludes(String source, List<FXOMIntrinsic> result) { 326 for (FXOMProperty p : properties.values()) { 327 if (p instanceof FXOMPropertyC) { 328 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 329 v.collectIncludes(source, result); 330 } 331 } 332 } 333 } 334 335 @Override 336 protected void collectFxIds(Map<String, FXOMObject> result) { 337 final String fxId = getFxId(); 338 if (fxId != null) { 339 result.put(fxId, this); 340 } 341 342 for (FXOMProperty p : properties.values()) { 343 if (p instanceof FXOMPropertyC) { 344 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 345 v.collectFxIds(result); 346 } 347 } 348 } 349 } 350 351 @Override 352 protected void collectObjectWithSceneGraphObjectClass(Class<?> sceneGraphObjectClass, List<FXOMObject> result) { 353 if (getSceneGraphObject() != null) { 354 if (getSceneGraphObject().getClass() == sceneGraphObjectClass) { 355 result.add(this); 356 } 357 for (FXOMProperty p : properties.values()) { 358 if (p instanceof FXOMPropertyC) { 359 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 360 v.collectObjectWithSceneGraphObjectClass(sceneGraphObjectClass, result); 361 } 362 } 363 } 364 } 365 } 366 367 @Override 368 protected void collectEventHandlers(List<FXOMPropertyT> result) { 369 if (getSceneGraphObject() != null) { 370 for (FXOMProperty p : properties.values()) { 371 if (p instanceof FXOMPropertyT) { 372 final FXOMPropertyT pt = (FXOMPropertyT) p; 373 if (pt.getName().getName().startsWith("on") && pt.getValue().startsWith("#")) { 374 result.add(pt); 375 } 376 } 377 } 378 for (FXOMProperty p : properties.values()) { 379 if (p instanceof FXOMPropertyC) { 380 for (FXOMObject v : ((FXOMPropertyC)p).getValues()) { 381 v.collectEventHandlers(result); 382 } 383 } 384 } 385 } 386 } 387 388 /* 389 * FXOMNode 390 */ 391 392 @Override 393 protected void changeFxomDocument(FXOMDocument destination) { 394 395 super.changeFxomDocument(destination); 396 for (FXOMProperty p : properties.values()) { 397 p.changeFxomDocument(destination); 398 } 399 } 400 401 @Override 402 public void documentLocationWillChange(URL newLocation) { 403 for (FXOMProperty p : properties.values()) { 404 p.documentLocationWillChange(newLocation); 405 } 406 } 407 408 409 /* 410 * Package 411 */ 412 413 /* For FXOMProperty.addToParentInstance() private use only */ 414 void addProperty(FXOMProperty property) { 415 assert property.getParentInstance() == this; 416 assert properties.get(property.getName()) == null; 417 properties.put(property.getName(), property); 418 } 419 420 /* For FXOMProperty.removeFromParentInstance() private use only */ 421 void removeProperty(FXOMProperty property) { 422 assert property.getParentInstance() == null; 423 assert properties.get(property.getName()) == property; 424 properties.remove(property.getName()); 425 426 } 427 428 429 /* 430 * Private 431 */ 432 433 private void resetRootProperties() { 434 if (isFxRoot()) { 435 toggleFxRoot(); 436 } 437 } 438 }