Mentions légales du service

Skip to content
Snippets Groups Projects
Commit f7cb1d57 authored by YUKI Tomofumi's avatar YUKI Tomofumi
Browse files

Merge branch 'develop' into 'master'

Develop

See merge request !3
parents 8ed5a30b 0b239e76
No related branches found
Tags v1.2.0
1 merge request!3Develop
Showing
with 190 additions and 1601 deletions
......@@ -50,8 +50,8 @@ public class CommonExtensions {
public EObject eRootContainer(final EObject e) {
EObject _xifexpression = null;
EObject _eContainer = e.eContainer();
boolean _equals = Objects.equal(_eContainer, null);
if (_equals) {
boolean _tripleEquals = (_eContainer == null);
if (_tripleEquals) {
_xifexpression = e;
} else {
_xifexpression = this.eRootContainer(e.eContainer());
......@@ -79,7 +79,7 @@ public class CommonExtensions {
}
public String packageName(final Mapping m) {
if (((!Objects.equal(m.getPackage(), null)) && (m.getPackage().length() > 0))) {
if (((m.getPackage() != null) && (m.getPackage().length() > 0))) {
return m.getPackage();
}
StringConcatenation _builder = new StringConcatenation();
......@@ -225,8 +225,7 @@ public class CommonExtensions {
};
final MethodGroup mg = IterableExtensions.<MethodGroup>findFirst(m.getMethodGroups(), _function);
EList<Method> _xifexpression = null;
boolean _equals = Objects.equal(mg, null);
if (_equals) {
if ((mg == null)) {
return new BasicEList<Method>();
} else {
_xifexpression = mg.getMethods();
......
......@@ -165,8 +165,8 @@ public class TypeExtensions {
public String getMethodName(final Method m) {
String _newname = m.getNewname();
boolean _notEquals = (!Objects.equal(_newname, null));
if (_notEquals) {
boolean _tripleNotEquals = (_newname != null);
if (_tripleNotEquals) {
return m.getNewname();
} else {
final Function1<String, CharSequence> _function = new Function1<String, CharSequence>() {
......@@ -184,7 +184,7 @@ public class TypeExtensions {
{
final String typeName = StandardJavaNameBuilder.nameFor(type);
String _xifexpression = null;
if (((!Objects.equal(this.getMappingFor(type), null)) && (!Objects.equal(this._commonExtensions.getEnclosingMapping(this.getMappingFor(type)), this._commonExtensions.getRoot(type))))) {
if (((this.getMappingFor(type) != null) && (!Objects.equal(this._commonExtensions.getEnclosingMapping(this.getMappingFor(type)), this._commonExtensions.getRoot(type))))) {
StringConcatenation _builder = new StringConcatenation();
String _packageName = this._commonExtensions.packageName(this._commonExtensions.getEnclosingMapping(this.getMappingFor(type)));
_builder.append(_packageName);
......@@ -294,8 +294,7 @@ public class TypeExtensions {
}
public Iterable<Method> constructors(final MethodGroup mg) {
boolean _equals = Objects.equal(mg, null);
if (_equals) {
if ((mg == null)) {
return new BasicEList<Method>();
} else {
final Function1<Method, Boolean> _function = new Function1<Method, Boolean>() {
......@@ -309,8 +308,7 @@ public class TypeExtensions {
}
public Iterable<Method> destructors(final MethodGroup mg) {
boolean _equals = Objects.equal(mg, null);
if (_equals) {
if ((mg == null)) {
return new BasicEList<Method>();
} else {
final Function1<Method, Boolean> _function = new Function1<Method, Boolean>() {
......@@ -324,8 +322,7 @@ public class TypeExtensions {
}
public Iterable<Method> staticMethods(final MethodGroup mg) {
boolean _equals = Objects.equal(mg, null);
if (_equals) {
if ((mg == null)) {
return new BasicEList<Method>();
} else {
final Function1<Method, Boolean> _function = new Function1<Method, Boolean>() {
......@@ -339,8 +336,7 @@ public class TypeExtensions {
}
public Iterable<Method> memberMethod(final MethodGroup mg) {
boolean _equals = Objects.equal(mg, null);
if (_equals) {
if ((mg == null)) {
return new BasicEList<Method>();
}
ClassMapping _class_ = mg.getClass_();
......
......@@ -105,10 +105,6 @@ public abstract class AbstractWrapper {
_builder.newLineIfNotEmpty();
_builder.newLine();
_builder.append("\t");
CharSequence _constructorMethodBodies = this.constructorMethodBodies(cm, m);
_builder.append(_constructorMethodBodies, "\t");
_builder.newLineIfNotEmpty();
_builder.append("\t");
_builder.newLine();
_builder.append("\t");
CharSequence _staticMethodBodies = this.staticMethodBodies(cm, m);
......@@ -164,11 +160,6 @@ public abstract class AbstractWrapper {
public CharSequence nativePointerManagement(final ClassMapping cm, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("private static long giveCount = 0;");
_builder.newLine();
_builder.append("private static long takeCount = 0;");
_builder.newLine();
_builder.newLine();
_builder.append("/* @generated */");
_builder.newLine();
_builder.append("protected ");
......@@ -186,9 +177,6 @@ public abstract class AbstractWrapper {
_builder.append("super(ptr);");
_builder.newLine();
_builder.append("\t");
_builder.append("giveCount++;");
_builder.newLine();
_builder.append("\t");
_builder.append("/*** PROTECTED REGION END ***/");
_builder.newLine();
_builder.append("}");
......@@ -209,30 +197,6 @@ public abstract class AbstractWrapper {
_builder.newLineIfNotEmpty();
_builder.append("}");
_builder.newLine();
_builder.newLine();
_builder.append("@Override");
_builder.newLine();
_builder.append("public void taken() {");
_builder.newLine();
_builder.append("\t");
_builder.append("super.taken();");
_builder.newLine();
_builder.append("\t");
_builder.append("takeCount++;");
_builder.newLine();
_builder.append("\t");
_builder.newLine();
_builder.append("\t");
_builder.append("if (takeCount > giveCount) {");
_builder.newLine();
_builder.append("\t\t");
_builder.append("throw new RuntimeException(\"Take count exceeds give count.\");");
_builder.newLine();
_builder.append("\t");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
return _builder;
}
......@@ -241,79 +205,6 @@ public abstract class AbstractWrapper {
return _builder;
}
public CharSequence constructorMethodBodies(final ClassMapping cm, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("/*************************************** ");
_builder.newLine();
_builder.append(" ");
_builder.append("*\t Constructors * ");
_builder.newLine();
_builder.append(" ");
_builder.append("***************************************/");
_builder.newLine();
{
Iterable<Method> _constructors = this._typeExtensions.constructors(this._commonExtensions.getMethodGroup(cm, m));
for(final Method method : _constructors) {
_builder.append("/* @generated */");
_builder.newLine();
String _visibility = this._commonExtensions.visibility(method);
_builder.append(_visibility);
_builder.append(" ");
CharSequence _javaClassName = this._jNIJavaUtilities.javaClassName(cm);
_builder.append(_javaClassName);
_builder.append("(");
final Function1<ParamDef, CharSequence> _function = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
return AbstractWrapper.this._typeExtensions.javaParam(p, cm);
}
};
String _join = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function);
_builder.append(_join);
_builder.append(") { ");
_builder.newLineIfNotEmpty();
_builder.append("\t");
_builder.append("this(");
String _ID = this._commonExtensions.ID(m);
_builder.append(_ID, "\t");
_builder.append("Native.");
String _name = method.getName();
_builder.append(_name, "\t");
_builder.append("(");
final Function1<ParamDef, CharSequence> _function_1 = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
return AbstractWrapper.this._jNIJavaUtilities.nativeParam(p);
}
};
String _join_1 = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function_1);
_builder.append(_join_1, "\t");
_builder.append("));");
_builder.newLineIfNotEmpty();
{
final Function1<ParamDef, Boolean> _function_2 = new Function1<ParamDef, Boolean>() {
@Override
public Boolean apply(final ParamDef p) {
return Boolean.valueOf(p.isTake());
}
};
Iterable<ParamDef> _filter = IterableExtensions.<ParamDef>filter(this._commonExtensions.getActiveParams(method), _function_2);
for(final ParamDef p : _filter) {
_builder.append("\t");
String _name_1 = p.getName();
_builder.append(_name_1, "\t");
_builder.append(".taken();");
_builder.newLineIfNotEmpty();
}
}
_builder.append("}");
_builder.newLine();
_builder.newLine();
}
}
return _builder;
}
public CharSequence destructorMethodBodies(final ClassMapping cm, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("/*************************************** ");
......@@ -540,43 +431,86 @@ public abstract class AbstractWrapper {
private CharSequence staticMethodBody(final Method method, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("checkParameters(");
final Function1<ParamDef, Boolean> _function = new Function1<ParamDef, Boolean>() {
@Override
public Boolean apply(final ParamDef p) {
return Boolean.valueOf(p.isTake());
}
};
final Function1<ParamDef, CharSequence> _function_1 = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
return p.getName();
}
};
String _join = IterableExtensions.<ParamDef>join(IterableExtensions.<ParamDef>filter(this._commonExtensions.getActiveParams(method), _function), ", ", _function_1);
_builder.append(_join);
_builder.append(");");
final String argCheck = _builder.toString();
StringConcatenation _builder_1 = new StringConcatenation();
String _ID = this._commonExtensions.ID(m);
_builder.append(_ID);
_builder.append("Native.");
_builder_1.append(_ID);
_builder_1.append("Native.");
String _name = method.getName();
_builder.append(_name);
_builder.append("(");
final Function1<ParamDef, CharSequence> _function = new Function1<ParamDef, CharSequence>() {
_builder_1.append(_name);
_builder_1.append("(");
final Function1<ParamDef, CharSequence> _function_2 = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
return AbstractWrapper.this._jNIJavaUtilities.nativeParamStatic(p);
}
};
String _join = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function);
_builder.append(_join);
_builder.append(")");
String mainCall = _builder.toString();
if (((!Objects.equal(this._typeExtensions.getMappingFor(method.getRes()), null)) || this._typeExtensions.isBuiltInTypePointer(method.getRes()))) {
StringConcatenation _builder_1 = new StringConcatenation();
String _join_1 = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function_2);
_builder_1.append(_join_1);
_builder_1.append(")");
String mainCall = _builder_1.toString();
if (((this._typeExtensions.getMappingFor(method.getRes()) != null) || this._typeExtensions.isBuiltInTypePointer(method.getRes()))) {
StringConcatenation _builder_2 = new StringConcatenation();
String _returnTypeStandardJavaName = this._typeExtensions.getReturnTypeStandardJavaName(method);
_builder_1.append(_returnTypeStandardJavaName);
_builder_1.append(".build(");
_builder_1.append(mainCall);
_builder_1.append(")");
mainCall = _builder_1.toString();
_builder_2.append(_returnTypeStandardJavaName);
_builder_2.append(".build(");
_builder_2.append(mainCall);
_builder_2.append(")");
mainCall = _builder_2.toString();
}
return this.returnExpr(method, mainCall, this.objStatusUpdate(method), m);
return this.returnExpr(method, argCheck, mainCall, this.objStatusUpdate(method), m);
}
private CharSequence memberMethodBody(final Method method, final ParamDef thisParam, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("checkParameters(");
final Function1<ParamDef, Boolean> _function = new Function1<ParamDef, Boolean>() {
@Override
public Boolean apply(final ParamDef p) {
return Boolean.valueOf(p.isTake());
}
};
final Function1<ParamDef, CharSequence> _function_1 = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
String _xifexpression = null;
boolean _equals = Objects.equal(p, thisParam);
if (_equals) {
_xifexpression = "this";
} else {
_xifexpression = p.getName();
}
return _xifexpression;
}
};
String _join = IterableExtensions.<ParamDef>join(IterableExtensions.<ParamDef>filter(this._commonExtensions.getActiveParams(method), _function), ", ", _function_1);
_builder.append(_join);
_builder.append(");");
final String argCheck = _builder.toString();
StringConcatenation _builder_1 = new StringConcatenation();
String _ID = this._commonExtensions.ID(m);
_builder.append(_ID);
_builder.append("Native.");
_builder_1.append(_ID);
_builder_1.append("Native.");
String _name = method.getName();
_builder.append(_name);
_builder.append("(");
final Function1<ParamDef, CharSequence> _function = new Function1<ParamDef, CharSequence>() {
_builder_1.append(_name);
_builder_1.append("(");
final Function1<ParamDef, CharSequence> _function_2 = new Function1<ParamDef, CharSequence>() {
@Override
public CharSequence apply(final ParamDef p) {
CharSequence _xifexpression = null;
......@@ -589,23 +523,23 @@ public abstract class AbstractWrapper {
return _xifexpression;
}
};
String _join = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function);
_builder.append(_join);
_builder.append(")");
String mainCall = _builder.toString();
if (((!Objects.equal(this._typeExtensions.getMappingFor(method.getRes()), null)) || this._typeExtensions.isBuiltInTypePointer(method.getRes()))) {
StringConcatenation _builder_1 = new StringConcatenation();
String _join_1 = IterableExtensions.<ParamDef>join(this._commonExtensions.getActiveParams(method), ", ", _function_2);
_builder_1.append(_join_1);
_builder_1.append(")");
String mainCall = _builder_1.toString();
if (((this._typeExtensions.getMappingFor(method.getRes()) != null) || this._typeExtensions.isBuiltInTypePointer(method.getRes()))) {
StringConcatenation _builder_2 = new StringConcatenation();
String _returnTypeStandardJavaName = this._typeExtensions.getReturnTypeStandardJavaName(method);
_builder_1.append(_returnTypeStandardJavaName);
_builder_1.append(".build(");
_builder_1.append(mainCall);
_builder_1.append(")");
mainCall = _builder_1.toString();
_builder_2.append(_returnTypeStandardJavaName);
_builder_2.append(".build(");
_builder_2.append(mainCall);
_builder_2.append(")");
mainCall = _builder_2.toString();
}
return this.returnExpr(method, mainCall, this.objStatusUpdate(method, thisParam), m);
return this.returnExpr(method, argCheck, mainCall, this.objStatusUpdate(method, thisParam), m);
}
private CharSequence returnExpr(final Method method, final CharSequence mainCall, final CharSequence objStatusUpdate, final Mapping m) {
private CharSequence returnExpr(final Method method, final CharSequence argCheck, final CharSequence mainCall, final CharSequence objStatusUpdate, final Mapping m) {
CharSequence _xblockexpression = null;
{
boolean _isVoid = this._typeExtensions.isVoid(method);
......@@ -627,22 +561,22 @@ public abstract class AbstractWrapper {
_builder.newLineIfNotEmpty();
}
}
{
boolean _useSemaphore = this.useSemaphore(this._commonExtensions.ID(m));
if (_useSemaphore) {
_builder.append("semISLCall.acquireUninterruptibly();");
_builder.newLine();
_builder.append("try {");
_builder.newLine();
}
}
_builder.newLine();
_builder.append("synchronized(LOCK) {");
_builder.newLine();
_builder.append("\t");
_builder.append(argCheck, "\t");
_builder.newLineIfNotEmpty();
_builder.append("\t");
_builder.append("try {");
_builder.newLine();
_builder.append("\t\t");
{
if (hasReturn) {
_builder.append("res = ");
}
}
_builder.append(mainCall, "\t");
_builder.append(mainCall, "\t\t");
{
if (returnBool) {
_builder.append(" != 0");
......@@ -650,21 +584,18 @@ public abstract class AbstractWrapper {
}
_builder.append(";");
_builder.newLineIfNotEmpty();
{
boolean _useSemaphore_1 = this.useSemaphore(this._commonExtensions.ID(m));
if (_useSemaphore_1) {
_builder.append("} finally {");
_builder.newLine();
_builder.append("\t");
_builder.append("semISLCall.release();");
_builder.newLine();
_builder.append("\t");
_builder.append(objStatusUpdate, "\t");
_builder.newLineIfNotEmpty();
_builder.append("}");
_builder.newLine();
}
}
_builder.append("\t");
_builder.append("} finally {");
_builder.newLine();
_builder.append("\t\t");
_builder.append(objStatusUpdate, "\t\t");
_builder.newLineIfNotEmpty();
_builder.append("\t");
_builder.append("}");
_builder.newLine();
_builder.append("}");
_builder.newLine();
_builder.newLine();
{
if (hasReturn) {
_builder.append("return res;");
......@@ -676,10 +607,6 @@ public abstract class AbstractWrapper {
return _xblockexpression;
}
private boolean useSemaphore(final String id) {
return ((id.equals("ISL") || id.equals("Barvinok")) || id.equals("Cloog"));
}
private CharSequence objStatusUpdate(final Method method) {
return this.objStatusUpdate(method, null);
}
......@@ -698,12 +625,13 @@ public abstract class AbstractWrapper {
{
boolean _equals = Objects.equal(param, thisParam);
if (_equals) {
_builder.append("this.taken();");
_builder.append("taken(this);");
_builder.newLine();
} else {
_builder.append("taken(");
String _name = param.getName();
_builder.append(_name);
_builder.append(".taken();");
_builder.append(");");
_builder.newLineIfNotEmpty();
}
}
......
package fr.irisa.cairn.jnimap.generator.java;
import com.google.common.base.Objects;
import fr.irisa.cairn.jniMap.EnumToClassMapping;
import fr.irisa.cairn.jniMap.EnumValue;
import fr.irisa.cairn.jniMap.Mapping;
......@@ -21,7 +20,7 @@ public class EnumWrapperExtension extends AbstractWrapper {
/**
* There is no pointer management for Enum.
* However, since the base consructor is defined here,
* However, since the base constructor is defined here,
* it is overridden to add some specific behaviors for Enum.
*/
public CharSequence enumToClassMappingContent(final EnumToClassMapping cm, final Mapping m) {
......@@ -90,8 +89,8 @@ public class EnumWrapperExtension extends AbstractWrapper {
for(final EnumValue enumValue : _values) {
{
EnumValue _enumNext = enumValue.getEnumNext();
boolean _notEquals = (!Objects.equal(_enumNext, null));
if (_notEquals) {
boolean _tripleNotEquals = (_enumNext != null);
if (_tripleNotEquals) {
_builder.append("\t");
_builder.append("public static final int ");
String _upperCase = enumValue.getName().toUpperCase();
......@@ -187,8 +186,8 @@ public class EnumWrapperExtension extends AbstractWrapper {
_builder.newLineIfNotEmpty();
{
EnumValue _enumNext_1 = enumValue_2.getEnumNext();
boolean _equals = Objects.equal(_enumNext_1, null);
if (_equals) {
boolean _tripleEquals = (_enumNext_1 == null);
if (_tripleEquals) {
_builder.append("\t\t\t");
_builder.append("return ");
String _name_5 = enumValue_2.getName();
......
package fr.irisa.cairn.jnimap.generator.java;
import com.google.common.base.Objects;
import fr.irisa.cairn.jniMap.CMethod;
import fr.irisa.cairn.jniMap.ClassMapping;
import fr.irisa.cairn.jniMap.EnumToClassMapping;
......@@ -691,8 +690,8 @@ public class JNIJavaTemplate {
for(final FieldDef field : _fields) {
{
Type _type = field.getType();
boolean _equals = Objects.equal(_type, null);
if (_equals) {
boolean _tripleEquals = (_type == null);
if (_tripleEquals) {
String _name = field.getName();
String _plus = ("[ERROR] Field " + _name);
String _plus_1 = (_plus + " for ");
......
......@@ -45,8 +45,8 @@ public class JNIJavaUtilities {
StringConcatenation _builder = new StringConcatenation();
{
ClassMapping _super = cm.getSuper();
boolean _notEquals = (!Objects.equal(_super, null));
if (_notEquals) {
boolean _tripleNotEquals = (_super != null);
if (_tripleNotEquals) {
CharSequence _javaClassName = this.javaClassName(cm.getSuper());
_builder.append(_javaClassName);
} else {
......@@ -58,15 +58,15 @@ public class JNIJavaUtilities {
protected CharSequence _javaSuperClass(final StructToClassMapping cm, final Mapping m) {
ClassMapping _super = cm.getSuper();
boolean _equals = Objects.equal(_super, null);
if (_equals) {
boolean _tripleEquals = (_super == null);
if (_tripleEquals) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("JNIObject");
return _builder.toString();
}
Mapping _enclosingMapping = this._commonExtensions.getEnclosingMapping(cm.getSuper());
boolean _equals_1 = Objects.equal(_enclosingMapping, m);
if (_equals_1) {
boolean _equals = Objects.equal(_enclosingMapping, m);
if (_equals) {
StringConcatenation _builder_1 = new StringConcatenation();
CharSequence _javaClassName = this.javaClassName(cm.getSuper());
_builder_1.append(_javaClassName);
......
package fr.irisa.cairn.jnimap.generator.java;
import com.google.common.base.Objects;
import fr.irisa.cairn.jniMap.BuiltInType;
import fr.irisa.cairn.jniMap.ClassMapping;
import fr.irisa.cairn.jniMap.EnumType;
......@@ -98,8 +97,8 @@ public class StructWrapperExtension extends AbstractWrapper {
_builder.newLine();
{
ClassMapping _super = cm.getSuper();
boolean _equals = Objects.equal(_super, null);
if (_equals) {
boolean _tripleEquals = (_super == null);
if (_tripleEquals) {
_builder.newLine();
_builder.append("/* @generated */");
_builder.newLine();
......@@ -164,7 +163,7 @@ public class StructWrapperExtension extends AbstractWrapper {
final MethodGroup scMG = this._commonExtensions.getMethodGroup(subClass_1, m);
_builder.newLineIfNotEmpty();
{
if ((Objects.equal(scMG, null) || (IterableExtensions.size(IterableExtensions.<Method>filter(scMG.getMethods(), new Function1<Method, Boolean>() {
if (((scMG == null) || (IterableExtensions.size(IterableExtensions.<Method>filter(scMG.getMethods(), new Function1<Method, Boolean>() {
@Override
public Boolean apply(final Method e) {
return Boolean.valueOf(e.isInstanceof());
......
......@@ -24,7 +24,7 @@ public class UnmappedWrapperExtension extends AbstractWrapper {
{
final ClassMapping sClass = ((UnmappedClass) cm).getSuper();
CharSequence _xifexpression = null;
if (((!Objects.equal(sClass, null)) && (!Objects.equal(this._commonExtensions.getEnclosingMapping(sClass), m)))) {
if (((sClass != null) && (!Objects.equal(this._commonExtensions.getEnclosingMapping(sClass), m)))) {
StringConcatenation _builder = new StringConcatenation();
_builder.append("import ");
String _packageName = this._commonExtensions.packageName(this._commonExtensions.getEnclosingMapping(sClass));
......@@ -43,12 +43,6 @@ public class UnmappedWrapperExtension extends AbstractWrapper {
return _xblockexpression;
}
@Override
public CharSequence constructorMethodBodies(final ClassMapping cm, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
return _builder;
}
@Override
public CharSequence destructorMethodBodies(final ClassMapping cm, final Mapping m) {
StringConcatenation _builder = new StringConcatenation();
......
......@@ -33,7 +33,7 @@ class CommonExtensions {
}
def EObject eRootContainer(EObject e) {
if (e.eContainer == null) {
if (e.eContainer === null) {
e;
} else {
e.eContainer.eRootContainer;
......@@ -57,7 +57,7 @@ class CommonExtensions {
def String packageName(Mapping m) {
if (m.package != null && m.package.length > 0)
if (m.package !== null && m.package.length > 0)
return m.package;
return '''fr.irisa.cairn.jnimap.«m.name.toLowerCase»''';
......@@ -139,7 +139,7 @@ class CommonExtensions {
def getMethods(ClassMapping cm, Mapping m) {
val mg = m.methodGroups.findFirst[mg|mg.class_ == cm]
if (mg == null) {
if (mg === null) {
return new BasicEList<Method>();
} else {
mg.methods;
......
......@@ -166,7 +166,7 @@ String dot2underscore(List<String> params) : JAVA
def String getMethodName(Method m) {
if (m.newname != null) {
if (m.newname !== null) {
return m.newname;
} else {
return m.name.split("_").join("", [e|e.toFirstUpper()]).toFirstLower;
......@@ -181,7 +181,7 @@ String dot2underscore(List<String> params) : JAVA
def String standardJavaName(Type type) {
val typeName = StandardJavaNameBuilder.nameFor(type);
if (type.mappingFor != null && type.mappingFor.enclosingMapping != type.root) {
if (type.mappingFor !== null && type.mappingFor.enclosingMapping != type.root) {
'''«type.mappingFor.enclosingMapping.packageName».jni.«typeName»'''
} else {
'''«typeName»'''
......@@ -251,7 +251,7 @@ String dot2underscore(List<String> params) : JAVA
//Various types of method registered for classMapping
def constructors(MethodGroup mg) {
if (mg == null) {
if (mg === null) {
return new BasicEList<Method>();
} else {
return mg.methods.filter[c|c.constructor && c.res.mappingFor==mg.class_];
......@@ -259,7 +259,7 @@ String dot2underscore(List<String> params) : JAVA
}
def destructors(MethodGroup mg) {
if (mg == null) {
if (mg === null) {
return new BasicEList<Method>();
} else {
return mg.methods.filter[c|c.destructor]
......@@ -267,7 +267,7 @@ String dot2underscore(List<String> params) : JAVA
}
def staticMethods(MethodGroup mg) {
if (mg == null) {
if (mg === null) {
return new BasicEList<Method>();
} else {
return mg.methods.filter[e|!e.destructor && !e.constructor && !e.^instanceof && e.static];
......@@ -275,7 +275,7 @@ String dot2underscore(List<String> params) : JAVA
}
def memberMethod(MethodGroup mg) {
if (mg == null) {
if (mg === null) {
return new BasicEList<Method>();
}
......
......@@ -41,7 +41,8 @@ abstract class AbstractWrapper {
«cm.specializedBody(m)»
«cm.constructorMethodBodies(m)»
««« Constructors are no longer used
««« «cm.constructorMethodBodies(m)»
««« Finalizers are no longer used
««« «cm.destructorMethodBodies(m)»
......@@ -71,14 +72,10 @@ abstract class AbstractWrapper {
''''''
def nativePointerManagement(ClassMapping cm, Mapping m) '''
private static long giveCount = 0;
private static long takeCount = 0;
/* @generated */
protected «cm.javaClassName»(long ptr) {
/*** PROTECTED REGION ID(«cm.name»_Constructor) DISABLED START ***/
super(ptr);
giveCount++;
/*** PROTECTED REGION END ***/
}
......@@ -86,37 +83,11 @@ abstract class AbstractWrapper {
protected static «cm.javaClassName» build(long ptr) {
return new «cm.javaClassName»(ptr);
}
@Override
public void taken() {
super.taken();
takeCount++;
if (takeCount > giveCount) {
throw new RuntimeException("Take count exceeds give count.");
}
}
'''
def specializedBody(ClassMapping cm, Mapping m)
''''''
def constructorMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Constructors *
***************************************/
«FOR method : cm.getMethodGroup(m).constructors»
/* @generated */
«method.visibility» «cm.javaClassName»(«method.activeParams.join(", ", [p|p.javaParam(cm)])») {
this(«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|p.nativeParam])»));
«FOR p : method.activeParams.filter[p|p.take]»
«p.name».taken();
«ENDFOR»
}
«ENDFOR»
'''
def destructorMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Finalizer *
......@@ -177,22 +148,25 @@ abstract class AbstractWrapper {
'''
def private staticMethodBody(Method method, Mapping m) {
val argCheck = '''checkParameters(«method.activeParams.filter[p|p.take].join(", ", [p|p.name])»);'''
var mainCall = '''«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|p.nativeParamStatic])»)''';
if (method.res.mappingFor!=null||method.res.builtInTypePointer) {
if (method.res.mappingFor!==null||method.res.builtInTypePointer) {
mainCall = '''«method.returnTypeStandardJavaName».build(«mainCall»)''';
}
return method.returnExpr(mainCall, method.objStatusUpdate, m);
return method.returnExpr(argCheck, mainCall, method.objStatusUpdate, m);
}
def private memberMethodBody(Method method, ParamDef thisParam, Mapping m) {
val argCheck = '''checkParameters(«method.activeParams.filter[p|p.take].join(", ", [p|if (p==thisParam) "this" else p.name])»);'''
var mainCall = '''«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|if (p==thisParam) {"getNativePtr(this)"} else {p.nativeParam}])»)''';
if (method.res.mappingFor!=null||method.res.builtInTypePointer) {
if (method.res.mappingFor!==null||method.res.builtInTypePointer) {
mainCall = '''«method.returnTypeStandardJavaName».build(«mainCall»)''';
}
return method.returnExpr(mainCall, method.objStatusUpdate(thisParam), m);
return method.returnExpr(argCheck, mainCall, method.objStatusUpdate(thisParam), m);
}
//
def private returnExpr(Method method, CharSequence mainCall, CharSequence objStatusUpdate, Mapping m) {
def private returnExpr(Method method, CharSequence argCheck, CharSequence mainCall, CharSequence objStatusUpdate, Mapping m) {
val hasReturn = !method.isVoid
val returnBool = hasReturn && method.res instanceof BooleanType
val res = if (returnBool) "boolean res" else method.returnTypeStandardJavaName + " res"
......@@ -201,27 +175,22 @@ abstract class AbstractWrapper {
«IF hasReturn»
«res»;
«ENDIF»
«IF useSemaphore(m.ID)»
semISLCall.acquireUninterruptibly();
synchronized(LOCK) {
«argCheck»
try {
«ENDIF»
«IF hasReturn»res = «ENDIF»«mainCall»«IF returnBool» != 0«ENDIF»;
«IF useSemaphore(m.ID)»
«IF hasReturn»res = «ENDIF»«mainCall»«IF returnBool» != 0«ENDIF»;
} finally {
semISLCall.release();
«objStatusUpdate»
}
«ENDIF»
}
«IF hasReturn»
return res;
«ENDIF»
'''
}
def private useSemaphore(String id) {
return (id.equals("ISL") || id.equals("Barvinok") || id.equals("Cloog")); // TODO: Cloog: only a few method use "isl_ctx" => Mapping can probably improved
}
def private objStatusUpdate(Method method) {
method.objStatusUpdate(null);
}
......@@ -230,9 +199,9 @@ abstract class AbstractWrapper {
'''
«FOR param : method.activeParams.filter[p|p.take]»
«IF param == thisParam»
this.taken();
taken(this);
«ELSE»
«param.name».taken();
taken(«param.name»);
«ENDIF»
«ENDFOR»
'''
......
package fr.irisa.cairn.jnimap.generator.java
import fr.irisa.cairn.jniMap.ClassMapping
import fr.irisa.cairn.jniMap.Mapping
import fr.irisa.cairn.jniMap.Method
import fr.irisa.cairn.jnimap.generator.CommonExtensions
import fr.irisa.cairn.jnimap.generator.TypeExtensions
import fr.irisa.cairn.jniMap.BooleanType
import fr.irisa.cairn.jniMap.ParamDef
import fr.irisa.cairn.jniMap.EnumType
import fr.irisa.cairn.jniMap.Type
import fr.irisa.cairn.jniMap.StringType
import fr.irisa.cairn.jniMap.IntegerType
import fr.irisa.cairn.jniMap.RealType
import fr.irisa.cairn.jniMap.VoidType
abstract class AbstractWrapper_PrintOutISLStatements {
// =====> Add the following lines to the JNIObject class:
/*
private final Semaphore semISLCall = new Semaphore(1, true);
public String nameISLCVariable;
public static int countInstruction;
public static BufferedWriter buffOut = null;
public static void addToOutputStream(String str) {
//System.out.println(str);
if (buffOut==null) {
File file = new File("~/Bureau/instructionIsl.txt");
try {
buffOut = new BufferedWriter(new FileWriter(file));
} catch (IOException e) {
throw new RuntimeException("Error creating the file");
}
}
try {
buffOut.write(str);
buffOut.flush();
} catch (IOException e) {
throw new RuntimeException("Error creating the file");
}
}
*/
// You still need to introduce the macro and the includes at the beginning of the instructionISl.txt file
// to transform it into a C executable program
extension CommonExtensions = new CommonExtensions();
extension TypeExtensions = new TypeExtensions();
extension JNIJavaUtilities = new JNIJavaUtilities();
def javaMethodName(Method method)
'''«method.methodName»'''
def classMappingContent(ClassMapping cm, Mapping m) '''
package «m.packageName».jni;
«cm.imports(m)»
/*** PROTECTED REGION ID(«cm.name»_userImport) ENABLED START ***/
/*
Put you custom import here ....
*/
/*** PROTECTED REGION END ***/
/**
* Automatically generated by jnimap
* @generated
*/
public class «cm.javaClassName» extends «cm.javaSuperClass(m)» {
«cm.nativePointerManagement(m)»
/*** PROTECTED REGION ID(«cm.name»_userCode) ENABLED START ***/
/*** PROTECTED REGION END ***/
«cm.specializedBody(m)»
«cm.constructorMethodBodies(m)»
««« Finalizers are no longer used
««« «cm.destructorMethodBodies(m)»
«cm.staticMethodBodies(m)»
«cm.memberMethodBodies(m)»
«cm.toStringBody(m)»
}
'''
def imports(ClassMapping cm, Mapping m) '''
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import fr.irisa.cairn.jnimap.runtime.JNIObject;
«importSuperClass(cm, m)»
'''
def importSuperClass(ClassMapping cm, Mapping m)
''''''
def nativePointerManagement(ClassMapping cm, Mapping m) '''
private static long giveCount = 0;
private static long takeCount = 0;
/* @generated */
protected «cm.javaClassName»(long ptr) {
/*** PROTECTED REGION ID(«cm.name»_Constructor) DISABLED START ***/
super(ptr);
giveCount++;
/*** PROTECTED REGION END ***/
}
/* @generated */
protected static «cm.javaClassName» build(long ptr) {
return new «cm.javaClassName»(ptr);
}
@Override
public void taken() {
super.taken();
takeCount++;
if (takeCount > giveCount) {
throw new RuntimeException("Take count exceeds give count.");
}
}
'''
def specializedBody(ClassMapping cm, Mapping m)
''''''
def constructorMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Constructors *
***************************************/
«FOR method : cm.getMethodGroup(m).constructors»
/* @generated */
«method.visibility» «cm.javaClassName»(«method.activeParams.join(", ", [p|p.javaParam(cm)])») {
this(«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|p.nativeParam])»));
«FOR p : method.activeParams.filter[p|p.take]»
«p.name».taken();
«ENDFOR»
}
«ENDFOR»
'''
def destructorMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Finalizer *
***************************************/
«FOR method : cm.getMethodGroup(m).destructors»
«System.err.println("[ERROR] Destructors are currently not supported")»
««« Direct port from Xpand version, but it looks broken
««« /* @generated */
««« finalize «cm.name»() {
««« «method.javaMethodName»(«method.params.join(", ", [p|p.javaParam])») {
««« this «method.res.standardJavaName»(«m.ID»Native.«method.name»(«method.params.join(", ", [p|p.nativeParam])»));
««« }
«ENDFOR»
'''
def staticMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Static Methods *
***************************************/
«FOR method : cm.getMethodGroup(m).staticMethods»
«val takeList = method.activeParams.filter[p|p.take]»
/**
* «method.name»
*
«IF !takeList.empty»@take «takeList.join(" ", [p|p.name])»«ENDIF»
* @generated
**/
«method.visibility» static «method.returnTypeStandardJavaName» «method.javaMethodName»(«method.activeParams.join(", ", [p|p.javaParam(cm)])») {
/*** PROTECTED REGION ID(static_«method.name») DISABLED START ***/
«method.staticMethodBody(m)»
/*** PROTECTED REGION END ***/
}
«ENDFOR»
'''
def memberMethodBodies(ClassMapping cm, Mapping m) '''
/***************************************
* Member Methods *
***************************************/
«FOR method : cm.getMethodGroup(m).memberMethod»
«val thisParam = method.activeParams.get(method.arg)»
«val usedParams = method.activeParams.filter[p|p!=thisParam]»
«val takeList = method.activeParams.filter[p|p.take]»
/**
* «method.name»
*
«IF !takeList.empty» * @take «takeList.join(" ", [p|if(p!=thisParam) p.name else "this"])»«ENDIF»
* @generated
**/
«method.visibility» «method.returnTypeStandardJavaName» «method.javaMethodName»(«usedParams.join(", ", [p|p.javaParam(cm)])») {
/*** PROTECTED REGION ID(«method.name») DISABLED START ***/
«method.memberMethodBody(thisParam, m)»
/*** PROTECTED REGION END ***/
}
«ENDFOR»
'''
def private staticMethodBody(Method method, Mapping m) {
var mainCall = '''«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|p.nativeParamStatic])»)''';
if (method.res.mappingFor!=null||method.res.builtInTypePointer) {
mainCall = '''«method.returnTypeStandardJavaName».build(«mainCall»)''';
}
var printerIslC = '''«if (method.res instanceof VoidType) {}
else if (method.res.basicType || method.res instanceof EnumType) {"String resVarName = \"res\" + countInstruction;"}
else {"res.nameISLCVariable = \"" + method.returnTypeStandardJavaName + "\" + countInstruction;"}»
JNIObject.countInstruction++;
addToOutputStream(«if (method.res instanceof VoidType) {"\""}
else {"\"" + method.returnTypeStandardJavaName + " \" + " + if (method.res.basicType || method.res instanceof EnumType) {"resVarName + \" = "}
else {"res.nameISLCVariable + \" = "}}» «method.name» (" + «
if (method.activeParams.isEmpty) {"\" \""}
else {method.activeParams.join(" + \", \" + ", [p|
if (p.type.isStringType) { "\" \\\"\" + " + p.name + " + \"\\\" \" "} else
if (p.type.basicType) {p.name} else
if (p.type instanceof EnumType) { p.name + ".getValue()" } else
if (p.type.JNIJavaName.equals("JNIPtrBoolean")) { p.name + ".value"} else
p.name+".nameISLCVariable"])}» + ");\n");''';
return method.returnExpr(mainCall, printerIslC, method.objStatusUpdate);
}
def private memberMethodBody(Method method, ParamDef thisParam, Mapping m) {
var mainCall = '''«m.ID»Native.«method.name»(«method.activeParams.join(", ", [p|if (p==thisParam) {"getNativePtr(this)"} else {p.nativeParam}])»)''';
if (method.res.mappingFor!=null||method.res.builtInTypePointer) {
mainCall = '''«method.returnTypeStandardJavaName».build(«mainCall»)''';
}
var printerIslC = '''«if (method.res instanceof VoidType) {}
else if (method.res.basicType || method.res instanceof EnumType) {"String resVarName = \"res\" + countInstruction;"}
else {"res.nameISLCVariable = \"" + method.returnTypeStandardJavaName + "\" + countInstruction;"}»
JNIObject.countInstruction++;
addToOutputStream(«if (method.res instanceof VoidType) {"\""}
else {"\"" + method.returnTypeStandardJavaName + " \" + " + if (method.res.basicType || method.res instanceof EnumType) {"resVarName + \" = "}
else {"res.nameISLCVariable + \" = "}}» «method.name» (" + «
if (method.activeParams.isEmpty) {"\" \""}
else {method.activeParams.join(" + \", \" + ", [p|
if (p.type.isStringType) { "\" \\\"\" + " + p.name + " + \"\\\" \" "} else
if (p.type.basicType) {p.name} else
if (p.type instanceof EnumType) { p.name + ".getValue()" } else
if (p.type.JNIJavaName.equals("JNIPtrBoolean")) { p.name + ".value"} else
if (p==thisParam) {"this.nameISLCVariable"} else
p.name+".nameISLCVariable"])}» + ");\n");''';
return method.returnExpr(mainCall, printerIslC, method.objStatusUpdate(thisParam));
}
def private basicType(Type type) {
return (type.isStringType) || (type instanceof IntegerType) || (type instanceof RealType) || (type instanceof BooleanType);
}
def private returnExpr(Method method, CharSequence mainCall, CharSequence printerIslC, CharSequence objStatusUpdate) {
if (method.isVoid) {
'''
semISLCall.acquireUninterruptibly();
«mainCall»;
«objStatusUpdate»
«printerIslC»
semISLCall.release();
'''
} else if (method.res instanceof BooleanType) {
'''
semISLCall.acquireUninterruptibly();
boolean res = «mainCall» != 0;
«objStatusUpdate»
«printerIslC»
semISLCall.release();
return res;
'''
} else {
'''
semISLCall.acquireUninterruptibly();
«method.returnTypeStandardJavaName» res = «mainCall»;
«objStatusUpdate»
«printerIslC»
semISLCall.release();
return res;
'''
}
}
def private objStatusUpdate(Method method) {
method.objStatusUpdate(null);
}
def private objStatusUpdate(Method method, ParamDef thisParam) {
'''
«FOR param : method.activeParams.filter[p|p.take]»
«IF param == thisParam»
this.taken();
«ELSE»
«param.name».taken();
«ENDIF»
«ENDFOR»
'''
}
def toStringBody(ClassMapping cm, Mapping m) '''
public String toString() {
/*** PROTECTED REGION ID(«cm.name»_toString) DISABLED START ***/
return «m.ID»PrettyPrinter.asString(this);
/*** PROTECTED REGION END ***/
}
'''
}
\ No newline at end of file
......@@ -11,7 +11,7 @@ class EnumWrapperExtension extends AbstractWrapper {
/**
* There is no pointer management for Enum.
* However, since the base consructor is defined here,
* However, since the base constructor is defined here,
* it is overridden to add some specific behaviors for Enum.
*
*/
......@@ -39,7 +39,7 @@ class EnumWrapperExtension extends AbstractWrapper {
/*** PROTECTED REGION ID(«cm.name»_values) DISABLED START ***/
«FOR enumValue : cm.enum_.values»
«IF enumValue.enumNext != null»
«IF enumValue.enumNext !== null»
public static final int «enumValue.name.toUpperCase» = « enumValue.enumNext.name.toUpperCase()»;
«ELSE»
public static final int «enumValue.name.toUpperCase» = «enumValue.value»;
......@@ -61,7 +61,7 @@ class EnumWrapperExtension extends AbstractWrapper {
switch(value) {
«FOR enumValue : cm.enum_.values»
case «enumValue.name.toUpperCase()»:
«IF enumValue.enumNext == null»
«IF enumValue.enumNext === null»
return «enumValue.name»;
«ENDIF»
«ENDFOR»
......
......@@ -258,7 +258,7 @@ class JNIJavaTemplate {
def dispatch javaGetterSetter(StructToClassMapping scm) '''
«FOR field : scm.struct.fields»
«IF field.type == null»
«IF field.type === null»
«System.err.println("[ERROR] Field "+field.name+" for "+scm.name+ " is null")»
«ELSE»
// getter for «scm.name».«field.name»
......
......@@ -26,10 +26,10 @@ class JNIJavaUtilities {
'''JNIObject'''
def dispatch javaSuperClass(UnmappedClass cm, Mapping m)
'''«IF cm.^super != null»«cm.^super.javaClassName»«ELSE»JNIObject«ENDIF»'''
'''«IF cm.^super !== null»«cm.^super.javaClassName»«ELSE»JNIObject«ENDIF»'''
def dispatch javaSuperClass(StructToClassMapping cm, Mapping m) {
if (cm.^super == null)
if (cm.^super === null)
return '''JNIObject''';
if (cm.^super.enclosingMapping == m) {
......
......@@ -42,7 +42,7 @@ class StructWrapperExtension extends AbstractWrapper {
/*** PROTECTED REGION END ***/
}
«IF cm.^super==null»
«IF cm.^super===null»
/* @generated */
static «cm.javaClassName» build(long ptr) {
......@@ -59,7 +59,7 @@ class StructWrapperExtension extends AbstractWrapper {
«FOR subClass : getAllSubClasses(cm)»
«val scMG = subClass.getMethodGroup(m)»
«IF scMG == null || scMG.methods.filter[e|e.^instanceof].size==0»
«IF scMG === null || scMG.methods.filter[e|e.^instanceof].size==0»
«System.err.println("[ERROR] @StructWrapper: Subclass " +subClass.name+" of "+cm.name+" has no instanceof method")»
«ELSE»
«FOR method : subClass.getMethodGroup(m).methods.filter[e|e.^instanceof]»
......
......@@ -13,14 +13,12 @@ class UnmappedWrapperExtension extends AbstractWrapper {
override importSuperClass(ClassMapping cm, Mapping m) {
val sClass = (cm as UnmappedClass).^super
if (sClass != null && sClass.enclosingMapping != m) {
if (sClass !== null && sClass.enclosingMapping != m) {
'''import «sClass.enclosingMapping.packageName».jni.«sClass.javaClassName»;'''
} else {
''''''
}
}
override constructorMethodBodies(ClassMapping cm, Mapping m) ''''''
override destructorMethodBodies(ClassMapping cm, Mapping m) ''''''
......
package fr.irisa.cairn.jnimap.runtime;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.Semaphore;
/**
* Common parent for all the classes wrapping a JNI object.
*
......@@ -16,41 +10,11 @@ import java.util.concurrent.Semaphore;
*/
public abstract class JNIObject {
public static Object LOCK = new Object();
private final long nativePtr;
protected boolean taken = false;
public static final Semaphore semISLCall = new Semaphore(1, true);
/* Modification to print out all ISL instructions
public String nameISLCVariable;
public static int countInstruction;
public static BufferedWriter buffOut = null;
public static void addToOutputStream(String str) {
// DEBUG
//System.out.println(str);
if (buffOut==null) {
File file = new File("./instructionIsl.txt");
try {
buffOut = new BufferedWriter(new FileWriter(file));
} catch (IOException e) {
throw new RuntimeException("Error creating the file");
}
}
try {
buffOut.write(str);
buffOut.flush();
} catch (IOException e) {
throw new RuntimeException("Error creating the file");
}
// bw.close(); => cleaner, but not needed
}
//*/
private static final long NULL_VALUE = 0;
protected JNIObject(long ptr) {
......@@ -77,9 +41,21 @@ public abstract class JNIObject {
return obj.getNativePtr();
}
protected boolean isTaken() {
return taken;
}
protected void taken() {
//Taken should never be called when the object is already taken
// the getNativePtr method should throw and exception when calling the method before taken is called
assert(!taken);
taken = true;
}
//for static methods in subclasses to access taken
protected static final void taken(JNIObject obj) {
obj.taken();
}
@Override
protected void finalize() {
......@@ -95,4 +71,12 @@ public abstract class JNIObject {
protected static final int toInt(boolean b) {
return b ? 1 : 0;
}
protected static void checkParameters(JNIObject...objs) {
for (JNIObject obj : objs) {
if (obj.isTaken()) {
throw new IllegalStateException("This object has already been freed.");
}
}
}
}
......@@ -6,7 +6,7 @@
<parent>
<groupId>fr.irisa.cairn.gecos.tools.jnimapper</groupId>
<artifactId>fr.irisa.cairn.gecos.tools.jnimapper.root</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
<relativePath>..</relativePath>
</parent>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment