जावा स्रोत फ़ाइलों को उत्पन्न करने के लिए जावा एपीआई [बंद]


127

मैं जावा स्रोत फ़ाइलों को उत्पन्न करने के लिए एक रूपरेखा की तलाश कर रहा हूं।

निम्नलिखित एपीआई की तरह कुछ:

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. समस्या डोमेन सामान्य है: "सामान्य संरचना" के बिना, बहुत भिन्न वर्गों की एक बड़ी राशि उत्पन्न करने के लिए।

समाधान
मैंने आपके उत्तरों में आधारित 2 उत्तर पोस्ट किए हैं ... कोडमॉडल के साथ और ग्रहण जेडीटी के साथ

मैंने अपने समाधान में कोडमॉडल का उपयोग किया है , :-)


आपका प्रश्न बहुत सामान्य है, क्या आपकी समस्या डोमेन वास्तव में यह सामान्य है? क्या आप अपनी समस्या डोमेन के बारे में अधिक विशिष्ट हो सकते हैं? उदाहरण के लिए, मैंने विशिष्ट समस्याओं के लिए कोड जनरेट करने के लिए कोड जनरेशन टूल्स लिखे हैं, जैसे डुप्लिकेट अपवाद क्लास कोड को खत्म करना, या एनम में डुप्लीकेशन को खत्म करना।
ग्रेग मैट्स

@ विवेचक: आप उन प्रश्नों को हल कर सकते हैं जिन्हें आपने प्रश्न में 2 अलग उत्तरों के रूप में रखा है। फिर प्रश्न से प्रत्येक के लिए एक लिंक जोड़ें।
एंडी टर्नर

@Banengusk: पूछने के लिए धन्यवाद, मुझे इंटरनेट के सबसे गहरे हिस्सों को खोजने के घंटों में बचा लिया। @skaffman: शानदार खोज - आपने अपने आगामी कार्य के साथ एक और डेवलपर को और अधिक आसान बना दिया :)
रैन बिरनो

यह SO उत्तर जावा के बजाय C ++ के लिए प्रश्न को संबोधित करता है, लेकिन उत्तर जावा के लिए भी काम करता है। stackoverflow.com/a/28103779/120163
इरा बैक्सटर

जवाबों:


70

सूर्य एक एपीआई का उपयोग करके जावा स्रोत फ़ाइलों को बनाने के लिए कोडमॉडल नामक एक एपीआई प्रदान करता है। जानकारी प्राप्त करना सबसे आसान काम नहीं है, लेकिन यह वहां है और यह बहुत अच्छी तरह से काम करता है।

इसे पकड़ने का सबसे आसान तरीका JAXB 2 RI के भाग के रूप में है - XJC स्कीमा-टू-जावा जनरेटर अपने जावा स्रोत को उत्पन्न करने के लिए कोडमॉडल का उपयोग करता है, और यह XJC जार का हिस्सा है। आप इसे कोडमॉडल के लिए उपयोग कर सकते हैं।

इसे http://codemodel.java.net/ से पकड़ो


2
यह वही है जो मुझे चाहिए! सरल और पूरी तरह कार्यात्मक। धन्यवाद, स्कफ़मैन!
डैनियल फंजुल

1
@BradCupit पोम फ़ाइल के अनुसार repo.maven.apache.org/maven2/com/sun/codemodel/codemodel/2.6/... , यह CDDL + जीपीएल है glassfish.java.net/public/CDDL+GPL_1_1.html
ykaganovich

@ykaganovich अच्छी कॉल। यह [ repo.maven.apache.org/maven2/com/sun/codemodel/… CDDL और GPL के तहत लाइसेंस प्राप्त है)। मैंने अपनी पिछली टिप्पणी हटा दी।
ब्रैड कपिट

46

समाधान के साथ CodeModel पाया
धन्यवाद, skaffman

उदाहरण के लिए, इस कोड के साथ:

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;
    }
}

यह कमाल लग रहा है। आप एक ऐसी विधि कैसे उत्पन्न करते हैं जो एक और प्रकार का रिटर्न देता है जो कोडमॉडल के साथ भी उत्पन्न हो रहा है?
एंड्रस हमर


@ AndrásHummer के लिए cm._class(...)रिटर्न प्रकार तर्क के रूप में दिए गए उदाहरण का उपयोग करें dc.method(...)
ह्यूगो बैस

28

ग्रहण जेडीटी के एएसटी
धन्यवाद, गिल्स के साथ मिला समाधान

उदाहरण के लिए, इस कोड के साथ:

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();
  }
}

क्या मैं पूछ सकता हूं - क्या आपने यह जावा एक्लिप्स प्लगिन के हिस्से के रूप में किया था या आपने इसे स्टैंडअलोन कोड के रूप में उपयोग करने का प्रबंधन किया था? मुझे लगता है कि यह वर्षों पुराना है।
mtrc

@mtrc अगर मुझे अच्छी तरह से याद है, तो यह ग्रहण में एक स्टैंडअलोन और सामान्य जावा प्रोजेक्ट था, क्लासपैथ में उचित जार जोड़ रहा है - लेकिन मुझे फ़ाइल नाम याद नहीं है।
डेनियल फंजुल

17

कोड जनरेशन करने के लिए आप Roaster ( 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;
   }
}

9

एक अन्य विकल्प एक्लिप्स जेडीटी का एएसटी है जो अच्छा है अगर आपको स्रोत कोड को उत्पन्न करने के बजाय मनमाने ढंग से जावा स्रोत कोड को फिर से लिखना होगा। (और मेरा मानना ​​है कि इसे ग्रहण से स्वतंत्र रूप से इस्तेमाल किया जा सकता है)।


1
महान!! एक सार सिंटेक्स ट्री वह है जिसकी मैं तलाश कर रहा हूं ... अब मैं एपीआई के बारे में अधिक जानकारी
खोजूंगा

एपीआई जटिल है, जैसा कि मुझे उम्मीद थी। लेकिन इसमें मेरी जरूरत की सारी कार्यक्षमता है। धन्यवाद, जाइल्स
डेनियल फंजुल

1
जैसा कि @gastaldi द्वारा उल्लेख किया गया है, रोस्टर (JBoss फोर्ज से) ग्रहण JDT के लिए एक अच्छा आवरण है। यह JDT की जटिलता को छुपाता है और जावा कोड को पार्स, संशोधित या लिखने के लिए एक अच्छा एपीआई प्रदान करता है। github.com/forge/roaster
Jmini

4

ग्रहण जेट परियोजना स्रोत पीढ़ी करने के लिए इस्तेमाल किया जा सकता। मुझे नहीं लगता कि यह एपीआई वास्तव में आपके द्वारा वर्णित के समान है, लेकिन हर बार जब मैंने एक परियोजना के बारे में सुना है जो जावा स्रोत पीढ़ी कर रहा है, तो उन्होंने जेट या होमग्रोन टूल का उपयोग किया है।



2

मैंने कुछ ऐसा बनाया है जो आपके सैद्धांतिक डीएसएल को बहुत पसंद करता है, जिसे "सोर्सगेन" कहा जाता है, लेकिन तकनीकी रूप से ओआरएम के लिए एक उपयोग परियोजना के बजाय। 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

यह कुछ साफ-सुथरी चीजें भी करता है जैसे "ऑटो-ऑर्गन इंपोर्ट" किसी भी FQCN को पैरामीटर / रिटर्न प्रकार में, किसी भी पुरानी फाइलों को ऑटो-प्रूनिंग करना जो इस कोडगेन रन में टच नहीं किए गए थे, सही ढंग से इनर क्लास को इंडेंट करना, आदि।

विचार यह है कि उत्पन्न कोड को इसे देखने के लिए सुंदर होना चाहिए, बिना किसी चेतावनी (अप्रयुक्त आयात, आदि) के साथ, आपके बाकी कोड की तरह। इतना उत्पन्न कोड पढ़ने में बदसूरत है ... यह भयानक है।

वैसे भी, बहुत सारे डॉक्स नहीं हैं, लेकिन मुझे लगता है कि एपीआई बहुत सरल / सहज है। मावेन रेपो यहाँ है अगर किसी को दिलचस्पी है।


1

यदि आपको वास्तव में स्रोत की आवश्यकता है, तो मुझे उस स्रोत के बारे में कुछ भी पता नहीं है। हालाँकि .class फ़ाइलों को सीधे बनाने के लिए आप ASM या CGLIB का उपयोग कर सकते हैं ।

आप इनमें से स्रोत उत्पन्न करने में सक्षम हो सकते हैं, लेकिन मैंने केवल उनका उपयोग बायटेकोड उत्पन्न करने के लिए किया है।


1

मैं इसे खुद एक नकली जनरेटर टूल के लिए कर रहा था। यह एक बहुत ही सरल कार्य है, भले ही आपको सूर्य प्रारूपण दिशानिर्देशों का पालन करने की आवश्यकता हो। मुझे यकीन है कि आप उस कोड को समाप्त कर देंगे जो इसे तेज़ी से करता है फिर आपको कुछ ऐसा मिला जो आपके लक्ष्य को इंटरनेट पर फिट करता है।

आपने मूल रूप से स्वयं एपीआई की रूपरेखा तैयार की है। बस अब इसे वास्तविक कोड के साथ भरें!


हेहेहे ... अगर कोई ढांचा नहीं मिला है तो मैं इसे लिखने जा रहा हूं। मुझे बहुत अधिक कार्यक्षमता पसंद है इसलिए मैं इसे सुबह नहीं करूंगा ...
डैनियल फंजुल


1

एक बार में नया प्रोजेक्ट लिखना है । टेम्पलेट आधारित कोड जनरेटर। आप Groovy का उपयोग करके कस्टम टेम्पलेट लिखते हैं , और जावा प्रतिबिंबों के आधार पर फ़ाइल उत्पन्न करते हैं। यह किसी भी फ़ाइल को जेनरेट करने का सबसे सरल तरीका है। आप AspectJ फाइलें, SQL को JPA एनोटेशन, इन्सर्ट्स और अन्य अपडेट्स के आधार पर SQL जनरेट / इनस्ट्रीमिंग कर सकते हैं।

खाका उदाहरण:

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;
    }
}

0

यह वास्तव में आप क्या करने की कोशिश कर रहे हैं पर निर्भर करता है। कोड जेनरेशन अपने आप में एक विषय है। एक विशिष्ट उपयोग के मामले के बिना, मैं सुझाव देता हूं कि वेग कोड जनरेशन / टेम्प्लेट लाइब्रेरी देखें। इसके अलावा, अगर आप कोड जेनरेशन को ऑफलाइन कर रहे हैं, तो मैं यूएमएल आरेख / ऑब्जेक्ट मॉडल से जावा कोड तक जाने के लिए ArgoUML जैसी किसी चीज़ का उपयोग करने का सुझाव दूंगा।


0

छूट: 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//"));

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.