2010-06-09 4 views
6

원래 제목은 "개미를 사용하여 속성 파일에서 열거 형을 생성하는 방법"Maven의 속성 파일에서 enum을 생성하는 방법은 무엇입니까?

모든 속성을 반복하고 모든 속성을 가진 enum 클래스를 생성하려고합니다.

사용자 정의 작업을 작성하는 것에 대해 생각하고 있지만 추가 병에 넣어야한다고 생각합니다.

메신저를 사용하여 메신저와 나는 generate-sources 단계에서 그것을하고 싶다.

+1

환경은 maven이고 개미는 단지 하나의 가능한 옵션이기 때문에 실제로 질문 제목을 편집해야합니다. –

+0

나는 이것이 오래된 것으로 알고 있지만 속성 파일을 버리고 그냥 enum을 사용하지 않는 이유는 무엇입니까? –

답변

8

비록 다소 Peter Tilemans에 동의하지만,이 문제로 인해 유혹을 받았으며 Groovy와 GMaven-Plugin을 사용하여 솔루션을 해킹했습니다. EDIT : GMaven의 가장 큰 장점은 먼저 플러그인을 만들지 않고도 Maven 객체 모델에 직접 액세스 할 수 있으며 Groovy의 전체 프로그래밍 능력이 있다는 것입니다.

이 경우 나는 src/main/groovy라는 실제 빌드 프로세스의 일부가 아닌 소스 폴더를 만드는 것이므로 jar/war 등에 기여하지 않을 것입니다. 거기 그루비 소스 파일을 넣을 수 있습니다, 그래서 이클립스 빌드를 변경하지 않고 자동 완성 등 그루비 소스 폴더로 그들을 사용할 수 있습니다.

그래서이 폴더에서 나는 세 개의 파일이 있습니다 EnumGenerator.groovy, enumTemplate.txt 및 enum.properties을 여기

그들이 (내가 단순화하기 위해 이런 짓을, 당신은 아마 특성이 다른 곳에서 파일을 얻을 것이다) :

EnumGenerator.groovy

import java.util.Arrays; 
import java.util.HashMap; 
import java.util.TreeMap; 
import java.io.File; 
import java.util.Properties; 

class EnumGenerator{ 

    public EnumGenerator(
     File targetDir, 
     File propfile, 
     File templateFile, 
     String pkgName, 
     String clsName 
    ) { 
     def properties = new Properties(); 
     properties.load(propfile.newInputStream()); 
     def bodyText = generateBody(new TreeMap(properties)); 
     def enumCode = templateFile.getText(); 
     def templateMap = [ body:bodyText, packageName:pkgName, className: clsName ]; 
     templateMap.each{ key, value -> 
           enumCode = enumCode.replace("\${$key}", value) } 
     writeToFile(enumCode, targetDir, pkgName, clsName) 
    } 

    void writeToFile(code, dir, pkg, cls) { 
     def parentDir = new File(dir, pkg.replace('.','/')) 
     parentDir.mkdirs(); 
     def enumFile = new File (parentDir, cls + '.java') 
     enumFile.write(code) 
     System.out.println("Wrote file $enumFile successfully") 
    } 

    String generateBody(values) { 

     // create constructor call PROPERTY_KEY("value") 
     // from property.key=value 
     def body = ""; 
     values.eachWithIndex{ 
      key, value, index -> 
       body += 
       ( 
        (index > 0 ? ",\n\t" : "\t") 
        + toConstantCase(key) + '("' + value + '")' 
       ) 
     } 
     body += ";"; 
     return body; 

    } 

    String toConstantCase(value) { 
     // split camelCase and dot.notation to CAMEL_CASE and DOT_NOTATION 
     return Arrays.asList( 
      value.split("(?:(?=\\p{Upper})|\\.)") 
     ).join('_').toUpperCase(); 
    } 

} 

enumTemplate.txt

package ${packageName}; 

public enum ${className} { 

${body} 

    private ${className}(String value){ 
     this.value = value; 
    } 

    private String value; 

    public String getValue(){ 
     return this.value; 
    } 

} 

enum.속성 여기

simple=value 
not.so.simple=secondvalue 
propertyWithCamelCase=thirdvalue 

가 치어 구성입니다 :

<plugin> 
    <groupId>org.codehaus.groovy.maven</groupId> 
    <artifactId>gmaven-plugin</artifactId> 
    <version>1.0</version> 
    <executions> 
     <execution> 
      <id>create-enum</id> 
      <phase>generate-sources</phase> 
      <goals> 
       <goal>execute</goal> 
      </goals> 
      <configuration> 
       <scriptpath> 
        <element>${pom.basedir}/src/main/groovy</element> 
       </scriptpath> 
       <source> 
        import java.io.File 
        import EnumGenerator 

        File groovyDir = new File(pom.basedir, 
         "src/main/groovy") 
        new EnumGenerator(
         new File(pom.build.directory, 
          "generated-sources/enums"), 
         new File(groovyDir, 
          "enum.properties"), 
         new File(groovyDir, 
          "enumTemplate.txt"), 
         "com.mycompany.enums", 
         "ServiceProperty" 
        ); 

       </source> 
      </configuration> 
     </execution> 
    </executions> 
</plugin> 

그리고 여기 결과입니다 : 템플릿을 사용하여

package com.mycompany.enums; 

public enum ServiceProperty { 

    NOT_SO_SIMPLE("secondvalue"), 
    PROPERTY_WITH_CAMEL_CASE("thirdvalue"), 
    SIMPLE("value"); 

    private ServiceProperty(String value){ 
     this.value = value; 
    } 

    private String value; 

    public String getValue(){ 
     return this.value; 
    } 

} 

, 당신은 당신의 요구에 맞게 열거를 사용자 정의 할 수 있습니다 . gmaven은 maven에 groovy를 내장하고 있기 때문에 아무 것도 설치하거나 빌드 구성을 변경할 필요가 없습니다.

기억해야 할 점은 buildhelper 플러그인을 사용하여 빌드에 add the generated source folder을 사용해야한다는 것입니다.

+0

멋진 아이디어, 감사합니다. – IAdapter

+0

독창성에 대한 +1 (다시) –

+0

@ 파스칼 (우리는 그 중 일부를 더 보게 될 것입니다 :-)) –

3

다시 생각해 보시기 바랍니다.

구성 파일에서 오는 값에 대해 하드 코딩이 끝날 위험이 있으며 언제든지 변경 될 수 있습니다.

속성 파일을 읽는 HashMap 또는 BidiMap 주위의 약간의 래퍼 클래스가 거의 동일한 이점을 얻게 될 것이며 나중에 개발자는 작은 변경으로 인해 gazillion 컴파일 오류가 발생하는 이유를 모르는 채로 자신의 머리카락을 꺼내지 않을 것이라고 생각합니다. 프로퍼티 파일

나는 코드 생성에 대한 내 몫을했습니다. 파서와 프로토콜 처리기에 유용하지만, 다른 모든 유스 케이스의 경우 타임 봄을 똑딱 거리며 사용하고 있습니다.

+0

테스트 용 jQuery 선택기로 사용했습니다. 왜 그게 나쁜 생각이라고 생각하니? 누군가가 선택기를 제거하는 것보다이를 사용하는 테스트를 제거/업데이트해야합니다. 방금 컴파일 오류로 런타임 오류를 교환했습니다. 더하기 내가이 easly 탈출 할 수있는이 방법 : 선택기 (그것은 단지 \\ :)으로 작동합니다. – IAdapter

+0

나는 당신이 소스 제어하에 생성 된 클래스를 유지하지 않았기 때문에 문제가 있다고 생각한다. 그래서 무언가가 망가 졌을 때 그것을 고치기가 정말로 어려웠다. – IAdapter

+0

생성 된 코드가 자체 포함되어 있으면 문제가되지 않지만 생성 된 시그니처가있는 함수에 대해 생성되지 않은 클래스에서 코딩을 시작하면 문제가 발생합니다. 아니요, 생성 된 클래스는 소스 제어하에 있지 않으며 생성 된 파일 만 생성되었으며 생성 시스템에 의해 생성되었습니다. 코드가 실제로 잘 테스트되고 개발 및 유지 관리 팀의 모든 사람이 알고 있다면 잘 작동 할 것입니다. 실제로 사용 유스 케이스가 좋은 "바보 같은"reptitive 코드를 생성하는 것은 좋은 사용 사례처럼 보입니다. –

관련 문제