/**
* This file is part of ObjectFabric (http://objectfabric.org).
*
* ObjectFabric is licensed under the Apache License, Version 2.0, the terms
* of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
*
* Copyright ObjectFabric Inc.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.objectfabric;
import javax.xml.bind.annotation.XmlType;
@XmlType(name = "Type")
public class TypeDef {
static {
JVMPlatform.loadClass();
}
// TODO merge with TType
static final String ENUM_VALUES_ARRAY = "_ENUM_VALUES_ARRAY";
private List<TypeDef> _genericsParameters = new List<TypeDef>();
private Immutable _immutable;
private ClassDef _generated;
private java.lang.Class _otherClass;
private String _custom;
private Immutable _customUnderlyingImmutable;
public TypeDef() {
}
public TypeDef(Immutable immutable) {
_immutable = immutable;
}
public TypeDef(ClassDef generated) {
_generated = generated;
}
public TypeDef(java.lang.Class other) {
Immutable immutable = Immutable.parse(Platform.get().simpleName(other));
if (immutable != null)
_immutable = immutable;
else
_otherClass = other;
}
static TypeDef parse(String text, ObjectModelDef model) {
if (text == null)
throw new IllegalArgumentException("Type is null.");
TypeDef result = new TypeDef();
List<String> args = new List<String>();
String name = text;
StringBuilder sb = new StringBuilder();
int parenthesisLevel = 0;
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
switch (c) {
case '(':
if (parenthesisLevel == 0) {
name = sb.toString().trim();
sb.setLength(0);
} else
sb.append(c);
parenthesisLevel++;
break;
case ')':
if (parenthesisLevel == 1) {
args.add(sb.toString().trim());
sb.setLength(0);
} else
sb.append(c);
parenthesisLevel--;
break;
case ',':
if (parenthesisLevel == 1) {
args.add(sb.toString().trim());
sb.setLength(0);
}
break;
default:
sb.append(c);
break;
}
}
if ("Custom".equals(name)) {
if (args.size() != 2)
throw new IllegalArgumentException(text + ": Custom type requires 2 parameters, e.g. Custom(MyEnum, int).");
result._custom = args.get(0);
result._customUnderlyingImmutable = Immutable.parse(args.get(1));
if (result._customUnderlyingImmutable == null)
throw new IllegalArgumentException(text + ": Second parameter of a Custom type must be a primitive.");
} else {
result._immutable = Immutable.parse(name);
if (result._immutable == null) {
if ("object".equals(name) || "Object".equals(name) || "Object".equals(name) || "java.lang.Object".equals(name))
result._otherClass = Platform.get().objectClass();
else if ("void".equals(name) || "Void".equals(name) || "Void".equals(name) || "java.lang.Void".equals(name))
result._otherClass = Platform.get().voidClass();
else {
result._generated = findGeneratedClass(name, model);
if (result._generated == null) {
result._otherClass = findOtherClass(name);
if (result._otherClass == null)
throw new IllegalArgumentException(name);
}
}
}
for (int i = 0; i < args.size(); i++)
result._genericsParameters.add(parse(args.get(i), model));
}
return result;
}
private static java.lang.Class findOtherClass(String name) {
BuiltInClass builtIn = BuiltInClass.parse(name);
java.lang.Class c = null;
if (builtIn != null)
c = Platform.get().defaultObjectModel().getClass(builtIn.id(), null);
if (c != null)
return c;
c = PlatformGenerator.forName(name);
if (c == null)
c = PlatformGenerator.forName("org.objectfabric." + name);
if (c != null)
if (!(PlatformGenerator.isTObject(c)) && !PlatformGenerator.isJavaEnum(c))
throw new IllegalArgumentException("Class \"" + c + "\" is not supported.");
return c;
}
static ClassDef findGeneratedClass(String name, ObjectModelDef model) {
for (int i = 0; i < model.allClasses().size(); i++) {
ClassDef classDef = model.allClasses().get(i);
if (classDef.fullName().equals(name) || classDef.Name.equals(name))
return classDef;
}
return null;
}
public void addGenericsParameter(java.lang.Class c) {
addGenericsParameter(new TypeDef(c));
}
public void addGenericsParameter(ClassDef classDef) {
addGenericsParameter(new TypeDef(classDef));
}
public void addGenericsParameter(TypeDef type) {
if (_genericsParameters == null)
_genericsParameters = new List<TypeDef>();
_genericsParameters.add(type);
}
String fullName(Target target) {
return fullName(target, false);
}
String fullName(Target target, boolean generics) {
return getFullName(target, generics, false);
}
String getFullName(Target target, boolean generics, boolean useParenthesis) {
String s = className(target);
if (target == Target.CSHARP || generics) {
if (_genericsParameters != null && _genericsParameters.size() > 0) {
String params = "";
for (int i = 0; i < _genericsParameters.size(); i++) {
if (params.length() != 0)
params += ", ";
params += _genericsParameters.get(i).getFullName(target, generics, useParenthesis);
}
if (useParenthesis)
s += "(" + params + ")";
else
s += "<" + params + ">";
}
}
return s;
}
String className(Target target) {
if (_immutable != null)
return target == Target.CSHARP ? _immutable.csharp() : _immutable.java();
if (_generated != null)
return _generated.fullName();
if (_otherClass != null) {
boolean ok = PlatformGenerator.isTObject(_otherClass);
if (_otherClass == Platform.get().voidClass())
ok = true;
if (_otherClass == Platform.get().objectClass())
ok = true;
if (PlatformGenerator.isJavaEnum(_otherClass))
ok = true;
if (!ok)
throw new IllegalArgumentException("Class \"" + Platform.get().name(_otherClass) + "\" is not supported.");
return Platform.get().name(_otherClass).replace('$', '.');
}
if (_custom == null)
throw new RuntimeException("Type value is missing.");
return _custom;
}
String fullNameWithGenericsAndBoxPrimitives(Target target) {
String result;
if (target == Target.JAVA && immutable() != null && immutable().isPrimitive() && !immutable().isBoxed())
result = immutable().boxed().java();
else
result = fullName(target, true);
return result;
}
String cast(GeneratorBase generator) {
String type = castType(generator);
return type == null ? "" : "(" + type + ") ";
}
private String castType(GeneratorBase generator) {
if (_otherClass == Platform.get().objectClass())
return null;
if (generator.isJava())
if (_immutable != null && _immutable.isPrimitive() && !_immutable.isBoxed())
return _immutable.boxed().java();
return fullName(generator.target(), false);
}
String getTTypeString(Target target) {
if (_immutable != null)
return "org.objectfabric.Immutable." + Utils.getNameAsConstant(_immutable.toString()) + ".type()";
if (_generated != null)
return _generated.fullName() + ".TYPE";
if (_otherClass != null) {
String name = Platform.get().name(_otherClass).replace('$', '.');
if (_otherClass == Platform.get().voidClass())
return "org.objectfabric.TType.VOID";
if (PlatformGenerator.isTObject(_otherClass))
return name + ".TYPE";
if (_otherClass == Platform.get().objectClass())
return "org.objectfabric.TType.OBJECT";
String type = target == Target.JAVA ? name + ".class" : "typeof(" + name + ")";
return "new org.objectfabric.TType(" + type + ")";
}
if (_custom == null)
throw new RuntimeException("Type value is missing.");
String type = target == Target.JAVA ? _custom + ".class" : "typeof(" + _custom + ")";
return "new org.objectfabric.TType(" + type + ")";
}
String defaultString() {
return immutable() != null ? immutable().defaultString() : "null";
}
Immutable immutable() {
return _immutable;
}
java.lang.Class otherClass() {
return _otherClass;
}
String custom() {
return _custom;
}
Immutable customUnderlyingImmutable() {
return _customUnderlyingImmutable;
}
boolean isTObject() {
return _generated != null || (_otherClass != null && PlatformGenerator.isTObject(_otherClass));
}
boolean canBeTObject() {
if (isTObject())
return true;
if (_otherClass != null)
if (_otherClass == Platform.get().objectClass() || PlatformGenerator.isInterface(_otherClass))
return true;
return false;
}
boolean isJavaEnum() {
return _otherClass != null && PlatformGenerator.isJavaEnum(_otherClass);
}
ClassDef firstGeneratedClassAmongstThisAndParents(ObjectModelDef model) {
if (_generated != null)
return _generated;
if (_otherClass != null) {
java.lang.Class parent = Platform.get().superclass(_otherClass);
while (parent != Platform.get().tObjectClass()) {
ClassDef def = TypeDef.findGeneratedClass(Platform.get().name(parent), model);
if (def != null)
return def;
parent = Platform.get().superclass(parent);
}
}
return null;
}
boolean isTGeneratedFields(ObjectModelDef model) {
if (_generated != null && _generated.parent() != null)
return _generated.parent().isTGeneratedFields(model);
if (_otherClass != null) {
java.lang.Class parent = Platform.get().superclass(_otherClass);
while (parent != Platform.get().tObjectClass()) {
if (parent == Platform.get().tGeneratedClass())
return true;
parent = Platform.get().superclass(parent);
}
return false;
}
return true;
}
//
boolean fixedLength() {
if (immutable() != null && immutable().fixedLength() || isJavaEnum())
return true;
return false;
}
}