All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jfxcore.compiler.util.PropertyInfo Maven / Gradle / Ivy

// Copyright (c) 2022, 2023, JFXcore. All rights reserved.
// Use of this source code is governed by the BSD-3-Clause license that can be found in the LICENSE file.

package org.jfxcore.compiler.util;

import javafx.beans.property.Property;
import javafx.beans.value.ObservableValue;
import javafx.beans.value.WritableValue;
import javassist.CtMethod;
import javassist.NotFoundException;
import org.jetbrains.annotations.Nullable;
import org.jfxcore.compiler.ast.BindingMode;
import java.util.Objects;

import static org.jfxcore.compiler.util.Classes.*;

/**
 * The compiler will recognize a JavaFX property if it is implemented by a well-defined set of methods.
 *
 * 

Read-only properties: *

    *
  1. T getValue() *
  2. ObservableValue<T> valueProperty() *
  3. ObservableValue<T> valueProperty(), T getValue() *
  4. static T getValue(Node) *
  5. static ObservableValue<T> valueProperty(Node) *
  6. static ObservableValue<T> valueProperty(Node), static T getValue(Node) *
* *

Writable properties: *

    *
  1. T getValue(), void setValue(T) *
  2. Property<T> valueProperty() *
  3. Property<T> valueProperty(), T getValue() *
  4. Property<T> valueProperty(), T getValue(), void setValue(T) *
  5. static T getValue(Node), static void setValue(Node, T) *
  6. static Property<T> valueProperty(Node) *
  7. static Property<T> valueProperty(Node), T getValue(Node) *
  8. static Property<T> valueProperty(Node), T getValue(Node), void setValue(Node, T) *
* *

If the property uses a primitive wrapper like ObservableBooleanValue, the optional getter and setter * methods will only be recognized if they return or set a primitive value (i.e. not a boxed value). */ public class PropertyInfo { private final String name; private final CtMethod propertyGetter; private final CtMethod getter; private final CtMethod setter; private final TypeInstance typeInstance; private final TypeInstance observableType; private final TypeInstance declaringType; private final boolean isStatic; private final boolean observable; private final boolean readonly; private final boolean bindable; PropertyInfo( String name, CtMethod propertyGetter, CtMethod getter, CtMethod setter, TypeInstance type, TypeInstance observableType, TypeInstance declaringType, boolean isStatic) throws NotFoundException { this.name = name; this.propertyGetter = propertyGetter; this.getter = getter; this.setter = setter; this.typeInstance = type; this.observableType = observableType; this.declaringType = declaringType; this.isStatic = isStatic; this.observable = propertyGetter != null; this.readonly = setter == null && (propertyGetter == null || !propertyGetter.getReturnType().subtypeOf(Classes.WritableValueType())); this.bindable = propertyGetter != null && propertyGetter.getReturnType().subtypeOf(Classes.PropertyType()); } public String getName() { return name; } /** * Returns the property getter method. * This may be {@code null} if the property doesn't have an {@link ObservableValue}-based property getter. */ public @Nullable CtMethod getPropertyGetter() { return propertyGetter; } /** * Returns the getter method. * This may be {@code null} if the property doesn't have a getter method. * If there is no getter method, the property must have an {@link ObservableValue}-based property getter. */ public @Nullable CtMethod getGetter() { return getter; } /** * Returns the setter method. This may be {@code null} if the property doesn't have a setter method. */ public @Nullable CtMethod getSetter() { return setter; } /** * Returns the property getter method. If there is no property getter method, returns the getter method. */ public CtMethod getPropertyGetterOrGetter() { return propertyGetter != null ? propertyGetter : getter; } /** * Returns the getter method. If there is no getter method, returns the property getter method. */ public CtMethod getGetterOrPropertyGetter() { return getter != null ? getter : propertyGetter; } /** * Returns the setter method. If there is no setter method, returns the property getter method. */ public CtMethod getSetterOrPropertyGetter() { return setter != null ? setter : propertyGetter; } /** * Returns the type of the property. * For properties that use primitive wrappers like ObservableBooleanValue, returns the primitive type. */ public TypeInstance getType() { return typeInstance; } /** * Returns the observable type of the property. */ public TypeInstance getObservableType() { return observableType; } /** * Returns the declaring type of the property. */ public TypeInstance getDeclaringType() { return declaringType; } /** * Returns whether the property is a static property. */ public boolean isStatic() { return isStatic; } /** * Returns whether the property has an {@link ObservableValue}-based property getter. */ public boolean isObservable() { return observable; } /** * Returns whether the property has no setter and no {@link WritableValue}-based property getter. */ public boolean isReadOnly() { return readonly; } /** * Returns whether the property has a {@link Property}-based property getter, which can be used to set up bindings. */ public boolean isBindable() { return bindable; } /** * Returns whether the property is content-bindable using one of * {@link java.util.Collection#addAll}, * {@link java.util.Map#putAll}, * {@link javafx.beans.binding.Bindings#bindContent}, or * {@link javafx.beans.binding.Bindings#bindContentBidirectional}. */ public boolean isContentBindable(BindingMode forMode) { switch (forMode) { case CONTENT: return typeInstance.subtypeOf(CollectionType()) || typeInstance.subtypeOf(MapType()); case UNIDIRECTIONAL_CONTENT: return (observableType == null || observableType.subtypeOf(ListType())) && typeInstance.subtypeOf(ListType()) || (observableType == null || observableType.subtypeOf(SetType())) && typeInstance.subtypeOf(SetType()) || (observableType == null || observableType.subtypeOf(MapType())) && typeInstance.subtypeOf(MapType()); case BIDIRECTIONAL_CONTENT: return (observableType == null || observableType.subtypeOf(ObservableListType())) && typeInstance.subtypeOf(ObservableListType()) || (observableType == null || observableType.subtypeOf(ObservableSetType())) && typeInstance.subtypeOf(ObservableSetType()) || (observableType == null || observableType.subtypeOf(ObservableMapType())) && typeInstance.subtypeOf(ObservableMapType()); default: return false; } } @Override public String toString() { return declaringType.getSimpleName() + "." + name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PropertyInfo that = (PropertyInfo)o; return name.equals(that.name) && declaringType.equals(that.declaringType); } @Override public int hashCode() { return Objects.hash(name, declaringType); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy