diff --git a/app/src/main/java/com/ebr163/android/attributesdispatcher/MyCustomView.java b/app/src/main/java/com/ebr163/android/attributesdispatcher/MyCustomView.java
new file mode 100644
index 0000000..ce233f6
--- /dev/null
+++ b/app/src/main/java/com/ebr163/android/attributesdispatcher/MyCustomView.java
@@ -0,0 +1,42 @@
+package com.ebr163.android.attributesdispatcher;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+import com.ebr163.attributesdispatcher.Attribute;
+import com.ebr163.attributesdispatcher.CustomView;
+import com.ebr163.attributesdispatcher.attr.ColorAttr;
+import com.ebr163.attributesdispatcher.attr.StringAttr;
+
+/**
+ * Created by mac1 on 24.11.16.
+ */
+
+@CustomView
+public class MyCustomView extends EditText {
+
+ @ColorAttr("custom_color")
+ protected int color;
+ @StringAttr("custom_text")
+ protected String text;
+
+ public MyCustomView(Context context) {
+ super(context);
+ }
+
+ public MyCustomView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ MyCustomViewAttribute.init(this, attrs);
+ }
+
+ public MyCustomView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ MyCustomViewAttribute.init(this, attrs);
+ }
+
+ @Attribute
+ protected void setCustomAttr(@ColorAttr("custom_color") int color) {
+ this.setTextColor(color);
+ }
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index f1702f2..0c5d6d9 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,18 +1,26 @@
-
+ android:paddingTop="@dimen/activity_vertical_margin">
+
+
-
-
+ app:custom_text="Text2"
+ app:custom_color="@android:color/holo_red_dark" />
+
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
new file mode 100644
index 0000000..7ac7c2d
--- /dev/null
+++ b/app/src/main/res/values/attrs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/AttributesProcessor.java b/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/AttributesProcessor.java
index c427bb5..3c50b5e 100644
--- a/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/AttributesProcessor.java
+++ b/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/AttributesProcessor.java
@@ -1,14 +1,220 @@
package com.ebr163.attributesdispatcher.internal;
+import com.ebr163.attributesdispatcher.Attribute;
+import com.ebr163.attributesdispatcher.CustomView;
+import com.ebr163.attributesdispatcher.attr.BooleanAttr;
+import com.ebr163.attributesdispatcher.attr.ColorAttr;
+import com.ebr163.attributesdispatcher.attr.DimenAttr;
+import com.ebr163.attributesdispatcher.attr.FloatAttr;
+import com.ebr163.attributesdispatcher.attr.IntAttr;
+import com.ebr163.attributesdispatcher.attr.ReferenceAttr;
+import com.ebr163.attributesdispatcher.attr.StringAttr;
+import com.squareup.javapoet.ClassName;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.MethodSpec;
+import com.squareup.javapoet.ParameterSpec;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeSpec;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+@SupportedAnnotationTypes("com.ebr163.attributesdispatcher.CustomView")
public class AttributesProcessor extends AbstractProcessor {
+ private static final String METHOD_PREFIX = "Generation";
+
+ private ClassName AttributeSet = ClassName.get("android.util", "AttributeSet");
+ private ClassName TypedArray = ClassName.get("android.content.res", "TypedArray");
+ private ClassName Build = ClassName.get("android.os", "Build");
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+
+ @Override
+ public Set getSupportedAnnotationTypes() {
+ Set set = new HashSet<>();
+ set.add(CustomView.class.getCanonicalName());
+ return Collections.unmodifiableSet(set);
+ }
+
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
- return false;
+ for (Element element : roundEnv.getElementsAnnotatedWith(CustomView.class)) {
+ JavaFile javaFile = createJavaFile(new CustomViewElement((TypeElement) element));
+ try {
+ javaFile.writeTo(processingEnv.getFiler());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return true;
+ }
+
+ private JavaFile createJavaFile(CustomViewElement customViewElement) {
+ return JavaFile.builder(customViewElement.packageName, createTypeSpec(customViewElement))
+ .addFileComment("This file was generated by AttrGenerator. Do not modify!")
+ .build();
+ }
+
+ private TypeSpec createTypeSpec(CustomViewElement customViewElement) {
+ TypeSpec.Builder builder = TypeSpec.classBuilder(customViewElement.generatedClassName)
+ .addModifiers(Modifier.FINAL)
+ .addMethod(createConstructor())
+ .addMethods(createAttrMethods(customViewElement))
+ .addMethod(createInitMethod(customViewElement));
+ return builder.build();
+
+
+ }
+
+ private MethodSpec createConstructor() {
+ return MethodSpec.constructorBuilder()
+ .addModifiers(Modifier.PRIVATE)
+ .build();
+ }
+
+ private MethodSpec createInitMethod(CustomViewElement customViewElement) {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder("init")
+ .addTypeVariables(customViewElement.typeVariables)
+ .addModifiers(Modifier.STATIC)
+ .returns(TypeName.VOID)
+ .addParameter(customViewElement.typeName, "target")
+ .addParameter(ParameterSpec.builder(AttributeSet, "attributeSet").build());
+
+ addAttrGenBodyInit(builder, customViewElement);
+ return builder.build();
+ }
+
+ private List createAttrMethods(CustomViewElement customViewElement) {
+ List methods = new ArrayList<>();
+ for (ExecutableElement method : customViewElement.attrElements) {
+ methods.add(createAttrGenMethod(customViewElement, method));
+ }
+
+ return methods;
+ }
+
+ private void addAttrGenBodyInit(MethodSpec.Builder builder, CustomViewElement customViewElement) {
+ builder.addStatement("$T typedArray = $N.getContext().getTheme().obtainStyledAttributes(\n" +
+ " $N,\n" +
+ " R.styleable.$L,\n" +
+ " 0, 0)", TypedArray, "target", "attributeSet", customViewElement.inputClassName);
+
+ addInitTargetField(builder, customViewElement);
+
+ for (ExecutableElement method : customViewElement.attrElements) {
+ builder.addStatement(method.getSimpleName().toString() + METHOD_PREFIX + "($N, $N)", "target", "typedArray");
+ }
+ builder.addStatement("$N.recycle()", "typedArray");
+ }
+
+ private void addInitTargetField(MethodSpec.Builder builder, CustomViewElement customViewElement) {
+ for (Element field : customViewElement.booleanElements) {
+ String value = field.getAnnotation(BooleanAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getBoolean(R.styleable.$L_$L, false)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.colorElements) {
+ String value = field.getAnnotation(ColorAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getColor(R.styleable.$L_$L, 0)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.dimenElements) {
+ String value = field.getAnnotation(DimenAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getDimension(R.styleable.$L_$L, 0f)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.floatElements) {
+ String value = field.getAnnotation(FloatAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getFloat(R.styleable.$L_$L, 0f)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.integerElements) {
+ String value = field.getAnnotation(IntAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getInt(R.styleable.$L_$L, 0)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.referenceElements) {
+ String value = field.getAnnotation(ReferenceAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getResourceId(R.styleable.$L_$L, -1)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+
+ for (Element field : customViewElement.stringElements) {
+ String value = field.getAnnotation(StringAttr.class).value();
+ builder.addStatement("$N." + field.getSimpleName().toString() + " = $N.getString(R.styleable.$L_$L)", "target", "typedArray", customViewElement.inputClassName, value);
+ }
+ }
+
+ private MethodSpec createAttrGenMethod(CustomViewElement customViewElement, ExecutableElement method) {
+ MethodSpec.Builder builder = MethodSpec.methodBuilder(method.getSimpleName().toString() + METHOD_PREFIX)
+ .addTypeVariables(customViewElement.typeVariables)
+ .addModifiers(Modifier.PRIVATE, Modifier.STATIC)
+ .returns(TypeName.VOID)
+ .addParameter(customViewElement.typeName, "target")
+ .addParameter(ParameterSpec.builder(TypedArray, "typedArray").build());
+
+ addAttrGenBody(builder, method, customViewElement);
+ return builder.build();
+ }
+
+ private void addAttrGenBody(MethodSpec.Builder builder, ExecutableElement method, CustomViewElement customViewElement) {
+ int maxSdkVersion = method.getAnnotation(Attribute.class).maxSdkVersion();
+ builder.beginControlFlow("if ($T.VERSION.SDK_INT < $L)", Build, maxSdkVersion);
+ builder.addStatement("return");
+ builder.endControlFlow();
+
+ String params = "";
+ for (int i = 0; i < method.getParameters().size(); i++) {
+ TypeName type = TypeName.get(method.getParameters().get(i).asType());
+ String name = method.getParameters().get(i).getSimpleName().toString();
+
+ Element parameter = method.getParameters().get(i);
+ DeclaredType annotation = parameter.getAnnotationMirrors().get(0).getAnnotationType();
+
+ if (annotation.toString().equals(IntAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(IntAttr.class).value();
+ builder.addStatement("$T $N = $N.getInt(R.styleable.$L_$L, 0)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(BooleanAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(BooleanAttr.class).value();
+ builder.addStatement("$T $N = $N.getBoolean(R.styleable.$L_$L, false)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(ColorAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(ColorAttr.class).value();
+ builder.addStatement("$T $N = $N.getColor(R.styleable.$L_$L, 0)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(DimenAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(DimenAttr.class).value();
+ builder.addStatement("$T $N = $N.getDimension(R.styleable.$L_$L, 0f)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(FloatAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(FloatAttr.class).value();
+ builder.addStatement("$T $N = $N.getFloat(R.styleable.$L_$L, 0f)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(StringAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(StringAttr.class).value();
+ builder.addStatement("$T $N = $N.getString(R.styleable.$L_$L)", type, name, "typedArray", customViewElement.inputClassName, key);
+ } else if (annotation.toString().equals(ReferenceAttr.class.getCanonicalName())) {
+ String key = parameter.getAnnotation(ReferenceAttr.class).value();
+ builder.addStatement("$T $N = $N.getResourceId(R.styleable.$L_$L, -1)", type, name, "typedArray", customViewElement.inputClassName, key);
+ }
+ if (i == 0) {
+ params += name;
+ } else {
+ params += ", " + name;
+ }
+ }
+ builder.addStatement("$N." + method.getSimpleName().toString() + "($L)", "target", params);
}
}
diff --git a/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/CustomViewElement.java b/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/CustomViewElement.java
new file mode 100644
index 0000000..ad320b0
--- /dev/null
+++ b/compiler/src/main/java/com/ebr163/attributesdispatcher/internal/CustomViewElement.java
@@ -0,0 +1,94 @@
+package com.ebr163.attributesdispatcher.internal;
+
+import com.ebr163.attributesdispatcher.Attribute;
+import com.ebr163.attributesdispatcher.attr.BooleanAttr;
+import com.ebr163.attributesdispatcher.attr.ColorAttr;
+import com.ebr163.attributesdispatcher.attr.DimenAttr;
+import com.ebr163.attributesdispatcher.attr.FloatAttr;
+import com.ebr163.attributesdispatcher.attr.IntAttr;
+import com.ebr163.attributesdispatcher.attr.ReferenceAttr;
+import com.ebr163.attributesdispatcher.attr.StringAttr;
+import com.squareup.javapoet.TypeName;
+import com.squareup.javapoet.TypeVariableName;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+
+/**
+ * Created by mac1 on 23.11.16.
+ */
+
+class CustomViewElement {
+
+ private static final String GEN_CLASS_SUFFIX = "Attribute";
+
+ final TypeName typeName;
+ final List typeVariables;
+ final String packageName;
+ final String inputClassName;
+ final String generatedClassName;
+ final List attrElements;
+ final TypeElement typeElement;
+ final List booleanElements;
+ final List colorElements;
+ final List dimenElements;
+ final List floatElements;
+ final List integerElements;
+ final List referenceElements;
+ final List stringElements;
+
+ CustomViewElement(TypeElement typeElement) {
+ this.typeElement = typeElement;
+ typeName = TypeName.get(typeElement.asType());
+ typeVariables = getTypeVariables(typeElement);
+ packageName = getPackageName(typeElement);
+ inputClassName = typeElement.getSimpleName().toString();
+ generatedClassName = inputClassName + GEN_CLASS_SUFFIX;
+ attrElements = getChildElementsAnnotatedWith(typeElement, Attribute.class);
+ booleanElements = getChildFieldsAnnotatedWith(typeElement, BooleanAttr.class);
+ colorElements = getChildFieldsAnnotatedWith(typeElement, ColorAttr.class);
+ dimenElements = getChildFieldsAnnotatedWith(typeElement, DimenAttr.class);
+ floatElements = getChildFieldsAnnotatedWith(typeElement, FloatAttr.class);
+ integerElements = getChildFieldsAnnotatedWith(typeElement, IntAttr.class);
+ referenceElements = getChildFieldsAnnotatedWith(typeElement, ReferenceAttr.class);
+ stringElements = getChildFieldsAnnotatedWith(typeElement, StringAttr.class);
+ }
+
+ private List getTypeVariables(TypeElement typeElement) {
+ List names = new ArrayList<>();
+ for (TypeParameterElement e : typeElement.getTypeParameters()) {
+ names.add(TypeVariableName.get(e));
+ }
+ return names;
+ }
+
+ private String getPackageName(TypeElement typeElement) {
+ String packageName = typeElement.getQualifiedName().toString();
+ return packageName.substring(0, packageName.lastIndexOf("."));
+ }
+
+ private List getChildElementsAnnotatedWith(TypeElement typeElement, Class clazz) {
+ List childElements = new ArrayList<>();
+ for (Element e : typeElement.getEnclosedElements()) {
+ if (e.getAnnotation(clazz) != null) {
+ childElements.add((ExecutableElement) e);
+ }
+ }
+ return childElements;
+ }
+
+ private List getChildFieldsAnnotatedWith(TypeElement typeElement, Class clazz) {
+ List childElements = new ArrayList<>();
+ for (Element e : typeElement.getEnclosedElements()) {
+ if (e.getAnnotation(clazz) != null) {
+ childElements.add(e);
+ }
+ }
+ return childElements;
+ }
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/Attribute.java b/library/src/main/java/com/ebr163/attributesdispatcher/Attribute.java
new file mode 100644
index 0000000..96fe7ad
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/Attribute.java
@@ -0,0 +1,15 @@
+package com.ebr163.attributesdispatcher;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by mac1 on 22.11.16.
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.CLASS)
+public @interface Attribute {
+ int maxSdkVersion() default 0;
+}
\ No newline at end of file
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/CustomView.java b/library/src/main/java/com/ebr163/attributesdispatcher/CustomView.java
new file mode 100644
index 0000000..4a1a133
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/CustomView.java
@@ -0,0 +1,14 @@
+package com.ebr163.attributesdispatcher;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Created by mac1 on 22.11.16.
+ */
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.CLASS)
+public @interface CustomView {
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/MyClass.java b/library/src/main/java/com/ebr163/attributesdispatcher/MyClass.java
deleted file mode 100644
index 8985f2e..0000000
--- a/library/src/main/java/com/ebr163/attributesdispatcher/MyClass.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.ebr163.attributesdispatcher;
-
-public class MyClass {
-}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/BooleanAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/BooleanAttr.java
new file mode 100644
index 0000000..1b3570e
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/BooleanAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface BooleanAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/ColorAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/ColorAttr.java
new file mode 100644
index 0000000..3dc9c14
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/ColorAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface ColorAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/DimenAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/DimenAttr.java
new file mode 100644
index 0000000..8ade2b9
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/DimenAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface DimenAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/FloatAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/FloatAttr.java
new file mode 100644
index 0000000..06a9b11
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/FloatAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface FloatAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/IntAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/IntAttr.java
new file mode 100644
index 0000000..c668f66
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/IntAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface IntAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/ReferenceAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/ReferenceAttr.java
new file mode 100644
index 0000000..1dca771
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/ReferenceAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface ReferenceAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}
diff --git a/library/src/main/java/com/ebr163/attributesdispatcher/attr/StringAttr.java b/library/src/main/java/com/ebr163/attributesdispatcher/attr/StringAttr.java
new file mode 100644
index 0000000..c57f8c2
--- /dev/null
+++ b/library/src/main/java/com/ebr163/attributesdispatcher/attr/StringAttr.java
@@ -0,0 +1,11 @@
+package com.ebr163.attributesdispatcher.attr;
+
+/**
+ * Created by mac1 on 29.11.16.
+ */
+
+public @interface StringAttr {
+ String value();
+
+ int maxSdkVersion() default 0;
+}