22# pylint doesn't recognize abstract methods
33import logging
44import shutil
5+ from collections import namedtuple
56
67from rpdk .core .data_loaders import resource_stream
78from rpdk .core .exceptions import InternalError , SysExitRecommendedError
1011from rpdk .core .plugin_base import LanguagePlugin
1112
1213from .resolver import translate_type
13- from .utils import safe_reserved , validate_namespace
14+ from .utils import safe_reserved , validate_codegen_model , validate_namespace
1415
1516LOG = logging .getLogger (__name__ )
1617
1718OPERATIONS = ("Create" , "Read" , "Update" , "Delete" , "List" )
1819EXECUTABLE = "cfn"
20+ AWSCODEGEN = namedtuple ("AWSCODEGEN" , "default guided default_code guided_code" )
21+ CODEGEN = AWSCODEGEN ("default" , "guided_aws" , "1" , "2" )
22+
23+
24+ def logdebug (func : object ):
25+ def wrapper (* args , ** kwargs ):
26+ log_msg = func .__name__ if not func .__doc__ else func .__doc__
27+ entry_message = "{} started" .format (log_msg )
28+ LOG .debug (entry_message )
29+ if "entity" in kwargs :
30+ writing_message = "Writing {}" .format (kwargs ["entity" ])
31+ LOG .debug (writing_message )
32+ result = func (* args , ** kwargs )
33+ exit_message = "{} complete" .format (log_msg )
34+ LOG .debug (exit_message )
35+ return result
36+
37+ return wrapper
1938
2039
2140class JavaArchiveNotFoundError (SysExitRecommendedError ):
@@ -33,6 +52,7 @@ def __init__(self):
3352 self .env = self ._setup_jinja_env (
3453 trim_blocks = True , lstrip_blocks = True , keep_trailing_newline = True
3554 )
55+ self .codegen_template_path = None
3656 self .env .filters ["translate_type" ] = translate_type
3757 self .env .filters ["safe_reserved" ] = safe_reserved
3858 self .namespace = None
@@ -66,19 +86,61 @@ def _prompt_for_namespace(self, project):
6686 project .settings ["namespace" ] = self .namespace
6787 self .package_name = "." .join (self .namespace )
6888
69- def init (self , project ):
70- LOG .debug ("Init started" )
89+ @staticmethod
90+ def _prompt_for_codegen_model (project ):
91+ prompt = "Choose codegen model - 1 (default) or 2 (guided-aws): "
7192
72- self ._prompt_for_namespace (project )
93+ codegen_model = input_with_validation (
94+ prompt , validate_codegen_model (CODEGEN .default_code )
95+ )
7396
74- self . _init_settings ( project )
97+ project . settings [ "codegen_template_path" ] = CODEGEN . default
7598
76- # .gitignore
77- path = project .root / ".gitignore"
78- LOG .debug ("Writing .gitignore: %s" , path )
79- contents = resource_stream (__name__ , "data/java.gitignore" ).read ()
99+ if codegen_model == CODEGEN .guided_code :
100+ project .settings ["codegen_template_path" ] = CODEGEN .guided
101+
102+ def _get_template (self , project , stage , name ):
103+ return self .env .get_template (
104+ stage + "/" + project .settings ["codegen_template_path" ] + "/" + name
105+ )
106+
107+ @staticmethod
108+ def _is_aws_guided (project : object ) -> bool :
109+ return project .settings ["codegen_template_path" ] == CODEGEN .guided
110+
111+ @logdebug
112+ def _writing_component (
113+ self , project : object , src : str , entity : str , ** kwargs # noqa: C816
114+ ) -> None :
115+ """Writing module"""
116+
117+ stub_entity : str = kwargs .get ("stub_entity" )
118+ operation : str = kwargs .get ("operation" )
119+ pojo_name : str = kwargs .get ("pojo_name" )
120+ call_graph : str = kwargs .get ("call_graph" )
121+
122+ if not stub_entity :
123+ stub_entity = entity
124+
125+ template = self ._get_template (project , "init" , stub_entity )
126+ path = src / entity
127+ contents = template .render (
128+ package_name = self .package_name ,
129+ operation = operation ,
130+ pojo_name = pojo_name ,
131+ call_graph = call_graph ,
132+ )
80133 project .safewrite (path , contents )
81134
135+ @logdebug
136+ def init (self , project ):
137+ """Init"""
138+ self ._prompt_for_namespace (project )
139+
140+ self ._prompt_for_codegen_model (project )
141+
142+ self ._init_settings (project )
143+
82144 # maven folder structure
83145 src = (project .root / "src" / "main" / "java" ).joinpath (* self .namespace )
84146 LOG .debug ("Making source folder structure: %s" , src )
@@ -87,9 +149,26 @@ def init(self, project):
87149 LOG .debug ("Making test folder structure: %s" , tst )
88150 tst .mkdir (parents = True , exist_ok = True )
89151
152+ # initialize shared files
153+ self .init_shared (project , src , tst )
154+
155+ # write specialized generated files
156+ if self ._is_aws_guided (project ):
157+ self .init_guided_aws (project , src , tst )
158+
159+ @logdebug
160+ def init_shared (self , project , src , tst ):
161+ """Writing project configuration"""
162+ # .gitignore
163+ path = project .root / ".gitignore"
164+ LOG .debug ("Writing .gitignore: %s" , path )
165+ contents = resource_stream (__name__ , "data/java.gitignore" ).read ()
166+ project .safewrite (path , contents )
167+
168+ # pom.xml
90169 path = project .root / "pom.xml"
91170 LOG .debug ("Writing Maven POM: %s" , path )
92- template = self .env .get_template ("pom.xml" )
171+ template = self .env .get_template ("init/shared/ pom.xml" )
93172 artifact_id = "{}-handler" .format (project .hypenated_name )
94173 contents = template .render (
95174 group_id = self .package_name ,
@@ -100,17 +179,35 @@ def init(self, project):
100179 )
101180 project .safewrite (path , contents )
102181
182+ # lombok.config
103183 path = project .root / "lombok.config"
104184 LOG .debug ("Writing Lombok Config: %s" , path )
105- template = self .env .get_template ("lombok.config" )
185+ template = self .env .get_template ("init/shared/ lombok.config" )
106186 contents = template .render ()
107187 project .safewrite (path , contents )
108188
189+ LOG .debug ("Writing callback context" )
190+ template = self .env .get_template ("init/shared/CallbackContext.java" )
191+ path = src / "CallbackContext.java"
192+ contents = template .render (package_name = self .package_name )
193+ project .safewrite (path , contents )
194+
195+ path = src / "Configuration.java"
196+ LOG .debug ("Writing configuration: %s" , path )
197+ template = self .env .get_template ("init/shared/StubConfiguration.java" )
198+ contents = template .render (
199+ package_name = self .package_name ,
200+ schema_file_name = project .schema_filename ,
201+ pojo_name = "ResourceModel" ,
202+ )
203+ project .safewrite (path , contents )
204+
109205 # CloudFormation/SAM template for handler lambda
110206 path = project .root / "template.yml"
111207 LOG .debug ("Writing SAM template: %s" , path )
112- template = self .env .get_template ("template.yml" )
113-
208+ template = self .env .get_template (
209+ "template.yml"
210+ ) # this template is in the CLI itself
114211 handler_params = {
115212 "Handler" : project .entrypoint ,
116213 "Runtime" : project .runtime ,
@@ -128,69 +225,59 @@ def init(self, project):
128225 )
129226 project .safewrite (path , contents )
130227
131- LOG .debug ("Writing handlers and tests" )
132- self .init_handlers (project , src , tst )
133-
134- LOG .debug ("Writing callback context" )
135- template = self .env .get_template ("CallbackContext.java" )
136- path = src / "CallbackContext.java"
137- contents = template .render (package_name = self .package_name )
138- project .safewrite (path , contents )
139-
140- path = src / "Configuration.java"
141- LOG .debug ("Writing configuration: %s" , path )
142- template = self .env .get_template ("StubConfiguration.java" )
143- contents = template .render (
144- package_name = self .package_name ,
145- schema_file_name = project .schema_filename ,
146- pojo_name = "ResourceModel" ,
147- )
148- project .safewrite (path , contents )
149-
150- # generated docs
228+ # generate docs
151229 path = project .root / "README.md"
152230 LOG .debug ("Writing README: %s" , path )
153- template = self .env .get_template ("README.md" )
231+ template = self .env .get_template ("init/shared/ README.md" )
154232 contents = template .render (
155233 type_name = project .type_name ,
156234 schema_path = project .schema_path ,
157235 executable = EXECUTABLE ,
158236 )
159237 project .safewrite (path , contents )
160238
161- LOG .debug ("Init complete" )
239+ self .init_handlers (project , src , tst )
240+
241+ @logdebug
242+ def init_guided_aws (self , project , src , tst ):
243+ """Writing supporting modules"""
244+ self ._writing_component (project , src , entity = "Translator.java" )
245+ self ._writing_component (project , src , entity = "ClientBuilder.java" )
246+ self ._writing_component (project , src , entity = "BaseHandlerStd.java" )
247+ self ._writing_component (project , tst , entity = "AbstractTestBase.java" )
162248
249+ @logdebug
163250 def init_handlers (self , project , src , tst ):
164- LOG .debug ("Writing stub handlers" )
251+ """Writing stub handlers and tests"""
252+ pojo_name = "ResourceModel"
165253 for operation in OPERATIONS :
166- if operation == "List" :
167- template = self .env .get_template ("StubListHandler.java" )
168- else :
169- template = self .env .get_template ("StubHandler.java" )
170- path = src / "{}Handler.java" .format (operation )
171- LOG .debug ("%s handler: %s" , operation , path )
172- contents = template .render (
173- package_name = self .package_name ,
174- operation = operation ,
175- pojo_name = "ResourceModel" ,
176- )
177- project .safewrite (path , contents )
254+ entity = "{}Handler.java" .format (operation )
255+ entity_test = "{}HandlerTest.java" .format (operation )
178256
179- LOG . debug ( "Writing stub tests" )
180- for operation in OPERATIONS :
181- if operation == "List" :
182- template = self . env . get_template ( "StubListHandlerTest .java")
183- else :
184- template = self . env . get_template ( "StubHandlerTest.java" )
257+ stub_entity = "Stub{}Handler.java" . format (
258+ operation if operation == "List" or self . _is_aws_guided ( project ) else ""
259+ )
260+ stub_entity_test = "Stub{}HandlerTest .java". format (
261+ operation if operation == "List" else ""
262+ )
185263
186- path = tst / "{}HandlerTest.java" .format (operation )
187- LOG .debug ("%s handler: %s" , operation , path )
188- contents = template .render (
189- package_name = self .package_name ,
264+ self ._writing_component (
265+ project ,
266+ src ,
267+ entity = entity ,
268+ stub_entity = stub_entity ,
190269 operation = operation ,
191- pojo_name = "ResourceModel" ,
270+ pojo_name = pojo_name ,
271+ call_graph = project .type_name .replace ("::" , "-" ),
272+ )
273+ self ._writing_component (
274+ project ,
275+ tst ,
276+ entity = entity_test ,
277+ stub_entity = stub_entity_test ,
278+ operation = operation ,
279+ pojo_name = pojo_name ,
192280 )
193- project .safewrite (path , contents )
194281
195282 def _init_settings (self , project ):
196283 project .runtime = self .RUNTIME
@@ -205,8 +292,9 @@ def _get_generated_root(project):
205292 def _get_generated_tests_root (project ):
206293 return project .root / "target" / "generated-test-sources" / "rpdk"
207294
295+ @logdebug
208296 def generate (self , project ):
209- LOG . debug ( " Generate started" )
297+ """ Generate"""
210298
211299 self ._namespace_from_project (project )
212300
@@ -230,7 +318,7 @@ def generate(self, project):
230318 # write generated handler integration with LambdaWrapper
231319 path = src / "HandlerWrapper.java"
232320 LOG .debug ("Writing handler wrapper: %s" , path )
233- template = self .env .get_template ("HandlerWrapper.java" )
321+ template = self .env .get_template ("generate/ HandlerWrapper.java" )
234322 contents = template .render (
235323 package_name = self .package_name ,
236324 operations = project .schema .get ("handlers" , {}).keys (),
@@ -240,7 +328,7 @@ def generate(self, project):
240328
241329 path = src / "BaseConfiguration.java"
242330 LOG .debug ("Writing base configuration: %s" , path )
243- template = self .env .get_template ("BaseConfiguration.java" )
331+ template = self .env .get_template ("generate/ BaseConfiguration.java" )
244332 contents = template .render (
245333 package_name = self .package_name ,
246334 schema_file_name = project .schema_filename ,
@@ -250,7 +338,7 @@ def generate(self, project):
250338
251339 path = src / "BaseHandler.java"
252340 LOG .debug ("Writing base handler: %s" , path )
253- template = self .env .get_template ("BaseHandler.java" )
341+ template = self .env .get_template ("generate/ BaseHandler.java" )
254342 contents = template .render (
255343 package_name = self .package_name ,
256344 operations = OPERATIONS ,
@@ -263,8 +351,8 @@ def generate(self, project):
263351
264352 LOG .debug ("Writing %d POJOs" , len (models ))
265353
266- base_template = self .env .get_template ("ResourceModel.java" )
267- pojo_template = self .env .get_template ("POJO.java" )
354+ base_template = self .env .get_template ("generate/ ResourceModel.java" )
355+ pojo_template = self .env .get_template ("generate/ POJO.java" )
268356
269357 for model_name , properties in models .items ():
270358 path = src / "{}.java" .format (model_name )
@@ -289,8 +377,6 @@ def generate(self, project):
289377 )
290378 project .overwrite (path , contents )
291379
292- LOG .debug ("Generate complete" )
293-
294380 @staticmethod
295381 def _find_jar (project ):
296382 jar_glob = list (
@@ -313,8 +399,9 @@ def _find_jar(project):
313399
314400 return jar_glob [0 ]
315401
402+ @logdebug
316403 def package (self , project , zip_file ):
317- LOG . info ( " Packaging Java project")
404+ """ Packaging Java project"""
318405
319406 def write_with_relative_path (path ):
320407 relative = path .relative_to (project .root )
0 commit comments