001/*
002  GRANITE DATA SERVICES
003  Copyright (C) 2011 GRANITE DATA SERVICES S.A.S.
004
005  This file is part of Granite Data Services.
006
007  Granite Data Services is free software; you can redistribute it and/or modify
008  it under the terms of the GNU Library General Public License as published by
009  the Free Software Foundation; either version 2 of the License, or (at your
010  option) any later version.
011
012  Granite Data Services is distributed in the hope that it will be useful, but
013  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
015  for more details.
016
017  You should have received a copy of the GNU Library General Public License
018  along with this library; if not, see <http://www.gnu.org/licenses/>.
019*/
020
021package org.granite.generator.javafx;
022
023import java.util.HashSet;
024import java.util.List;
025import java.util.Set;
026
027import org.granite.generator.as3.ClientType;
028import org.granite.generator.as3.PackageTranslator;
029
030/**
031 * @author Franck WOLFF
032 */
033public class JavaFXType implements ClientType {
034
035    ///////////////////////////////////////////////////////////////////////////
036    // Fields.
037
038    public static final JavaFXType BOOLEAN = new JavaFXType(null, "boolean", false);
039    public static final JavaFXType INT = new JavaFXType(null, "int", Integer.valueOf(0));
040    public static final JavaFXType LONG = new JavaFXType(null, "long", Long.valueOf(0));
041    public static final JavaFXType FLOAT = new JavaFXType(null, "float", Float.valueOf(0.0f));
042    public static final JavaFXType DOUBLE = new JavaFXType(null, "double", Double.valueOf(0.0));
043    public static final JavaFXType STRING = new JavaFXType(null, "String", null);
044    
045    public static final JavaFXType PAGE_INFO = new JavaFXType("org.granite.tide.data.model", "PageInfo", null);
046    public static final JavaFXType SORT_INFO = new JavaFXType("org.granite.tide.data.model", "SortInfo", null);
047    
048    public static final JavaFXType BOOLEAN_PROPERTY = new JavaFXType(null, "boolean", "javafx.beans.property.BooleanProperty", "javafx.beans.property.SimpleBooleanProperty", Boolean.FALSE);
049    public static final JavaFXType INT_PROPERTY = new JavaFXType(null, "int", "javafx.beans.property.IntegerProperty", "javafx.beans.property.SimpleIntegerProperty", Integer.valueOf(0));
050    public static final JavaFXType LONG_PROPERTY = new JavaFXType(null, "long", "javafx.beans.property.LongProperty", "javafx.beans.property.SimpleLongProperty", Long.valueOf(0));
051    public static final JavaFXType FLOAT_PROPERTY = new JavaFXType(null, "float", "javafx.beans.property.FloatProperty", "javafx.beans.property.SimpleFloatProperty", Float.valueOf(0.0f));
052    public static final JavaFXType DOUBLE_PROPERTY = new JavaFXType(null, "double", "javafx.beans.property.DoubleProperty", "javafx.beans.property.SimpleDoubleProperty", Double.valueOf(0.0));
053    public static final JavaFXType STRING_PROPERTY = new JavaFXType(null, "String", "javafx.beans.property.StringProperty", "javafx.beans.property.SimpleStringProperty", null);
054    
055    public static final JavaFXType BOOLEAN_READONLY_PROPERTY = new JavaFXType(null, "boolean", "javafx.beans.property.ReadOnlyBooleanProperty", "javafx.beans.property.ReadOnlyBooleanWrapper", null, Boolean.FALSE, true);
056    public static final JavaFXType INT_READONLY_PROPERTY = new JavaFXType(null, "int", "javafx.beans.property.ReadOnlyIntegerProperty", "javafx.beans.property.ReadOnlyIntegerWrapper", null, Integer.valueOf(0), true);
057    public static final JavaFXType LONG_READONLY_PROPERTY = new JavaFXType(null, "long", "javafx.beans.property.ReadOnlyLongProperty", "javafx.beans.property.ReadOnlyLongWrapper", null, Long.valueOf(0), true);
058    public static final JavaFXType FLOAT_READONLY_PROPERTY = new JavaFXType(null, "float", "javafx.beans.property.ReadOnlyFloatProperty", "javafx.beans.property.ReadOnlyFloatWrapper", null, Float.valueOf(0.0f), true);
059    public static final JavaFXType DOUBLE_READONLY_PROPERTY = new JavaFXType(null, "double", "javafx.beans.property.ReadOnlyDoubleProperty", "javafx.beans.property.ReadOnlyDoubleWrapper", null, Double.valueOf(0.0), true);
060    public static final JavaFXType STRING_READONLY_PROPERTY = new JavaFXType(null, "String", "javafx.beans.property.ReadOnlyStringProperty", "javafx.beans.property.ReadOnlyStringWrapper", null, null, true);
061    
062    private final String packageName;
063    private final String name;
064    private final String qualifiedName;
065    private final String propertyTypeName;
066    private final String propertyImplTypeName;
067    private final String propertyFactoryName;
068    private final Object nullValue;
069    private final boolean readOnly;
070    private final Set<String> imports = new HashSet<String>(); 
071
072    ///////////////////////////////////////////////////////////////////////////
073    // Constructors.
074
075    public JavaFXType(String packageName, String simpleName) {
076        this(packageName, simpleName, null);
077    }
078    public JavaFXType(String packageName, String name, Object nullValue) {
079        this(packageName, name, null, null, nullValue);
080    }
081    public JavaFXType(String packageName, String name, String propertyTypeName, String propertyImplTypeName, Object nullValue) {
082        this(packageName, name, propertyTypeName, propertyImplTypeName, null, nullValue, false);
083    }
084    public JavaFXType(String packageName, String name, String propertyTypeName, String propertyImplTypeName, String propertyFactoryName, Object nullValue, boolean readOnly) {
085        this.packageName = (packageName != null ? packageName : "");
086        this.name = name;
087        this.qualifiedName = (hasPackage() ? (packageName + '.' + name) : name);
088        this.nullValue = nullValue;
089        this.propertyTypeName = propertyTypeName;
090        this.propertyImplTypeName = propertyImplTypeName;
091        this.propertyFactoryName = propertyFactoryName;
092        this.readOnly = readOnly;
093        if (hasPackage())
094                imports.add(ungenerify(qualifiedName));
095        if (propertyTypeName != null)
096                imports.add(ungenerify(propertyTypeName));
097        if (propertyImplTypeName != null)
098                imports.add(ungenerify(propertyImplTypeName));
099    }
100
101    ///////////////////////////////////////////////////////////////////////////
102    // Properties.
103
104    @Override
105        public boolean hasPackage() {
106        return packageName.length() > 0;
107    }
108
109    @Override
110        public String getPackageName() {
111        return packageName;
112    }
113
114    @Override
115        public String getName() {
116        return name;
117    }
118
119    @Override
120        public String getQualifiedName() {
121        return qualifiedName;
122    }
123    
124    public String getPropertyTypeName() {
125        return propertyTypeName;
126    }
127    
128    public String getSimplePropertyTypeName() {
129        return propertyTypeName != null && propertyTypeName.indexOf(".") >= 0 
130                ? propertyTypeName.substring(propertyTypeName.lastIndexOf(".")+1) : propertyTypeName;
131    }
132    
133    public String getPropertyImplTypeName() {
134        return propertyImplTypeName;
135    }
136    
137    public String getSimplePropertyImplTypeName() {
138        return propertyImplTypeName != null && propertyImplTypeName.indexOf(".") >= 0 
139                ? propertyImplTypeName.substring(propertyImplTypeName.lastIndexOf(".")+1) : propertyImplTypeName;
140    }
141    
142    public String getPropertyFactoryName() {
143        return propertyFactoryName != null ? propertyFactoryName : "new " + getSimplePropertyImplTypeName();
144    }
145
146    @Override
147        public Object getNullValue() {
148        return nullValue;
149    }
150    
151    public boolean isReadOnly() {
152        return readOnly;
153    }
154
155    public boolean isNumber() {
156        return false;
157    }
158    
159    ///////////////////////////////////////////////////////////////////////////
160    // Methods
161    
162    @Override
163        public Set<String> getImports() {
164        return imports;
165    }
166    
167    @Override
168        public void addImports(Set<String> classNames) {
169        for (String className : classNames) {
170                if (className.indexOf(".") < 0 || className.startsWith("java.lang"))
171                        continue;
172                imports.add(ungenerify(className));
173        }
174    }
175    
176    private String ungenerify(String className) {
177                if (className.indexOf("<") >= 0)
178                        return className.substring(0, className.indexOf("<"));
179                return className;
180    }
181    
182    @Override
183        public JavaFXType toArrayType() {
184        return new JavaFXType(packageName, name + "[]", null);
185    }
186    
187    @Override
188        public JavaFXType translatePackage(PackageTranslator translator) {
189        return new JavaFXType(translator.translate(packageName), getName(), getPropertyTypeName(), getPropertyImplTypeName(), getPropertyFactoryName(), getNullValue(), isReadOnly());
190    }
191    
192    @Override
193    public JavaFXType translatePackages(List<PackageTranslator> translators) {
194        boolean translate = false;
195        
196        PackageTranslator translator = PackageTranslator.forPackage(translators, packageName);
197        String translatedPackageName = packageName;
198        if (translator != null) {
199                translate = true;
200                translatedPackageName = translator.translate(packageName);
201        }
202        
203        Set<String> translatedImports = new HashSet<String>();
204        for (String imp : imports) {
205                translator = PackageTranslator.forPackage(translators, imp);
206                if (translator != null) {
207                        translate = true;
208                        translatedImports.add(translator.translate(imp));
209                }
210                else
211                        translatedImports.add(imp);
212        }
213        
214        if (!translate)
215                return this;
216        
217        JavaFXType translatedType = new JavaFXType(translatedPackageName, getName(), getPropertyTypeName(), getPropertyImplTypeName(), getPropertyFactoryName(), getNullValue(), isReadOnly());
218                translatedType.addImports(translatedImports);
219        return translatedType;
220    }
221
222    ///////////////////////////////////////////////////////////////////////////
223    // Utilities.
224
225    @Override
226    public int hashCode() {
227        return qualifiedName.hashCode();
228    }
229
230    @Override
231    public boolean equals(Object obj) {
232        if (obj == this)
233            return true;
234        if (!(obj instanceof JavaFXType))
235            return false;
236        return qualifiedName.equals(((JavaFXType)obj).qualifiedName);
237    }
238
239    @Override
240    public String toString() {
241        return qualifiedName;
242    }
243}