واجهة برمجة تطبيقات Java لإنشاء ملفات مصدر Java [مغلق]

StackOverflow https://stackoverflow.com/questions/121324

  •  02-07-2019
  •  | 
  •  

سؤال

أنا أبحث عن إطار عمل لإنشاء ملفات مصدر Java.

شيء مثل واجهة برمجة التطبيقات التالية:

X clazz = Something.createClass("package name", "class name");
clazz.addSuperInterface("interface name");
clazz.addMethod("method name", returnType, argumentTypes, ...);

File targetDir = ...;
clazz.generate(targetDir);

بعد ذلك، يجب العثور على ملف جافا المصدر في دليل فرعي للدليل الهدف.

هل يعرف أحد مثل هذا الإطار؟


يحرر:

  1. أنا حقا بحاجة إلى الملفات المصدر.
  2. أود أيضًا ملء كود الطرق.
  3. أنا أبحث عن تجريد عالي المستوى، وليس معالجة/إنشاء الكود الثانوي المباشر.
  4. أحتاج أيضًا إلى "بنية الفصل" في شجرة الكائنات.
  5. مجال المشكلة عام:لتوليد عدد كبير من الفئات المختلفة جدًا، بدون "بنية مشتركة".

حلول
لقد نشرت إجابتين بناءً على إجاباتك ... مع CodeModel و مع الكسوف JDT.

لقد استخدمت CodeModel في الحل الخاص بي، :-)

هل كانت مفيدة؟

المحلول

توفر Sun واجهة برمجة تطبيقات تسمى CodeModel لإنشاء ملفات مصدر Java باستخدام واجهة برمجة التطبيقات.إنه ليس أسهل شيء للحصول على معلومات عنه، ولكنه موجود ويعمل بشكل جيد للغاية.

أسهل طريقة للحصول عليه هي كجزء من JAXB 2 RI - يستخدم مولد مخطط XJC إلى Java CodeModel لإنشاء مصدر Java الخاص به، وهو جزء من مرطبانات XJC.يمكنك استخدامه فقط لـ CodeModel.

الاستيلاء عليها من http://codemodel.java.net/

نصائح أخرى

تم العثور على الحل باستخدام CodeModel
شكرًا، سكافمان.

على سبيل المثال بهذا الكود:

JCodeModel cm = new JCodeModel();
JDefinedClass dc = cm._class("foo.Bar");
JMethod m = dc.method(0, int.class, "foo");
m.body()._return(JExpr.lit(5));

File file = new File("./target/classes");
file.mkdirs();
cm.build(file);

يمكنني الحصول على هذا الإخراج:

package foo;
public class Bar {
    int foo() {
        return  5;
    }
}

تم العثور على الحل باستخدام AST الخاص بـ Eclipse JDT
شكرًا، جايلز.

على سبيل المثال بهذا الكود:

AST ast = AST.newAST(AST.JLS3);
CompilationUnit cu = ast.newCompilationUnit();

PackageDeclaration p1 = ast.newPackageDeclaration();
p1.setName(ast.newSimpleName("foo"));
cu.setPackage(p1);

ImportDeclaration id = ast.newImportDeclaration();
id.setName(ast.newName(new String[] { "java", "util", "Set" }));
cu.imports().add(id);

TypeDeclaration td = ast.newTypeDeclaration();
td.setName(ast.newSimpleName("Foo"));
TypeParameter tp = ast.newTypeParameter();
tp.setName(ast.newSimpleName("X"));
td.typeParameters().add(tp);
cu.types().add(td);

MethodDeclaration md = ast.newMethodDeclaration();
td.bodyDeclarations().add(md);

Block block = ast.newBlock();
md.setBody(block);

MethodInvocation mi = ast.newMethodInvocation();
mi.setName(ast.newSimpleName("x"));

ExpressionStatement e = ast.newExpressionStatement(mi);
block.statements().add(e);

System.out.println(cu);

يمكنني الحصول على هذا الإخراج:

package foo;
import java.util.Set;
class Foo<X> {
  void MISSING(){
    x();
  }
}

يمكنك استخدام المحمصة (https://github.com/forge/roaster) للقيام بإنشاء التعليمات البرمجية.

هنا مثال:

JavaClassSource source = Roaster.create(JavaClassSource.class);
source.setName("MyClass").setPublic();
source.addMethod().setName("testMethod").setPrivate().setBody("return null;")
           .setReturnType(String.class).addAnnotation(MyAnnotation.class);
System.out.println(source);

سيعرض الإخراج التالي:

public class MyClass {
   private String testMethod() {
       return null;
   }
}

البديل الآخر هو AST الخاص بـ Eclipse JDT وهو أمر جيد إذا كنت بحاجة إلى إعادة كتابة كود مصدر Java التعسفي بدلاً من مجرد إنشاء كود المصدر.(وأعتقد أنه يمكن استخدامه بشكل مستقل عن الكسوف).

ال كسوف جيت يمكن استخدام المشروع للقيام بإنشاء المصدر.لا أعتقد أن واجهة برمجة التطبيقات (API) هي تمامًا مثل تلك التي وصفتها، ولكن في كل مرة سمعت عن مشروع يقوم بإنشاء مصدر Java، استخدموا JET أو أداة محلية.

لا تعرف مكتبة، ولكن قد يكون محرك القوالب العام هو كل ما تحتاجه.هناك حفنة منهم, ، وأنا شخصيا كان لي تجربة جيدة مع FreeMarker

لقد قمت ببناء شيء يشبه إلى حد كبير DSL النظري الخاص بك، يسمى "sourcegen"، ولكن من الناحية الفنية بدلاً من مشروع فائدة لـ ORM الذي كتبته.يبدو خط DSL كما يلي:

@Test
public void testTwoMethods() {
    GClass gc = new GClass("foo.bar.Foo");

    GMethod hello = gc.getMethod("hello");
    hello.arguments("String foo");
    hello.setBody("return 'Hi' + foo;");

    GMethod goodbye = gc.getMethod("goodbye");
    goodbye.arguments("String foo");
    goodbye.setBody("return 'Bye' + foo;");

    Assert.assertEquals(
    Join.lines(new Object[] {
        "package foo.bar;",
        "",
        "public class Foo {",
        "",
        "    public void hello(String foo) {",
        "        return \"Hi\" + foo;",
        "    }",
        "",
        "    public void goodbye(String foo) {",
        "        return \"Bye\" + foo;",
        "    }",
        "",
        "}",
        "" }),
    gc.toCode());
}

https://github.com/stephenh/joist/blob/master/util/src/test/java/joist/sourcegen/GClassTest.java

كما أنه يقوم ببعض الأشياء الرائعة مثل "التنظيم التلقائي للواردات" أي FQCNs في المعلمات/أنواع الإرجاع، والتقليم التلقائي لأي ملفات قديمة لم يتم التطرق إليها في تشغيل Codegen هذا، ووضع مسافة بادئة للفئات الداخلية بشكل صحيح، وما إلى ذلك.

الفكرة هي أن الكود الذي تم إنشاؤه يجب أن يكون جميلًا عند النظر إليه، بدون أي تحذيرات (الواردات غير المستخدمة، وما إلى ذلك)، تمامًا مثل بقية التعليمات البرمجية الخاصة بك.الكثير من التعليمات البرمجية التي تم إنشاؤها أمر قبيح للقراءة ... إنه أمر فظيع.

على أي حال، لا يوجد الكثير من المستندات، ولكن أعتقد أن واجهة برمجة التطبيقات (API) بسيطة/بديهية جدًا.الريبو مافن هو هنا إذا كان أي شخص مهتما.

إذا كنت حقا بحاجة إلى المصدر، فلا أعرف أي شيء يولد المصدر.ومع ذلك يمكنك استخدام أسم أو CGLIB لإنشاء ملفات .class مباشرةً.

ربما تكون قادرًا على إنشاء مصدر منها، لكنني استخدمتها فقط لإنشاء رمز بايت.

كنت أفعل ذلك بنفسي من أجل أداة إنشاء وهمية.إنها مهمة بسيطة للغاية، حتى لو كنت بحاجة إلى اتباع إرشادات تنسيق Sun.أراهن أنك ستنهي الكود الذي يقوم بذلك بشكل أسرع ثم تجد شيئًا يناسب هدفك على الإنترنت.

لقد حددت واجهة برمجة التطبيقات (API) بنفسك بشكل أساسي.فقط قم بملئه بالرمز الفعلي الآن!

يوجد ايضا StringTemplate.إنه من تأليف مؤلف ANTLR وهو قوي جدًا.

هناك مشروع جديد اكتبها مرة واحدة.مولد الكود القائم على القالب.تكتب قالبًا مخصصًا باستخدام رائع, وإنشاء ملف اعتمادًا على انعكاسات Java.إنها أبسط طريقة لإنشاء أي ملف.يمكنك إنشاء getters/settest/toString عن طريق إنشاء ملفات AspectJ، وSQL استنادًا إلى تعليقات JPA التوضيحية، والإدراجات/التحديثات استنادًا إلى التعدادات وما إلى ذلك.

مثال القالب:

package ${cls.package.name};

public class ${cls.shortName}Builder {

    public static ${cls.name}Builder builder() {
        return new ${cls.name}Builder();
    }
<% for(field in cls.fields) {%>
    private ${field.type.name} ${field.name};
<% } %>
<% for(field in cls.fields) {%>
    public ${cls.name}Builder ${field.name}(${field.type.name} ${field.name}) {
        this.${field.name} = ${field.name};
        return this;
    }
<% } %>
    public ${cls.name} build() {
        final ${cls.name} data = new ${cls.name}();
<% for(field in cls.fields) {%>
        data.${field.setter.name}(this.${field.name});
<% } %>
        return data;
    }
}

يعتمد الأمر حقًا على ما تحاول القيام به.يعد إنشاء التعليمات البرمجية موضوعًا في حد ذاته.بدون حالة استخدام محددة، أقترح النظر في مكتبة إنشاء كود السرعة/النماذج.أيضًا، إذا كنت تقوم بإنشاء التعليمات البرمجية دون الاتصال بالإنترنت، أود أن أقترح استخدام شيء مثل ArgoUML للانتقال من مخطط UML/نموذج الكائن إلى كود Java.

مثال :1/

private JFieldVar generatedField;

2/

String className = "class name";
        /* package name */
        JPackage jp = jCodeModel._package("package name ");
         /*  class name  */
        JDefinedClass jclass = jp._class(className);
        /* add comment */
        JDocComment jDocComment = jclass.javadoc();
        jDocComment.add("By AUTOMAT D.I.T tools : " + new Date() +" => " + className);
        // génération des getter & setter & attribues

            // create attribue 
             this.generatedField = jclass.field(JMod.PRIVATE, Integer.class) 
                     , "attribue name ");
             // getter
             JMethod getter = jclass.method(JMod.PUBLIC, Integer.class) 
                     , "attribue name ");
             getter.body()._return(this.generatedField);
             // setter
             JMethod setter = jclass.method(JMod.PUBLIC, Integer.class) 
                     ,"attribue name ");
             // create setter paramétre 
             JVar setParam = setter.param(getTypeDetailsForCodeModel(Integer.class,"param name");
             // affectation  ( this.param = setParam ) 
             setter.body().assign(JExpr._this().ref(this.generatedField), setParam);

        jCodeModel.build(new File("path c://javaSrc//"));

إليك مشروع JSON-to-POJO الذي يبدو مثيرًا للاهتمام:

http://www.jsonschema2pojo.org/

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top