init_project.py 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. #!/usr/bin/env python3
  2. """
  3. DDD Project Initialization Script
  4. This script creates a new DDD project structure based on the selected type:
  5. - single-module: Single Maven module monolith
  6. - multi-module: Multi-module monolith
  7. - microservices: Microservices architecture
  8. """
  9. import os
  10. import sys
  11. import json
  12. from pathlib import Path
  13. from typing import Dict, List, Optional
  14. class DDDProjectInitializer:
  15. """DDD Project Initializer"""
  16. def __init__(self, project_dir: str = "./ddd4j-project"):
  17. self.project_dir = Path(project_dir)
  18. self.project_dir.mkdir(parents=True, exist_ok=True)
  19. def init_single_module(
  20. self,
  21. group_id: str,
  22. artifact_id: str,
  23. version: str,
  24. parent_version: str,
  25. package_base: str,
  26. architecture: str = "ddd-classic"
  27. ):
  28. """Initialize single-module monolith project"""
  29. project_path = self.project_dir / artifact_id
  30. project_path.mkdir(parents=True, exist_ok=True)
  31. # Create directory structure
  32. src_main_java = project_path / "src" / "main" / "java" / package_base.replace(".", "/")
  33. src_main_resources = project_path / "src" / "main" / "resources"
  34. src_test_java = project_path / "src" / "test" / "java" / package_base.replace(".", "/")
  35. src_test_resources = project_path / "src" / "test" / "resources"
  36. for path in [src_main_java, src_main_resources, src_test_java, src_test_resources]:
  37. path.mkdir(parents=True, exist_ok=True)
  38. # Create layer directories
  39. layers = self._get_layers(architecture)
  40. for layer in layers:
  41. layer_path = src_main_java / layer
  42. layer_path.mkdir(parents=True, exist_ok=True)
  43. # Create package-info.java
  44. self._create_package_info(layer_path, f"{package_base}.{layer}")
  45. # Create pom.xml
  46. self._create_single_module_pom(
  47. project_path, group_id, artifact_id, version, parent_version
  48. )
  49. # Create application class
  50. app_class_name = self._to_class_name(artifact_id)
  51. self._create_application_class(
  52. src_main_java, package_base, app_class_name
  53. )
  54. # Create common files
  55. self._create_common_files(project_path, artifact_id)
  56. return str(project_path)
  57. def init_multi_module(
  58. self,
  59. group_id: str,
  60. artifact_id: str,
  61. version: str,
  62. parent_version: str,
  63. package_base: str,
  64. modules: List[str],
  65. architecture: str = "ddd-classic"
  66. ):
  67. """Initialize multi-module monolith project"""
  68. project_path = self.project_dir / artifact_id
  69. project_path.mkdir(parents=True, exist_ok=True)
  70. # Create parent pom.xml
  71. self._create_parent_pom(
  72. project_path, group_id, artifact_id, version, parent_version, modules
  73. )
  74. # Create BOM and dependencies modules
  75. self._create_bom_module(project_path, group_id, artifact_id, version, package_base)
  76. self._create_dependencies_module(project_path, group_id, artifact_id, version, package_base)
  77. # Create common module
  78. self._create_common_module(project_path, group_id, artifact_id, version, package_base)
  79. # Create business modules
  80. for module_name in modules:
  81. self._create_business_module(
  82. project_path, group_id, artifact_id, version, package_base,
  83. module_name, architecture
  84. )
  85. # Create start module
  86. self._create_start_module(
  87. project_path, group_id, artifact_id, version, package_base, modules
  88. )
  89. # Create common files
  90. self._create_common_files(project_path, artifact_id)
  91. return str(project_path)
  92. def init_microservices(
  93. self,
  94. group_id: str,
  95. artifact_id: str,
  96. version: str,
  97. parent_version: str,
  98. package_base: str,
  99. services: List[str],
  100. architecture: str = "ddd-classic"
  101. ):
  102. """Initialize microservices project"""
  103. project_path = self.project_dir / artifact_id
  104. project_path.mkdir(parents=True, exist_ok=True)
  105. # Create parent pom.xml
  106. self._create_microservices_parent_pom(
  107. project_path, group_id, artifact_id, version, parent_version, services
  108. )
  109. # Create platform-common
  110. self._create_platform_common(project_path, group_id, artifact_id, version, package_base)
  111. # Create services
  112. services_dir = project_path / "services"
  113. services_dir.mkdir(parents=True, exist_ok=True)
  114. for service_name in services:
  115. self._create_service(
  116. services_dir, group_id, artifact_id, version, package_base,
  117. service_name, architecture
  118. )
  119. # Create gateway
  120. self._create_gateway(project_path, group_id, artifact_id, version, package_base)
  121. # Create common files
  122. self._create_common_files(project_path, artifact_id)
  123. return str(project_path)
  124. def _get_layers(self, architecture: str) -> List[str]:
  125. """Get layer names based on architecture"""
  126. layer_map = {
  127. "ddd-classic": ["interfaces", "application", "domain", "infrastructure"],
  128. "hexagonal": ["adapter", "application", "domain", "infrastructure"],
  129. "clean": ["interfaces", "application", "domain", "infrastructure"],
  130. "cola-v5": ["adapter", "app", "domain", "infrastructure"]
  131. }
  132. return layer_map.get(architecture, layer_map["ddd-classic"])
  133. def _create_package_info(self, path: Path, package_name: str):
  134. """Create package-info.java file"""
  135. package_info = path / "package-info.java"
  136. content = f"""/**
  137. * {package_name}
  138. *
  139. * This package contains the {path.name} layer components.
  140. */
  141. package {package_name};
  142. """
  143. package_info.write_text(content, encoding="utf-8")
  144. def _create_single_module_pom(
  145. self, project_path: Path, group_id: str, artifact_id: str,
  146. version: str, parent_version: str
  147. ):
  148. """Create single-module pom.xml"""
  149. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  150. <project xmlns="http://maven.apache.org/POM/4.0.0"
  151. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  152. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  153. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  154. <modelVersion>4.0.0</modelVersion>
  155. <parent>
  156. <groupId>{group_id}</groupId>
  157. <artifactId>ddd4j-cloud-parent</artifactId>
  158. <version>{parent_version}</version>
  159. <relativePath/>
  160. </parent>
  161. <groupId>{group_id}</groupId>
  162. <artifactId>{artifact_id}</artifactId>
  163. <version>{version}</version>
  164. <packaging>jar</packaging>
  165. <name>{artifact_id}</name>
  166. <description>DDD Single-Module Monolith Project</description>
  167. <properties>
  168. <java.version>17</java.version>
  169. <maven.compiler.source>17</maven.compiler.source>
  170. <maven.compiler.target>17</maven.compiler.target>
  171. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  172. </properties>
  173. <dependencies>
  174. <dependency>
  175. <groupId>org.springframework.boot</groupId>
  176. <artifactId>spring-boot-starter-web</artifactId>
  177. </dependency>
  178. <dependency>
  179. <groupId>org.springframework.boot</groupId>
  180. <artifactId>spring-boot-starter-data-jpa</artifactId>
  181. </dependency>
  182. <dependency>
  183. <groupId>org.springframework.boot</groupId>
  184. <artifactId>spring-boot-starter-test</artifactId>
  185. <scope>test</scope>
  186. </dependency>
  187. </dependencies>
  188. <build>
  189. <plugins>
  190. <plugin>
  191. <groupId>org.springframework.boot</groupId>
  192. <artifactId>spring-boot-maven-plugin</artifactId>
  193. </plugin>
  194. </plugins>
  195. </build>
  196. </project>
  197. """
  198. (project_path / "pom.xml").write_text(pom_content, encoding="utf-8")
  199. def _create_application_class(self, src_main_java: Path, package_base: str, class_name: str):
  200. """Create Spring Boot application class"""
  201. app_package = src_main_java
  202. app_package.mkdir(parents=True, exist_ok=True)
  203. app_class = app_package / f"{class_name}Application.java"
  204. content = f"""package {package_base};
  205. import org.springframework.boot.SpringApplication;
  206. import org.springframework.boot.autoconfigure.SpringBootApplication;
  207. /**
  208. * {class_name} Application
  209. *
  210. * Main application entry point.
  211. */
  212. @SpringBootApplication
  213. public class {class_name}Application {{
  214. public static void main(String[] args) {{
  215. SpringApplication.run({class_name}Application.class, args);
  216. }}
  217. }}
  218. """
  219. app_class.write_text(content, encoding="utf-8")
  220. def _create_common_files(self, project_path: Path, artifact_id: str):
  221. """Create common files (.gitignore, LICENSE, README.md)"""
  222. # .gitignore
  223. gitignore_content = """# Maven
  224. target/
  225. pom.xml.tag
  226. pom.xml.releaseBackup
  227. pom.xml.versionsBackup
  228. pom.xml.next
  229. release.properties
  230. dependency-reduced-pom.xml
  231. buildNumber.properties
  232. .mvn/timing.properties
  233. .mvn/wrapper/maven-wrapper.jar
  234. # IDE
  235. .idea/
  236. *.iml
  237. *.iws
  238. *.ipr
  239. .vscode/
  240. .classpath
  241. .project
  242. .settings/
  243. *.swp
  244. *.swo
  245. *~
  246. # OS
  247. .DS_Store
  248. Thumbs.db
  249. # Logs
  250. *.log
  251. logs/
  252. """
  253. (project_path / ".gitignore").write_text(gitignore_content, encoding="utf-8")
  254. # LICENSE
  255. license_content = """MIT License
  256. Copyright (c) 2024
  257. Permission is hereby granted, free of charge, to any person obtaining a copy
  258. of this software and associated documentation files (the "Software"), to deal
  259. in the Software without restriction, including without limitation the rights
  260. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  261. copies of the Software, and to permit persons to whom the Software is
  262. furnished to do so, subject to the following conditions:
  263. The above copyright notice and this permission notice shall be included in all
  264. copies or substantial portions of the Software.
  265. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  266. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  267. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  268. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  269. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  270. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  271. SOFTWARE.
  272. """
  273. (project_path / "LICENSE").write_text(license_content, encoding="utf-8")
  274. # README.md
  275. readme_content = f"""# {artifact_id}
  276. DDD (Domain-Driven Design) Project
  277. ## Project Structure
  278. This project follows DDD principles with clear layer separation.
  279. ## Getting Started
  280. ### Prerequisites
  281. - Java 17+
  282. - Maven 3.6+
  283. ### Building
  284. ```bash
  285. mvn clean install
  286. ```
  287. ### Running
  288. ```bash
  289. mvn spring-boot:run
  290. ```
  291. ## Architecture
  292. This project uses DDD Classic Layered Architecture:
  293. - **interfaces**: Interface layer (Controllers, DTOs)
  294. - **application**: Application layer (Application Services, Commands, Queries)
  295. - **domain**: Domain layer (Aggregates, Entities, Value Objects)
  296. - **infrastructure**: Infrastructure layer (Repository Implementations, External Services)
  297. """
  298. (project_path / "README.md").write_text(readme_content, encoding="utf-8")
  299. def _to_class_name(self, artifact_id: str) -> str:
  300. """Convert artifact_id to class name (e.g., ddd4j-order -> Ddd4jOrder)"""
  301. parts = artifact_id.split("-")
  302. return "".join(word.capitalize() for word in parts)
  303. def _create_parent_pom(
  304. self, project_path: Path, group_id: str, artifact_id: str,
  305. version: str, parent_version: str, modules: List[str]
  306. ):
  307. """Create parent pom.xml for multi-module project"""
  308. module_list = "\n".join(f" <module>{artifact_id}-{module}</module>" for module in modules)
  309. module_list += f"\n <module>{artifact_id}-common</module>"
  310. module_list += f"\n <module>{artifact_id}-start</module>"
  311. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  312. <project xmlns="http://maven.apache.org/POM/4.0.0"
  313. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  314. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  315. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  316. <modelVersion>4.0.0</modelVersion>
  317. <parent>
  318. <groupId>{group_id}</groupId>
  319. <artifactId>ddd4j-cloud-parent</artifactId>
  320. <version>{parent_version}</version>
  321. <relativePath/>
  322. </parent>
  323. <groupId>{group_id}</groupId>
  324. <artifactId>{artifact_id}</artifactId>
  325. <version>{version}</version>
  326. <packaging>pom</packaging>
  327. <name>{artifact_id}</name>
  328. <description>DDD Multi-Module Monolith Project</description>
  329. <modules>
  330. <module>{artifact_id}-bom</module>
  331. <module>{artifact_id}-dependencies</module>
  332. {module_list}
  333. </modules>
  334. <properties>
  335. <java.version>17</java.version>
  336. <maven.compiler.source>17</maven.compiler.source>
  337. <maven.compiler.target>17</maven.compiler.target>
  338. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  339. </properties>
  340. </project>
  341. """
  342. (project_path / "pom.xml").write_text(pom_content, encoding="utf-8")
  343. def _create_bom_module(self, project_path: Path, group_id: str, artifact_id: str, version: str, package_base: str):
  344. """Create BOM module"""
  345. bom_dir = project_path / f"{artifact_id}-bom"
  346. bom_dir.mkdir(parents=True, exist_ok=True)
  347. src_main_java = bom_dir / "src" / "main" / "java" / package_base.replace(".", "/") / "bom"
  348. src_main_java.mkdir(parents=True, exist_ok=True)
  349. self._create_package_info(src_main_java, f"{package_base}.bom")
  350. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  351. <project xmlns="http://maven.apache.org/POM/4.0.0"
  352. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  353. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  354. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  355. <modelVersion>4.0.0</modelVersion>
  356. <parent>
  357. <groupId>{group_id}</groupId>
  358. <artifactId>{artifact_id}</artifactId>
  359. <version>{version}</version>
  360. </parent>
  361. <artifactId>{artifact_id}-bom</artifactId>
  362. <packaging>pom</packaging>
  363. <name>{artifact_id}-bom</name>
  364. <description>BOM Dependency Management</description>
  365. </project>
  366. """
  367. (bom_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  368. def _create_dependencies_module(self, project_path: Path, group_id: str, artifact_id: str, version: str, package_base: str):
  369. """Create dependencies module"""
  370. deps_dir = project_path / f"{artifact_id}-dependencies"
  371. deps_dir.mkdir(parents=True, exist_ok=True)
  372. src_main_java = deps_dir / "src" / "main" / "java" / package_base.replace(".", "/") / "dependencies"
  373. src_main_java.mkdir(parents=True, exist_ok=True)
  374. self._create_package_info(src_main_java, f"{package_base}.dependencies")
  375. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  376. <project xmlns="http://maven.apache.org/POM/4.0.0"
  377. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  378. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  379. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  380. <modelVersion>4.0.0</modelVersion>
  381. <parent>
  382. <groupId>{group_id}</groupId>
  383. <artifactId>{artifact_id}</artifactId>
  384. <version>{version}</version>
  385. </parent>
  386. <artifactId>{artifact_id}-dependencies</artifactId>
  387. <packaging>pom</packaging>
  388. <name>{artifact_id}-dependencies</name>
  389. <description>Common Dependencies</description>
  390. </project>
  391. """
  392. (deps_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  393. def _create_common_module(self, project_path: Path, group_id: str, artifact_id: str, version: str, package_base: str):
  394. """Create common module"""
  395. common_dir = project_path / f"{artifact_id}-common"
  396. common_dir.mkdir(parents=True, exist_ok=True)
  397. # Create sub-modules
  398. for sub_module in ["domain", "infrastructure"]:
  399. sub_dir = common_dir / f"{artifact_id}-common-{sub_module}"
  400. sub_dir.mkdir(parents=True, exist_ok=True)
  401. src_main_java = sub_dir / "src" / "main" / "java" / package_base.replace(".", "/") / "common" / sub_module
  402. src_main_java.mkdir(parents=True, exist_ok=True)
  403. self._create_package_info(src_main_java, f"{package_base}.common.{sub_module}")
  404. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  405. <project xmlns="http://maven.apache.org/POM/4.0.0"
  406. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  407. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  408. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  409. <modelVersion>4.0.0</modelVersion>
  410. <parent>
  411. <groupId>{group_id}</groupId>
  412. <artifactId>{artifact_id}-common</artifactId>
  413. <version>{version}</version>
  414. </parent>
  415. <artifactId>{artifact_id}-common-{sub_module}</artifactId>
  416. <packaging>jar</packaging>
  417. <name>{artifact_id}-common-{sub_module}</name>
  418. <description>Common {sub_module.capitalize()} Module</description>
  419. </project>
  420. """
  421. (sub_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  422. # Common parent pom
  423. common_pom = f"""<?xml version="1.0" encoding="UTF-8"?>
  424. <project xmlns="http://maven.apache.org/POM/4.0.0"
  425. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  426. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  427. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  428. <modelVersion>4.0.0</modelVersion>
  429. <parent>
  430. <groupId>{group_id}</groupId>
  431. <artifactId>{artifact_id}</artifactId>
  432. <version>{version}</version>
  433. </parent>
  434. <artifactId>{artifact_id}-common</artifactId>
  435. <packaging>pom</packaging>
  436. <name>{artifact_id}-common</name>
  437. <description>Common Modules</description>
  438. <modules>
  439. <module>{artifact_id}-common-domain</module>
  440. <module>{artifact_id}-common-infrastructure</module>
  441. </modules>
  442. </project>
  443. """
  444. (common_dir / "pom.xml").write_text(common_pom, encoding="utf-8")
  445. def _create_business_module(
  446. self, project_path: Path, group_id: str, artifact_id: str,
  447. version: str, package_base: str, module_name: str, architecture: str
  448. ):
  449. """Create business module with all layers"""
  450. module_dir = project_path / f"{artifact_id}-{module_name}"
  451. module_dir.mkdir(parents=True, exist_ok=True)
  452. layers = self._get_layers(architecture)
  453. layer_suffixes = {
  454. "interfaces": "adapter",
  455. "application": "app",
  456. "domain": "domain",
  457. "infrastructure": "infrastructure",
  458. "adapter": "adapter",
  459. "app": "app"
  460. }
  461. # Create sub-modules for each layer
  462. for layer in layers:
  463. layer_suffix = layer_suffixes.get(layer, layer)
  464. sub_module_dir = module_dir / f"{artifact_id}-{module_name}-{layer_suffix}"
  465. sub_module_dir.mkdir(parents=True, exist_ok=True)
  466. src_main_java = sub_module_dir / "src" / "main" / "java" / package_base.replace(".", "/") / module_name / layer
  467. src_main_java.mkdir(parents=True, exist_ok=True)
  468. self._create_package_info(src_main_java, f"{package_base}.{module_name}.{layer}")
  469. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  470. <project xmlns="http://maven.apache.org/POM/4.0.0"
  471. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  472. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  473. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  474. <modelVersion>4.0.0</modelVersion>
  475. <parent>
  476. <groupId>{group_id}</groupId>
  477. <artifactId>{artifact_id}-{module_name}</artifactId>
  478. <version>{version}</version>
  479. </parent>
  480. <artifactId>{artifact_id}-{module_name}-{layer_suffix}</artifactId>
  481. <packaging>jar</packaging>
  482. <name>{artifact_id}-{module_name}-{layer_suffix}</name>
  483. <description>{module_name.capitalize()} {layer.capitalize()} Layer</description>
  484. """
  485. if layer == "domain":
  486. pom_content += f"""
  487. <dependencies>
  488. <dependency>
  489. <groupId>{group_id}</groupId>
  490. <artifactId>{artifact_id}-common-domain</artifactId>
  491. <version>${{project.version}}</version>
  492. </dependency>
  493. </dependencies>
  494. """
  495. elif layer == "infrastructure":
  496. pom_content += f"""
  497. <dependencies>
  498. <dependency>
  499. <groupId>{group_id}</groupId>
  500. <artifactId>{artifact_id}-{module_name}-domain</artifactId>
  501. <version>${{project.version}}</version>
  502. </dependency>
  503. <dependency>
  504. <groupId>{group_id}</groupId>
  505. <artifactId>{artifact_id}-common-infrastructure</artifactId>
  506. <version>${{project.version}}</version>
  507. </dependency>
  508. </dependencies>
  509. """
  510. elif layer in ["application", "app"]:
  511. pom_content += f"""
  512. <dependencies>
  513. <dependency>
  514. <groupId>{group_id}</groupId>
  515. <artifactId>{artifact_id}-{module_name}-domain</artifactId>
  516. <version>${{project.version}}</version>
  517. </dependency>
  518. </dependencies>
  519. """
  520. elif layer in ["interfaces", "adapter"]:
  521. pom_content += f"""
  522. <dependencies>
  523. <dependency>
  524. <groupId>{group_id}</groupId>
  525. <artifactId>{artifact_id}-{module_name}-app</artifactId>
  526. <version>${{project.version}}</version>
  527. </dependency>
  528. </dependencies>
  529. """
  530. pom_content += "</project>\n"
  531. (sub_module_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  532. # Module parent pom
  533. module_list = "\n".join(
  534. f" <module>{artifact_id}-{module_name}-{layer_suffixes.get(layer, layer)}</module>"
  535. for layer in layers
  536. )
  537. module_pom = f"""<?xml version="1.0" encoding="UTF-8"?>
  538. <project xmlns="http://maven.apache.org/POM/4.0.0"
  539. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  540. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  541. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  542. <modelVersion>4.0.0</modelVersion>
  543. <parent>
  544. <groupId>{group_id}</groupId>
  545. <artifactId>{artifact_id}</artifactId>
  546. <version>{version}</version>
  547. </parent>
  548. <artifactId>{artifact_id}-{module_name}</artifactId>
  549. <packaging>pom</packaging>
  550. <name>{artifact_id}-{module_name}</name>
  551. <description>{module_name.capitalize()} Business Module</description>
  552. <modules>
  553. {module_list}
  554. </modules>
  555. </project>
  556. """
  557. (module_dir / "pom.xml").write_text(module_pom, encoding="utf-8")
  558. def _create_start_module(
  559. self, project_path: Path, group_id: str, artifact_id: str,
  560. version: str, package_base: str, modules: List[str]
  561. ):
  562. """Create start module"""
  563. start_dir = project_path / f"{artifact_id}-start"
  564. start_dir.mkdir(parents=True, exist_ok=True)
  565. src_main_java = start_dir / "src" / "main" / "java" / package_base.replace(".", "/")
  566. src_main_java.mkdir(parents=True, exist_ok=True)
  567. app_class_name = self._to_class_name(artifact_id)
  568. self._create_application_class(src_main_java, package_base, app_class_name)
  569. src_main_resources = start_dir / "src" / "main" / "resources"
  570. src_main_resources.mkdir(parents=True, exist_ok=True)
  571. (src_main_resources / "application.yml").write_text("spring:\n application:\n name: " + artifact_id + "\n", encoding="utf-8")
  572. # Dependencies on all business modules
  573. dependencies = "\n".join(
  574. f""" <dependency>
  575. <groupId>{group_id}</groupId>
  576. <artifactId>{artifact_id}-{module}-adapter</artifactId>
  577. <version>${{project.version}}</version>
  578. </dependency>"""
  579. for module in modules
  580. )
  581. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  582. <project xmlns="http://maven.apache.org/POM/4.0.0"
  583. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  584. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  585. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  586. <modelVersion>4.0.0</modelVersion>
  587. <parent>
  588. <groupId>{group_id}</groupId>
  589. <artifactId>{artifact_id}</artifactId>
  590. <version>{version}</version>
  591. </parent>
  592. <artifactId>{artifact_id}-start</artifactId>
  593. <packaging>jar</packaging>
  594. <name>{artifact_id}-start</name>
  595. <description>Application Start Module</description>
  596. <dependencies>
  597. {dependencies}
  598. <dependency>
  599. <groupId>{group_id}</groupId>
  600. <artifactId>{artifact_id}-common-infrastructure</artifactId>
  601. <version>${{project.version}}</version>
  602. </dependency>
  603. </dependencies>
  604. <build>
  605. <plugins>
  606. <plugin>
  607. <groupId>org.springframework.boot</groupId>
  608. <artifactId>spring-boot-maven-plugin</artifactId>
  609. </plugin>
  610. </plugins>
  611. </build>
  612. </project>
  613. """
  614. (start_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  615. def _create_microservices_parent_pom(
  616. self, project_path: Path, group_id: str, artifact_id: str,
  617. version: str, parent_version: str, services: List[str]
  618. ):
  619. """Create parent pom.xml for microservices project"""
  620. service_modules = "\n".join(f" <module>services/{service}</module>" for service in services)
  621. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  622. <project xmlns="http://maven.apache.org/POM/4.0.0"
  623. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  624. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  625. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  626. <modelVersion>4.0.0</modelVersion>
  627. <parent>
  628. <groupId>{group_id}</groupId>
  629. <artifactId>ddd4j-cloud-parent</artifactId>
  630. <version>{parent_version}</version>
  631. <relativePath/>
  632. </parent>
  633. <groupId>{group_id}</groupId>
  634. <artifactId>{artifact_id}</artifactId>
  635. <version>{version}</version>
  636. <packaging>pom</packaging>
  637. <name>{artifact_id}</name>
  638. <description>DDD Microservices Platform</description>
  639. <modules>
  640. <module>platform-common</module>
  641. {service_modules}
  642. <module>gateway</module>
  643. </modules>
  644. <properties>
  645. <java.version>17</java.version>
  646. <maven.compiler.source>17</maven.compiler.source>
  647. <maven.compiler.target>17</maven.compiler.target>
  648. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  649. </properties>
  650. </project>
  651. """
  652. (project_path / "pom.xml").write_text(pom_content, encoding="utf-8")
  653. def _create_platform_common(self, project_path: Path, group_id: str, artifact_id: str, version: str, package_base: str):
  654. """Create platform-common module"""
  655. common_dir = project_path / "platform-common"
  656. common_dir.mkdir(parents=True, exist_ok=True)
  657. src_main_java = common_dir / "src" / "main" / "java" / package_base.replace(".", "/") / "common"
  658. src_main_java.mkdir(parents=True, exist_ok=True)
  659. self._create_package_info(src_main_java, f"{package_base}.common")
  660. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  661. <project xmlns="http://maven.apache.org/POM/4.0.0"
  662. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  663. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  664. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  665. <modelVersion>4.0.0</modelVersion>
  666. <parent>
  667. <groupId>{group_id}</groupId>
  668. <artifactId>{artifact_id}</artifactId>
  669. <version>{version}</version>
  670. </parent>
  671. <artifactId>platform-common</artifactId>
  672. <packaging>jar</packaging>
  673. <name>platform-common</name>
  674. <description>Platform Common Module</description>
  675. </project>
  676. """
  677. (common_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  678. def _create_service(
  679. self, services_dir: Path, group_id: str, artifact_id: str,
  680. version: str, package_base: str, service_name: str, architecture: str
  681. ):
  682. """Create microservice with all modules"""
  683. service_dir = services_dir / service_name
  684. service_dir.mkdir(parents=True, exist_ok=True)
  685. layers = self._get_layers(architecture)
  686. service_modules = ["api", "domain", "application", "infrastructure", "interfaces", "start"]
  687. for module_suffix in service_modules:
  688. module_dir = service_dir / f"{service_name}-{module_suffix}"
  689. module_dir.mkdir(parents=True, exist_ok=True)
  690. if module_suffix == "start":
  691. src_main_java = module_dir / "src" / "main" / "java" / package_base.replace(".", "/") / service_name.replace("-service", "")
  692. src_main_java.mkdir(parents=True, exist_ok=True)
  693. app_class_name = self._to_class_name(service_name.replace("-service", ""))
  694. self._create_application_class(src_main_java, f"{package_base}.{service_name.replace('-service', '')}", app_class_name)
  695. else:
  696. src_main_java = module_dir / "src" / "main" / "java" / package_base.replace(".", "/") / service_name.replace("-service", "") / module_suffix
  697. src_main_java.mkdir(parents=True, exist_ok=True)
  698. self._create_package_info(src_main_java, f"{package_base}.{service_name.replace('-service', '')}.{module_suffix}")
  699. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  700. <project xmlns="http://maven.apache.org/POM/4.0.0"
  701. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  702. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  703. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  704. <modelVersion>4.0.0</modelVersion>
  705. <parent>
  706. <groupId>{group_id}</groupId>
  707. <artifactId>{service_name}</artifactId>
  708. <version>{version}</version>
  709. </parent>
  710. <artifactId>{service_name}-{module_suffix}</artifactId>
  711. <packaging>jar</packaging>
  712. <name>{service_name}-{module_suffix}</name>
  713. <description>{service_name} {module_suffix.capitalize()} Module</description>
  714. """
  715. if module_suffix == "start":
  716. pom_content += """
  717. <dependencies>
  718. <dependency>
  719. <groupId>${project.groupId}</groupId>
  720. <artifactId>${service-name}-interfaces</artifactId>
  721. <version>${project.version}</version>
  722. </dependency>
  723. <dependency>
  724. <groupId>${project.groupId}</groupId>
  725. <artifactId>${service-name}-application</artifactId>
  726. <version>${project.version}</version>
  727. </dependency>
  728. <dependency>
  729. <groupId>${project.groupId}</groupId>
  730. <artifactId>${service-name}-infrastructure</artifactId>
  731. <version>${project.version}</version>
  732. </dependency>
  733. <dependency>
  734. <groupId>${project.groupId}</groupId>
  735. <artifactId>platform-common</artifactId>
  736. <version>${project.version}</version>
  737. </dependency>
  738. </dependencies>
  739. <build>
  740. <plugins>
  741. <plugin>
  742. <groupId>org.springframework.boot</groupId>
  743. <artifactId>spring-boot-maven-plugin</artifactId>
  744. </plugin>
  745. </plugins>
  746. </build>
  747. """
  748. pom_content += "</project>\n"
  749. (module_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  750. # Service parent pom
  751. module_list = "\n".join(f" <module>{service_name}-{module}</module>" for module in service_modules)
  752. service_pom = f"""<?xml version="1.0" encoding="UTF-8"?>
  753. <project xmlns="http://maven.apache.org/POM/4.0.0"
  754. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  755. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  756. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  757. <modelVersion>4.0.0</modelVersion>
  758. <parent>
  759. <groupId>{group_id}</groupId>
  760. <artifactId>{artifact_id}</artifactId>
  761. <version>{version}</version>
  762. </parent>
  763. <artifactId>{service_name}</artifactId>
  764. <packaging>pom</packaging>
  765. <name>{service_name}</name>
  766. <description>{service_name.replace('-', ' ').title()} Microservice</description>
  767. <modules>
  768. {module_list}
  769. </modules>
  770. </project>
  771. """
  772. (service_dir / "pom.xml").write_text(service_pom, encoding="utf-8")
  773. def _create_gateway(self, project_path: Path, group_id: str, artifact_id: str, version: str, package_base: str):
  774. """Create gateway service"""
  775. gateway_dir = project_path / "gateway"
  776. gateway_dir.mkdir(parents=True, exist_ok=True)
  777. start_dir = gateway_dir / "gateway-start"
  778. start_dir.mkdir(parents=True, exist_ok=True)
  779. src_main_java = start_dir / "src" / "main" / "java" / package_base.replace(".", "/") / "gateway"
  780. src_main_java.mkdir(parents=True, exist_ok=True)
  781. app_class = src_main_java / "GatewayApplication.java"
  782. content = f"""package {package_base}.gateway;
  783. import org.springframework.boot.SpringApplication;
  784. import org.springframework.boot.autoconfigure.SpringBootApplication;
  785. /**
  786. * Gateway Application
  787. */
  788. @SpringBootApplication
  789. public class GatewayApplication {{
  790. public static void main(String[] args) {{
  791. SpringApplication.run(GatewayApplication.class, args);
  792. }}
  793. }}
  794. """
  795. app_class.write_text(content, encoding="utf-8")
  796. pom_content = f"""<?xml version="1.0" encoding="UTF-8"?>
  797. <project xmlns="http://maven.apache.org/POM/4.0.0"
  798. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  799. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
  800. http://maven.apache.org/xsd/maven-4.0.0.xsd">
  801. <modelVersion>4.0.0</modelVersion>
  802. <parent>
  803. <groupId>{group_id}</groupId>
  804. <artifactId>{artifact_id}</artifactId>
  805. <version>{version}</version>
  806. </parent>
  807. <artifactId>gateway</artifactId>
  808. <packaging>pom</packaging>
  809. <name>gateway</name>
  810. <description>API Gateway Service</description>
  811. <modules>
  812. <module>gateway-start</module>
  813. </modules>
  814. </project>
  815. """
  816. (gateway_dir / "pom.xml").write_text(pom_content, encoding="utf-8")
  817. def main():
  818. """Main entry point"""
  819. if len(sys.argv) < 2:
  820. print("Usage: init_project.py <project-type> [options]", file=sys.stderr)
  821. print("Project types: single-module, multi-module, microservices", file=sys.stderr)
  822. sys.exit(1)
  823. project_type = sys.argv[1]
  824. # Parse configuration from JSON or command line
  825. if len(sys.argv) >= 3:
  826. config = json.loads(sys.argv[2])
  827. else:
  828. # Default configuration
  829. config = {
  830. "groupId": "io.ddd4j.base",
  831. "artifactId": "ddd4j-project",
  832. "version": "1.0.0-SNAPSHOT",
  833. "parentVersion": "2023.0.x.20251205-SNAPSHOT",
  834. "packageBase": "io.ddd4j.project",
  835. "architecture": "ddd-classic"
  836. }
  837. initializer = DDDProjectInitializer()
  838. if project_type == "single-module":
  839. result = initializer.init_single_module(
  840. config["groupId"],
  841. config["artifactId"],
  842. config["version"],
  843. config["parentVersion"],
  844. config["packageBase"],
  845. config.get("architecture", "ddd-classic")
  846. )
  847. print(json.dumps({"status": "success", "path": result}))
  848. elif project_type == "multi-module":
  849. modules = config.get("modules", ["api"])
  850. result = initializer.init_multi_module(
  851. config["groupId"],
  852. config["artifactId"],
  853. config["version"],
  854. config["parentVersion"],
  855. config["packageBase"],
  856. modules,
  857. config.get("architecture", "ddd-classic")
  858. )
  859. print(json.dumps({"status": "success", "path": result}))
  860. elif project_type == "microservices":
  861. services = config.get("services", ["user-service", "order-service"])
  862. result = initializer.init_microservices(
  863. config["groupId"],
  864. config["artifactId"],
  865. config["version"],
  866. config["parentVersion"],
  867. config["packageBase"],
  868. services,
  869. config.get("architecture", "ddd-classic")
  870. )
  871. print(json.dumps({"status": "success", "path": result}))
  872. else:
  873. print(json.dumps({"status": "error", "message": f"Unknown project type: {project_type}"}), file=sys.stderr)
  874. sys.exit(1)
  875. if __name__ == "__main__":
  876. main()