From 25939ab9cc129c3134802e9e8a28fabc483cbdf5 Mon Sep 17 00:00:00 2001 From: ThomasF Date: Tue, 20 Mar 2012 01:42:26 +0100 Subject: [PATCH 1/3] enable detection of legacy primary key fields --- .../forge/scaffold/faces/FacesScaffold.java | 359 ++++++++---------- .../metawidget/config/ForgeConfigReader.java | 11 +- .../ForgeInspectionResultConstants.java | 10 + .../metawidget/inspector/ForgeInspector.java | 115 ++++-- .../inspector/ForgeInspectorConfig.java | 65 ++++ .../ForgeInspectionResultProcessor.java | 87 +++++ .../widgetbuilder/EntityWidgetBuilder.java | 27 +- .../QueryByExampleWidgetBuilder.java | 9 +- .../scaffold/faces/util/AnnotationLookup.java | 107 ++++++ .../resources/scaffold/faces/BackingBean.jv | 10 +- .../scaffold/faces/metawidget-bean.xml | 20 +- .../scaffold/faces/metawidget-entity.xml | 18 +- .../scaffold/faces/metawidget-qbe.xml | 20 +- .../scaffold/faces/metawidget-search.xml | 20 +- .../faces/PrimaryKeyFacesScaffoldTest.java | 242 ++++++++++++ .../inspector/ForgeInspectorTest.java | 2 +- 16 files changed, 863 insertions(+), 259 deletions(-) create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java create mode 100644 scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java index 4649528cee..88d1852a2c 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java @@ -33,14 +33,12 @@ import javax.enterprise.event.Event; import javax.inject.Inject; import javax.persistence.CascadeType; +import javax.persistence.Id; import javax.persistence.OneToOne; import org.jboss.forge.env.Configuration; import org.jboss.forge.parser.JavaParser; -import org.jboss.forge.parser.java.Annotation; -import org.jboss.forge.parser.java.Field; -import org.jboss.forge.parser.java.JavaClass; -import org.jboss.forge.parser.java.Method; +import org.jboss.forge.parser.java.*; import org.jboss.forge.parser.xml.Node; import org.jboss.forge.parser.xml.XMLParser; import org.jboss.forge.project.Project; @@ -94,33 +92,30 @@ import org.w3c.dom.NamedNodeMap; /** - * Facet to generate a Java Server Faces UI. - *

- * This facet utilizes Metawidget internally. This enables the use of the Metawidget - * SPI (pluggable WidgetBuilders, Layouts etc) for customizing the generated User Interface. For more information on - * writing Metawidget plugins, see the Metawidget documentation. - *

- * This Facet does not require Metawidget to be in the final project. + * Facet to generate a Java Server Faces UI.

This facet utilizes Metawidget internally. This enables the use + * of the Metawidget SPI (pluggable WidgetBuilders, Layouts etc) for customizing + * the generated User Interface. For more information on writing Metawidget + * plugins, see the Metawidget + * documentation.

This Facet does not require Metawidget to be + * in the final project. * * @author Lincoln Baxter, III * @author Richard Kennard */ - @Alias("faces") -@RequiresFacet({ WebResourceFacet.class, - DependencyFacet.class, - PersistenceFacet.class, - EJBFacet.class, - CDIFacet.class, - FacesFacet.class }) -public class FacesScaffold extends BaseFacet implements ScaffoldProvider -{ +@RequiresFacet({WebResourceFacet.class, + DependencyFacet.class, + PersistenceFacet.class, + EJBFacet.class, + CDIFacet.class, + FacesFacet.class}) +public class FacesScaffold extends BaseFacet implements ScaffoldProvider { // // Private statics // private static final String XMLNS_PREFIX = "xmlns:"; - private static final String BACKING_BEAN_TEMPLATE = "scaffold/faces/BackingBean.jv"; private static final String VIEW_UTILS_TEMPLATE = "scaffold/faces/ViewUtils.jv"; private static final String TAGLIB_TEMPLATE = "scaffold/faces/forge.taglib.xml"; @@ -128,44 +123,34 @@ public class FacesScaffold extends BaseFacet implements ScaffoldProvider private static final String CREATE_TEMPLATE = "scaffold/faces/create.xhtml"; private static final String SEARCH_TEMPLATE = "scaffold/faces/search.xhtml"; private static final String NAVIGATION_TEMPLATE = "scaffold/faces/page.xhtml"; - private static final String ERROR_TEMPLATE = "scaffold/faces/error.xhtml"; private static final String INDEX_TEMPLATE = "scaffold/faces/index.xhtml"; - private final Dependency richfaces3UI = DependencyBuilder.create("org.richfaces.ui:richfaces-ui"); private final Dependency richfaces3Impl = DependencyBuilder.create("org.richfaces.framework:richfaces-impl"); private final Dependency richfaces4UI = DependencyBuilder.create("org.richfaces.ui:richfaces-components-ui"); private final Dependency richfaces4Impl = DependencyBuilder.create("org.richfaces.core:richfaces-core-impl"); - // // Protected members (nothing is private, to help subclassing) // - protected CompiledTemplateResource backingBeanTemplate; protected int backingBeanTemplateQbeMetawidgetIndent; - protected CompiledTemplateResource viewUtilsTemplate; protected CompiledTemplateResource taglibTemplate; protected CompiledTemplateResource viewTemplate; protected Map viewTemplateNamespaces; protected int viewTemplateEntityMetawidgetIndent; - protected CompiledTemplateResource createTemplate; protected Map createTemplateNamespaces; protected int createTemplateEntityMetawidgetIndent; - protected CompiledTemplateResource searchTemplate; protected Map searchTemplateNamespaces; protected int searchTemplateSearchMetawidgetIndent; protected int searchTemplateBeanMetawidgetIndent; - protected CompiledTemplateResource navigationTemplate; protected int navigationTemplateIndent; - protected CompiledTemplateResource errorTemplate; protected CompiledTemplateResource indexTemplate; protected TemplateResolver resolver; - protected final ShellPrompt prompt; protected final TemplateCompiler compiler; protected final Event install; @@ -173,13 +158,15 @@ public class FacesScaffold extends BaseFacet implements ScaffoldProvider protected StaticHtmlMetawidget searchMetawidget; protected StaticHtmlMetawidget beanMetawidget; protected StaticJavaMetawidget qbeMetawidget; +// @Inject AnnotationLookup annotationLookup; +// @Inject RelationResolverWidgetProcessor relationResolver; +// @Inject RelationResolverWidgetProcessorConfig relationResolverConfig; private Configuration config; // // Constructor // - @Inject public FacesScaffold(final Configuration config, final ShellPrompt prompt, @@ -193,8 +180,7 @@ public FacesScaffold(final Configuration config, this.resolver = new ClassLoaderTemplateResolver(FacesScaffold.class.getClassLoader()); - if (this.compiler != null) - { + if (this.compiler != null) { this.compiler.getTemplateResolverFactory().addResolver(this.resolver); } } @@ -202,7 +188,6 @@ public FacesScaffold(final Configuration config, // // Public methods // - @Override public List> setup(String targetDir, final Resource template, final boolean overwrite) { @@ -213,16 +198,14 @@ public List> setup(String targetDir, final Resource template, fin } /** - * Overridden to setup the Metawidgets. - *

- * Metawidgets must be configured per project and per Forge invocation. It is not sufficient to simply - * configure them in setup because the user may restart Forge and not run scaffold setup a - * second time. + * Overridden to setup the Metawidgets.

Metawidgets must be configured + * per project and per Forge invocation. It is not sufficient to + * simply configure them in + * setup because the user may restart Forge and not run + * scaffold setup a second time. */ - @Override - public void setProject(Project project) - { + public void setProject(Project project) { super.setProject(project); ForgeConfigReader configReader = new ForgeConfigReader(this.config, this.project); @@ -242,6 +225,7 @@ public void setProject(Project project) this.qbeMetawidget = new StaticJavaMetawidget(); this.qbeMetawidget.setConfigReader(configReader); this.qbeMetawidget.setConfig("scaffold/faces/metawidget-qbe.xml"); + } @Override @@ -256,8 +240,7 @@ public List> generateFromEntity(String targetDir, final Resource // Track the list of resources generated List> result = new ArrayList>(); - try - { + try { JavaSourceFacet java = this.project.getFacet(JavaSourceFacet.class); WebResourceFacet web = this.project.getFacet(WebResourceFacet.class); @@ -266,20 +249,22 @@ public List> generateFromEntity(String targetDir, final Resource context.put("entity", entity); String ccEntity = StringUtils.decapitalize(entity.getName()); context.put("ccEntity", ccEntity); + setPrimaryKeyMetaData(context, entity); // Prepare qbeMetawidget this.qbeMetawidget.setPath(entity.getQualifiedName()); StringWriter stringWriter = new StringWriter(); this.qbeMetawidget.write(stringWriter, this.backingBeanTemplateQbeMetawidgetIndent); + context.put("qbeMetawidget", stringWriter.toString().trim()); context.put("qbeMetawidgetImports", - CollectionUtils.toString(this.qbeMetawidget.getImports(), ";\r\nimport ", true, false)); + CollectionUtils.toString(this.qbeMetawidget.getImports(), ";\r\nimport ", true, false)); // Create the Backing Bean for this entity JavaClass viewBean = JavaParser.parse(JavaClass.class, this.backingBeanTemplate.render(context)); viewBean.setPackage(java.getBasePackage() + ".view"); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, java.getJavaResource(viewBean), viewBean.toString(), - overwrite)); + overwrite)); // Set new context for view generation context = getTemplateContext(template); @@ -287,6 +272,7 @@ public List> generateFromEntity(String targetDir, final Resource context.put("beanName", beanName); context.put("ccEntity", ccEntity); context.put("entityName", StringUtils.uncamelCase(entity.getName())); + setPrimaryKeyMetaData(context, entity); // Prepare entityMetawidget this.entityMetawidget.setValue(StaticFacesUtils.wrapExpression(beanName + "." + ccEntity)); @@ -316,7 +302,7 @@ public List> generateFromEntity(String targetDir, final Resource this.beanMetawidget.setValue(StaticFacesUtils.wrapExpression(beanName + ".pageItems")); this.beanMetawidget.setPath(viewBean.getQualifiedName() + "/pageItems"); writeSearchAndBeanMetawidget(context, this.searchTemplateSearchMetawidgetIndent, - this.searchTemplateBeanMetawidgetIndent, this.searchTemplateNamespaces); + this.searchTemplateBeanMetawidgetIndent, this.searchTemplateNamespaces); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource(targetDir + "/" + ccEntity + "/search.xhtml"), @@ -329,19 +315,17 @@ public List> generateFromEntity(String targetDir, final Resource JavaClass viewUtils = JavaParser.parse(JavaClass.class, this.viewUtilsTemplate.render(context)); viewUtils.setPackage(viewBean.getPackage()); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, java.getJavaResource(viewUtils), viewUtils.toString(), - true)); + true)); context.put("viewPackage", viewBean.getPackage()); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, - web.getWebResource("WEB-INF/classes/META-INF/forge.taglib.xml"), - this.taglibTemplate.render(context), true)); + web.getWebResource("WEB-INF/classes/META-INF/forge.taglib.xml"), + this.taglibTemplate.render(context), true)); createInitializers(entity); this.project.getFacet(JavaSourceFacet.class).saveJavaSource(entity); - } - catch (Exception e) - { + } catch (Exception e) { throw new RuntimeException("Error generating default scaffolding: " + e.getMessage(), e); } return result; @@ -349,21 +333,18 @@ public List> generateFromEntity(String targetDir, final Resource @Override @SuppressWarnings("unchecked") - public boolean install() - { + public boolean install() { if (!(this.project.hasFacet(WebResourceFacet.class) && this.project.hasFacet(PersistenceFacet.class) - && this.project.hasFacet(CDIFacet.class) && this.project.hasFacet(FacesFacet.class))) - { + && this.project.hasFacet(CDIFacet.class) && this.project.hasFacet(FacesFacet.class))) { this.install.fire(new InstallFacets(WebResourceFacet.class, PersistenceFacet.class, CDIFacet.class, - FacesFacet.class)); + FacesFacet.class)); } return true; } @Override - public boolean isInstalled() - { + public boolean isInstalled() { return true; } @@ -388,39 +369,39 @@ public List> generateIndex(String targetDir, final Resource templ this.indexTemplate.render(context), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("error.xhtml"), - this.errorTemplate.render(context), overwrite)); + this.errorTemplate.render(context), overwrite)); // Static resources result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/add.png"), - getClass().getResourceAsStream("/scaffold/faces/add.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/add.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/background.gif"), - getClass().getResourceAsStream("/scaffold/faces/background.gif"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/background.gif"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/false.png"), - getClass().getResourceAsStream("/scaffold/faces/false.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/false.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/favicon.ico"), - getClass().getResourceAsStream("/scaffold/faces/favicon.ico"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/favicon.ico"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/forge-logo.png"), - getClass().getResourceAsStream("/scaffold/faces/forge-logo.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/forge-logo.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/forge-style.css"), - getClass().getResourceAsStream("/scaffold/faces/forge-style.css"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/forge-style.css"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/jboss-community.png"), - getClass().getResourceAsStream("/scaffold/faces/jboss-community.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/jboss-community.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/remove.png"), - getClass().getResourceAsStream("/scaffold/faces/remove.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/remove.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/search.png"), - getClass().getResourceAsStream("/scaffold/faces/search.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/search.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/true.png"), - getClass().getResourceAsStream("/scaffold/faces/true.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/true.png"), overwrite)); return result; } @@ -432,14 +413,12 @@ public List> getGeneratedResources(String targetDir) } @Override - public AccessStrategy getAccessStrategy() - { + public AccessStrategy getAccessStrategy() { return new FacesAccessStrategy(this.project); } @Override - public TemplateStrategy getTemplateStrategy() - { + public TemplateStrategy getTemplateStrategy() { return new FacesTemplateStrategy(this.project); } @@ -448,14 +427,13 @@ public List> generateTemplates(String targetDir, final boolean overw { List> result = new ArrayList>(); - try - { + try { WebResourceFacet web = this.project.getFacet(WebResourceFacet.class); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, - web.getWebResource("/resources/scaffold/paginator.xhtml"), - getClass().getResourceAsStream("/scaffold/faces/paginator.xhtml"), - overwrite)); + web.getWebResource("/resources/scaffold/paginator.xhtml"), + getClass().getResourceAsStream("/scaffold/faces/paginator.xhtml"), + overwrite)); result.add(generateNavigation(targetDir, overwrite)); } @@ -470,91 +448,72 @@ public List> generateTemplates(String targetDir, final boolean overw // // Protected methods (nothing is private, to help subclassing) // - - protected void loadTemplates() - { - if (this.backingBeanTemplate == null) - { + protected void loadTemplates() { + if (this.backingBeanTemplate == null) { this.backingBeanTemplate = this.compiler.compile(BACKING_BEAN_TEMPLATE); String template = Streams.toString(this.backingBeanTemplate.getSourceTemplateResource().getInputStream()); this.backingBeanTemplateQbeMetawidgetIndent = parseIndent(template, "@{qbeMetawidget}"); } - if (this.viewUtilsTemplate == null) - { + if (this.viewUtilsTemplate == null) { this.viewUtilsTemplate = this.compiler.compile(VIEW_UTILS_TEMPLATE); } - if (this.taglibTemplate == null) - { + if (this.taglibTemplate == null) { this.taglibTemplate = this.compiler.compile(TAGLIB_TEMPLATE); } - if (this.viewTemplate == null) - { + if (this.viewTemplate == null) { this.viewTemplate = this.compiler.compile(VIEW_TEMPLATE); String template = Streams.toString(this.viewTemplate.getSourceTemplateResource().getInputStream()); this.viewTemplateNamespaces = parseNamespaces(template); this.viewTemplateEntityMetawidgetIndent = parseIndent(template, "@{metawidget}"); } - if (this.createTemplate == null) - { + if (this.createTemplate == null) { this.createTemplate = this.compiler.compile(CREATE_TEMPLATE); String template = Streams.toString(this.createTemplate.getSourceTemplateResource().getInputStream()); this.createTemplateNamespaces = parseNamespaces(template); this.createTemplateEntityMetawidgetIndent = parseIndent(template, "@{metawidget}"); } - if (this.searchTemplate == null) - { + if (this.searchTemplate == null) { this.searchTemplate = this.compiler.compile(SEARCH_TEMPLATE); String template = Streams.toString(this.searchTemplate.getSourceTemplateResource().getInputStream()); this.searchTemplateNamespaces = parseNamespaces(template); this.searchTemplateSearchMetawidgetIndent = parseIndent(template, "@{searchMetawidget}"); this.searchTemplateBeanMetawidgetIndent = parseIndent(template, "@{beanMetawidget}"); } - if (this.navigationTemplate == null) - { + if (this.navigationTemplate == null) { this.navigationTemplate = this.compiler.compile(NAVIGATION_TEMPLATE); String template = Streams.toString(this.navigationTemplate.getSourceTemplateResource().getInputStream()); this.navigationTemplateIndent = parseIndent(template, "@{navigation}"); } - if (this.errorTemplate == null) - { + if (this.errorTemplate == null) { this.errorTemplate = this.compiler.compile(ERROR_TEMPLATE); } - if (this.indexTemplate == null) - { + if (this.indexTemplate == null) { this.indexTemplate = this.compiler.compile(INDEX_TEMPLATE); } } - protected void setupRichFaces() - { + protected void setupRichFaces() { if ((this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3UI) - && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3Impl)) - || (this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4UI) - && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4Impl))) - { - this.entityMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.entityMetawidget - .getWidgetBuilder())); + && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3Impl)) + || (this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4UI) + && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4Impl))) { + this.entityMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.entityMetawidget.getWidgetBuilder())); - this.searchMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.searchMetawidget - .getWidgetBuilder())); + this.searchMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.searchMetawidget.getWidgetBuilder())); - this.beanMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.beanMetawidget - .getWidgetBuilder())); + this.beanMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.beanMetawidget.getWidgetBuilder())); } } /** - * Locates a ReadOnlyWidgetBuilder in the list of WidgetBuilders, and inserts a - * RichFacesWidgetBuilder after it (unless there's a RichFacesWidgetBuilder in there - * already). + * Locates a + * ReadOnlyWidgetBuilder in the list of WidgetBuilders, and + * inserts a + * RichFacesWidgetBuilder after it (unless there's a + * RichFacesWidgetBuilder in there already). */ - protected CompositeWidgetBuilder insertRichFacesWidgetBuilder( - final CompositeWidgetBuilder compositeWidgetBuilder) - { + final CompositeWidgetBuilder compositeWidgetBuilder) { // Get the current WidgetBuilders... WidgetBuilder[] existingWidgetBuilders = compositeWidgetBuilder.getWidgetBuilders(); @@ -563,19 +522,16 @@ protected CompositeWidgetBuilder ins int addAt = 0; - for (int loop = 0; loop < existingWidgetBuilders.length; loop++) - { + for (int loop = 0; loop < existingWidgetBuilders.length; loop++) { // ...(abort if there's already a RichFacesWidgetBuilder)... // Use an Object loop variable here to avoid a nasty Java/Generics compiler bug Object widgetBuilder = existingWidgetBuilders[loop]; - if (widgetBuilder instanceof RichFacesWidgetBuilder) - { + if (widgetBuilder instanceof RichFacesWidgetBuilder) { return compositeWidgetBuilder; } - if (widgetBuilder instanceof ReadOnlyWidgetBuilder) - { + if (widgetBuilder instanceof ReadOnlyWidgetBuilder) { addAt = loop + 1; } } @@ -583,55 +539,41 @@ protected CompositeWidgetBuilder ins // ...and insert our RichFacesWidgetBuilder just after it @SuppressWarnings("unchecked") - WidgetBuilder[] newWidgetBuilders = (WidgetBuilder[]) ArrayUtils - .addAt(existingWidgetBuilders, addAt, - new RichFacesWidgetBuilder()); + WidgetBuilder[] newWidgetBuilders = (WidgetBuilder[]) ArrayUtils.addAt(existingWidgetBuilders, addAt, + new RichFacesWidgetBuilder()); return new CompositeWidgetBuilder( - new CompositeWidgetBuilderConfig() - .setWidgetBuilders(newWidgetBuilders)); + new CompositeWidgetBuilderConfig().setWidgetBuilders(newWidgetBuilders)); } - protected void createInitializers(final JavaClass entity) - { - for (Field field : entity.getFields()) - { - if (field.hasAnnotation(OneToOne.class)) - { + protected void createInitializers(final JavaClass entity) { + for (Field field : entity.getFields()) { + if (field.hasAnnotation(OneToOne.class)) { Annotation oneToOne = field.getAnnotation(OneToOne.class); - if (oneToOne.getStringValue("mappedBy") == null) - { + if (oneToOne.getStringValue("mappedBy") == null) { oneToOne.setEnumValue("cascade", CascadeType.ALL); } String methodName = "new" + field.getTypeInspector().getName(); - if (!entity.hasMethodSignature(methodName)) - { - entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic() - .setBody("this." + field.getName() + " = new " + field.getType() + "();"); + if (!entity.hasMethodSignature(methodName)) { + entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic().setBody("this." + field.getName() + " = new " + field.getType() + "();"); } } } - for (Method method : entity.getMethods()) - { - if (method.hasAnnotation(OneToOne.class)) - { + for (Method method : entity.getMethods()) { + if (method.hasAnnotation(OneToOne.class)) { Annotation oneToOne = method.getAnnotation(OneToOne.class); - if (oneToOne.getStringValue("mappedBy") == null) - { + if (oneToOne.getStringValue("mappedBy") == null) { oneToOne.setEnumValue("cascade", CascadeType.ALL); } String methodName = "new" + method.getReturnTypeInspector().getName(); - if (!entity.hasMethodSignature(methodName)) - { - entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic() - .setBody("this." + method.getName() + " = new " + method.getReturnType() + "();"); + if (!entity.hasMethodSignature(methodName)) { + entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic().setBody("this." + method.getName() + " = new " + method.getReturnType() + "();"); } } } } - protected HashMap getTemplateContext(final Resource template) - { + protected HashMap getTemplateContext(final Resource template) { HashMap context; context = new HashMap(); context.put("template", template); @@ -639,8 +581,7 @@ protected HashMap getTemplateContext(final Resource template) return context; } - protected void setupWebXML() - { + protected void setupWebXML() { ServletFacet servlet = this.project.getFacet(ServletFacet.class); Node webXML = removeConflictingErrorPages(servlet); @@ -658,20 +599,16 @@ protected void setupWebXML() servlet.saveConfig(servletConfig); } - protected Node removeConflictingErrorPages(final ServletFacet servlet) - { + protected Node removeConflictingErrorPages(final ServletFacet servlet) { Node webXML = XMLParser.parse(servlet.getConfigFile().getResourceInputStream()); Node root = webXML.getRoot(); List errorPages = root.get("error-page"); - for (String code : Arrays.asList("404", "500")) - { - for (Node errorPage : errorPages) - { + for (String code : Arrays.asList("404", "500")) { + for (Node errorPage : errorPages) { if (code.equals(errorPage.getSingle("error-code").getText()) - && this.prompt.promptBoolean("Your web.xml already contains an error page for " + code - + " status codes, replace it?")) - { + && this.prompt.promptBoolean("Your web.xml already contains an error page for " + code + + " status codes, replace it?")) { root.removeChild(errorPage); } } @@ -705,37 +642,32 @@ protected Resource generateNavigation(final String targetDir, final boolean o Map context = CollectionUtils.newHashMap(); context.put("navigation", writer.toString().trim()); - if (this.navigationTemplate == null) - { + if (this.navigationTemplate == null) { loadTemplates(); } - return ScaffoldUtil.createOrOverwrite(this.prompt, (FileResource) getTemplateStrategy() - .getDefaultTemplate(), - this.navigationTemplate.render(context), - overwrite); + return ScaffoldUtil.createOrOverwrite(this.prompt, (FileResource) getTemplateStrategy().getDefaultTemplate(), + this.navigationTemplate.render(context), + overwrite); } /** - * Parses the given XML and determines what namespaces it already declares. These are later removed from the list of - * namespaces that Metawidget introduces. + * Parses the given XML and determines what namespaces it already declares. + * These are later removed from the list of namespaces that Metawidget + * introduces. */ - - protected Map parseNamespaces(final String template) - { + protected Map parseNamespaces(final String template) { Map namespaces = CollectionUtils.newHashMap(); Document document = XmlUtils.documentFromString(template); Element element = document.getDocumentElement(); NamedNodeMap attributes = element.getAttributes(); - for (int loop = 0, length = attributes.getLength(); loop < length; loop++) - { + for (int loop = 0, length = attributes.getLength(); loop < length; loop++) { org.w3c.dom.Node node = attributes.item(loop); String nodeName = node.getNodeName(); int indexOf = nodeName.indexOf(XMLNS_PREFIX); - if (indexOf == -1) - { + if (indexOf == -1) { continue; } @@ -746,18 +678,15 @@ protected Map parseNamespaces(final String template) } /** - * Parses the given XML and determines the indent of the given String namespaces that Metawidget introduces. + * Parses the given XML and determines the indent of the given String + * namespaces that Metawidget introduces. */ - - protected int parseIndent(final String template, final String indentOf) - { + protected int parseIndent(final String template, final String indentOf) { int indent = 0; int indexOf = template.indexOf(indentOf); - while ((indexOf >= 0) && (template.charAt(indexOf) != '\n')) - { - if (template.charAt(indexOf) == '\t') - { + while ((indexOf >= 0) && (template.charAt(indexOf) != '\n')) { + if (template.charAt(indexOf) == '\t') { indent++; } @@ -770,10 +699,8 @@ protected int parseIndent(final String template, final String indentOf) /** * Writes the entity Metawidget and its namespaces into the given context. */ - protected void writeEntityMetawidget(final Map context, final int entityMetawidgetIndent, - final Map existingNamespaces) - { + final Map existingNamespaces) { StringWriter stringWriter = new StringWriter(); this.entityMetawidget.write(stringWriter, entityMetawidgetIndent); context.put("metawidget", stringWriter.toString().trim()); @@ -784,13 +711,12 @@ protected void writeEntityMetawidget(final Map context, final in } /** - * Writes the search Metawidget, the bean Metawidget and their namespaces into the given context. + * Writes the search Metawidget, the bean Metawidget and their namespaces + * into the given context. */ - protected void writeSearchAndBeanMetawidget(final Map context, final int searchMetawidgetIndent, - final int beanMetawidgetIndent, - final Map existingNamespaces) - { + final int beanMetawidgetIndent, + final Map existingNamespaces) { StringWriter stringWriter = new StringWriter(); this.searchMetawidget.write(stringWriter, searchMetawidgetIndent); context.put("searchMetawidget", stringWriter.toString().trim()); @@ -805,12 +731,10 @@ protected void writeSearchAndBeanMetawidget(final Map context, f context.put("metawidgetNamespaces", namespacesToString(namespaces)); } - protected String namespacesToString(final Map namespaces) - { + protected String namespacesToString(final Map namespaces) { StringBuilder builder = new StringBuilder(); - for (Map.Entry entry : namespaces.entrySet()) - { + for (Map.Entry entry : namespaces.entrySet()) { // At the start, break out of the current quote. Field must be in quotes so that we're valid XML builder.append("\"\r\n\txmlns:"); @@ -821,4 +745,31 @@ protected String namespacesToString(final Map namespaces) return builder.toString(); } + + private void setPrimaryKeyMetaData(Map context, final JavaClass entity) { + String pkName = "id"; + String pkType = "Long"; + for (Member m : entity.getMembers()) { + if (m.hasAnnotation(Id.class)) { + if (m instanceof Field) { + Field field = (Field) m; + pkName = field.getName(); + pkType = field.getType(); + break; + } else if (m instanceof Member) { + Method method = (Method) m; + pkName = method.getName().substring(3); + if (method.getName().startsWith("get")) { + pkType = method.getReturnType(); + } else { + pkType = ((Parameter) method.getParameters().get(0)).getType(); + } + break; + } + } + } + context.put("primaryKey", pkName); + context.put("primaryKeyCC", StringUtils.capitalize(pkName)); + context.put("primaryKeyType", pkType); + } } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java index 021b410434..5dba48d9ab 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java @@ -23,6 +23,7 @@ import org.jboss.forge.env.Configuration; import org.jboss.forge.project.Project; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; import org.metawidget.config.impl.BaseConfigReader; /** @@ -42,12 +43,15 @@ public class ForgeConfigReader private static final String PROJECT_ELEMENT_NAME = "forgeProject"; + private static final String ANNOTATION_LOOKUP = "annotationLookup"; + // // Private members // private Configuration config; private Project project; + private AnnotationLookup annotationLookup; // // Constructor @@ -57,6 +61,7 @@ public ForgeConfigReader(Configuration config, Project project) { this.config = config; this.project = project; + this.annotationLookup = new AnnotationLookup(project); } // @@ -66,7 +71,7 @@ public ForgeConfigReader(Configuration config, Project project) @Override protected boolean isNative(String name) { - if (PROJECT_ELEMENT_NAME.equals(name)) + if (PROJECT_ELEMENT_NAME.equals(name) || ANNOTATION_LOOKUP.equals(name)) { return true; } @@ -86,6 +91,9 @@ protected Object createNative(String name, Class namespace, String recordedTe { return this.project; } + if (ANNOTATION_LOOKUP.equals(name)) { + return this.annotationLookup; + } if(CONFIG_ELEMENT_NAME.equals(name)) { @@ -94,4 +102,5 @@ protected Object createNative(String name, Class namespace, String recordedTe return super.createNative(name, namespace, recordedText); } + } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java index a85e7c99ec..4919c8667c 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java @@ -37,6 +37,16 @@ public final class ForgeInspectionResultConstants public static final String ONE_TO_ONE = "one-to-one"; + public static final String PRIMARY_KEY = "primary-key"; + + public static final String PRIMARY_KEY_GENERATED = "primary-key-generated"; + + public static final String ENTITY_PRIMARY_KEY = "entity-primary-key"; + + public static final String REVERSE_PRIMARY_KEY = "reverse-primary-key"; + + public static final String REVERSE_PRIMARY_KEY_TYPE = "reverse-primary-key-type"; + // // Private constructor // diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java index 770581d495..62de05ea87 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java @@ -21,6 +21,7 @@ */ package org.jboss.forge.scaffold.faces.metawidget.inspector; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; import static org.metawidget.inspector.InspectionResultConstants.*; import static org.metawidget.inspector.faces.StaticFacesInspectionResultConstants.*; @@ -28,15 +29,12 @@ import java.util.List; import java.util.Map; -import javax.persistence.Embedded; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; +import javax.persistence.*; import org.jboss.forge.parser.java.EnumConstant; import org.jboss.forge.parser.java.JavaEnum; import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyle.ForgeProperty; +import org.jboss.solder.logging.Logger; import org.metawidget.inspector.impl.BaseObjectInspector; import org.metawidget.inspector.impl.BaseObjectInspectorConfig; import org.metawidget.inspector.impl.propertystyle.Property; @@ -50,76 +48,65 @@ * * @author Richard Kennard */ - public class ForgeInspector - extends BaseObjectInspector -{ + extends BaseObjectInspector { + + ForgeInspectorConfig config; + Logger log = Logger.getLogger(getClass()); + // // Constructor // - - public ForgeInspector() - { - this(new BaseObjectInspectorConfig()); + public ForgeInspector() { + super(new BaseObjectInspectorConfig()); } - public ForgeInspector(BaseObjectInspectorConfig config) - { + public ForgeInspector(ForgeInspectorConfig config) { super(config); + this.config = config; } // // Protected methods // - @Override protected Map inspectProperty(Property property) - throws Exception - { + throws Exception { Map attributes = CollectionUtils.newHashMap(); // OneToOne - if (property.isAnnotationPresent(OneToOne.class) || property.isAnnotationPresent(Embedded.class)) - { + if (property.isAnnotationPresent(OneToOne.class) || property.isAnnotationPresent(Embedded.class)) { attributes.put(ONE_TO_ONE, TRUE); } // ManyToOne - if (property.isAnnotationPresent(ManyToOne.class)) - { - attributes - .put(FACES_LOOKUP, - StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property - .getType())) + "Bean.all")); - - attributes - .put(FACES_CONVERTER_ID, - StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property - .getType())) + "Bean.converter")); + if (property.isAnnotationPresent(ManyToOne.class)) { + attributes.put(FACES_LOOKUP, + StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property.getType())) + "Bean.all")); + + attributes.put(FACES_CONVERTER_ID, + StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property.getType())) + "Bean.converter")); } // OneToMany and ManyToMany - if (property.isAnnotationPresent(OneToMany.class) || property.isAnnotationPresent(ManyToMany.class)) - { + if (property.isAnnotationPresent(OneToMany.class) || property.isAnnotationPresent(ManyToMany.class)) { attributes.put(N_TO_MANY, TRUE); } // Enums - if ( property instanceof ForgeProperty ) { + if (property instanceof ForgeProperty) { List> enumConstants = ((ForgeProperty) property).getEnumConstants(); - if (enumConstants != null) - { + if (enumConstants != null) { List lookup = CollectionUtils.newArrayList(); - for (EnumConstant anEnum : enumConstants) - { + for (EnumConstant anEnum : enumConstants) { lookup.add(anEnum.getName()); } @@ -127,6 +114,60 @@ protected Map inspectProperty(Property property) } } + // do @Id specific handling + if (null != property.getAnnotation(Id.class)) { + attributes.put(PRIMARY_KEY, property.getName()); + + if (null != property.getAnnotation(GeneratedValue.class)) { + attributes.put(PRIMARY_KEY_GENERATED, TRUE); + } + } + + if (null != property.getAnnotation(ManyToOne.class)) { + attributes.put(REVERSE_PRIMARY_KEY_TYPE, property.getType()); + } + + if (attributes.containsKey(PRIMARY_KEY) && !TRUE.equals(attributes.get(PRIMARY_KEY_GENERATED))) { + // if primary key is not generated it cannot be hidden in view + attributes.remove(HIDDEN); + attributes.put(REQUIRED, TRUE); + } + + if (config != null && config.getAnnotationLookup() != null) { + final AnnotationLookup annotationLookup = config.getAnnotationLookup(); + + if (attributes.containsKey(REVERSE_PRIMARY_KEY_TYPE) && null != annotationLookup) { + try { + final String reverseKey = annotationLookup.getFieldName(Id.class, attributes.get(REVERSE_PRIMARY_KEY_TYPE)); + attributes.put(REVERSE_PRIMARY_KEY, reverseKey); + } catch (Exception e) { + throw new RuntimeException("cannot resolve reverse primary key", e); + } + } + } + + return attributes; + } + + @Override + protected Map inspectEntity(String declaredClass, String actualClass) throws Exception { + Map attributes = CollectionUtils.newHashMap(); + Map superMap = super.inspectEntity(declaredClass, actualClass); + if (superMap != null) + attributes.putAll(superMap); + + if (config != null && config.getAnnotationLookup() != null) { + final AnnotationLookup annotationLookup = config.getAnnotationLookup(); + + try { + final String primaryKey = annotationLookup.getFieldName(Id.class, declaredClass); + attributes.put(PRIMARY_KEY, primaryKey); + } catch (Exception e) { + log.debug("cannot resolve primary key for class "+declaredClass, e); + } + } return attributes; } + + } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java new file mode 100644 index 0000000000..afe9c572c2 --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java @@ -0,0 +1,65 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.metawidget.inspector; + +import org.jboss.forge.project.Project; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; +import org.metawidget.config.iface.NeedsResourceResolver; +import org.metawidget.config.iface.ResourceResolver; +import org.metawidget.inspector.impl.BaseObjectInspectorConfig; + +/** + * + * @author Thomas Frühbeck + */ +public class ForgeInspectorConfig extends BaseObjectInspectorConfig implements NeedsResourceResolver { + + ResourceResolver resolver; + Project project; + AnnotationLookup annotationLookup; + + @Override + public void setResourceResolver(ResourceResolver resourceResolver) { + this.resolver = resourceResolver; + } + + public ResourceResolver getResolver() { + return resolver; + } + + public void setProject(Project project) { + this.project = project; + } + + public Project getProject() { + return project; + } + + public void setAnnotationLookup(AnnotationLookup annotationLookup) { + this.annotationLookup = annotationLookup; + } + + public AnnotationLookup getAnnotationLookup() { + return annotationLookup; + } + +} diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java new file mode 100644 index 0000000000..786066f26f --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java @@ -0,0 +1,87 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.metawidget.processor; + +import java.util.Map; +import static org.metawidget.inspector.InspectionResultConstants.*; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; +import org.jboss.forge.project.Project; +import org.metawidget.inspectionresultprocessor.iface.InspectionResultProcessor; +import org.metawidget.statically.StaticMetawidget; +import org.metawidget.statically.javacode.StaticJavaMetawidget; +import org.metawidget.util.XmlUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @author Thomas Frühbeck + */ +public class ForgeInspectionResultProcessor implements InspectionResultProcessor { + + private Project project; + + public ForgeInspectionResultProcessor() { + } + + public void setProject(Project project) { + this.project = project; + } + + @Override + public String processInspectionResult(String inspectionResult, StaticMetawidget metawidget, Object toInspect, String type, String... names) { + + Document document = XmlUtils.documentFromString(inspectionResult); + NodeList entities = document.getElementsByTagName(ENTITY); + + if (entities.getLength() > 0) { + for (int i=0; i attributes = XmlUtils.getAttributesAsMap(entity); + + String primaryKey = attributes.get(PRIMARY_KEY); + if (null != primaryKey) { + + NodeList properties = document.getElementsByTagName(PROPERTY); + if (properties.getLength() > 0) { + for (int j=0; j propAttribs = XmlUtils.getAttributesAsMap(property); + propAttribs.put(ENTITY_PRIMARY_KEY, primaryKey); + + XmlUtils.setMapAsAttributes(property, propAttribs); + } + } + } + } + } + + inspectionResult = XmlUtils.documentToString(document, false); + + return inspectionResult; + } + +} diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java index 2c764625f0..4eb9a4293f 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java @@ -151,10 +151,12 @@ public StaticXmlWidget buildWidget(String elementName, Map attri (StaticUIMetawidget) metawidget); } + String reverseKey = getReversePrimaryKey(attributes); + Param param = new Param(); param.putAttribute("name", "id"); param.putAttribute("value", - StaticFacesUtils.wrapExpression(StaticFacesUtils.unwrapExpression(link.getValue()) + ".id")); + StaticFacesUtils.wrapExpression(StaticFacesUtils.unwrapExpression(link.getValue()) + "." + reverseKey)); link.getChildren().add(param); return link; @@ -257,6 +259,27 @@ public StaticXmlWidget buildWidget(String elementName, Map attri // Protected methods // + protected String getReversePrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(REVERSE_PRIMARY_KEY)) + reverseKey = attributes.get(REVERSE_PRIMARY_KEY); + return reverseKey; + } + + protected String getPrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(PRIMARY_KEY)) + reverseKey = attributes.get(PRIMARY_KEY); + return reverseKey; + } + + protected String getEntityPrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(ENTITY_PRIMARY_KEY)) + reverseKey = attributes.get(ENTITY_PRIMARY_KEY); + return reverseKey; + } + /** * Overridden to add row creation/deletion. */ @@ -541,7 +564,7 @@ protected void addColumnComponent(HtmlDataTable dataTable, Map t Param param = new Param(); param.putAttribute("name", "id"); - param.putAttribute("value", StaticFacesUtils.wrapExpression(dataTable.getAttribute("var") + ".id")); + param.putAttribute("value", StaticFacesUtils.wrapExpression(dataTable.getAttribute("var") + "." + getEntityPrimaryKey(columnAttributes))); link.getChildren().add(param); link.getChildren().add(column.getChildren().remove(1)); column.getChildren().add(link); diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java index fc45440967..d07be65dbd 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java @@ -16,6 +16,7 @@ package org.jboss.forge.scaffold.faces.metawidget.widgetbuilder; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; import static org.metawidget.inspector.InspectionResultConstants.*; import static org.metawidget.inspector.faces.StaticFacesInspectionResultConstants.*; @@ -108,12 +109,16 @@ public StaticJavaWidget buildWidget(String elementName, Map attr if (attributes.containsKey(FACES_LOOKUP)) { - StaticJavaStub toReturn = new StaticJavaStub(); + String reverseKey = "Id"; + if (attributes.containsKey(REVERSE_PRIMARY_KEY)) + reverseKey = StringUtils.capitalize(attributes.get(REVERSE_PRIMARY_KEY)); + + StaticJavaStub toReturn = new StaticJavaStub(); JavaStatement getValue = new JavaStatement(ClassUtils.getSimpleName(type) + " " + name + " = this.search.get" + StringUtils.capitalize(name) + "()"); getValue.putImport(type); toReturn.getChildren().add(getValue); - JavaStatement ifNotEmpty = new JavaStatement("if (" + name + " != null && " + name + ".getId() != null)"); + JavaStatement ifNotEmpty = new JavaStatement("if (" + name + " != null && " + name + ".get" + reverseKey + "() != null)"); ifNotEmpty.getChildren().add( new JavaStatement("predicatesList.add(builder.equal(root.get(\"" + name + "\"), " + name + "))")); toReturn.getChildren().add(ifNotEmpty); diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java new file mode 100644 index 0000000000..cfe2a96fe0 --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java @@ -0,0 +1,107 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.util; + +import java.io.FileNotFoundException; +import org.jboss.forge.parser.java.Field; +import org.jboss.forge.parser.java.JavaSource; +import org.jboss.forge.parser.java.Member; +import org.jboss.forge.parser.java.Method; +import org.jboss.forge.project.Project; +import org.jboss.forge.project.facets.JavaSourceFacet; +import org.metawidget.util.simple.StringUtils; + +/** + * utility for easy lookup of fields or properties in related entities of the domain model + * @author Thomas Frühbeck + */ +public class AnnotationLookup { + + public static final String JAVA_EXTENSION = ".java"; + + private Project project; + + public AnnotationLookup(Project project) { + this.project = project; + } + + /** + * lookup the annotated member of the class + * @param annotation + * @param qualifiedType + * @return + * @throws FileNotFoundException + */ + public Member lookup (Class annotation, String qualifiedType) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaSource javaSource = java.getJavaResource(qualifiedType).getJavaSource(); + + Member member = lookup(javaSource, annotation); + return member; + } + + /** + * convert the member to a field name, assumes JavaBeans notation + * @param member + * @return + */ + public String getFieldName(Member member) { + if (null == member) + return null; + if (member instanceof Method) { + String methodName = member.getName(); + return StringUtils.decapitalize(methodName.substring(3)); + } else if (member instanceof Field) { + return member.getName(); + } + return null; + } + + /** + * get the field name of the annotated member of the class + * @param annotation + * @param qualifiedType + * @return + * @throws FileNotFoundException + */ + public String getFieldName (Class annotation, String qualifiedType) throws FileNotFoundException { + Member member = lookup(annotation, qualifiedType); + return getFieldName(member); + } + + /** + * find a member annotated with this annotation. + * @param javaSource + * @param ann + * @return + */ + public Member lookup(JavaSource javaSource, Class ann) { + //@TODO Is not prepared for multiple PrimKeys + for (Member member : javaSource.getMembers()) { + if (member.hasAnnotation(ann)) { + return member; + } + } + return null; + } + +} diff --git a/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv b/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv index 30c24043da..681647ab87 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv +++ b/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv @@ -45,13 +45,13 @@ public class @{entity.getName()}Bean implements Serializable { * Support creating and retrieving @{entity.getName()} entities */ - private Long id; + private @{primaryKeyType} id; - public Long getId() { + public @{primaryKeyType} getId() { return this.id; } - public void setId(Long id) { + public void setId(@{primaryKeyType} id) { this.id = id; } @@ -103,7 +103,7 @@ public class @{entity.getName()}Bean implements Serializable { return "search?faces-redirect=true"; } else { this.entityManager.merge(this.@{ccEntity}); - return "view?faces-redirect=true&id=" + this.@{ccEntity}.getId(); + return "view?faces-redirect=true&id=" + this.@{ccEntity}.get@{primaryKeyCC}(); } } catch( Exception e ) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage( e.getMessage() )); @@ -234,7 +234,7 @@ public class @{entity.getName()}Bean implements Serializable { return ""; } - return String.valueOf(((@{entity.getName()}) value).getId()); + return String.valueOf(((@{entity.getName()}) value).get@{primaryKeyCC}()); } }; } diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml index 9650a0cd79..32555ce1c4 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml @@ -25,10 +25,16 @@ - + + + + + + + @@ -45,7 +51,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml index 8d3c545aea..f03a29a675 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml @@ -25,10 +25,16 @@ - + + + + + + + @@ -44,6 +50,16 @@ + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml index 03e3582cc5..90fac2db26 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml @@ -24,10 +24,16 @@ - + + + + + + + @@ -44,7 +50,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml index 69baabe4d8..1e9f8f7c45 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml @@ -24,10 +24,16 @@ - + + + + + + + @@ -44,7 +50,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java new file mode 100644 index 0000000000..ddc57d1870 --- /dev/null +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java @@ -0,0 +1,242 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jboss.forge.scaffold.faces; + +import java.io.FileNotFoundException; +import java.io.Serializable; +import java.util.Map; +import javax.inject.Inject; +import javax.persistence.*; +import junit.framework.Assert; +import org.jboss.arquillian.protocol.servlet.arq514hack.descriptors.impl.web.Strings; +import org.jboss.forge.parser.JavaParser; +import org.jboss.forge.parser.java.Field; +import org.jboss.forge.parser.java.JavaClass; +import org.jboss.forge.parser.java.Method; +import org.jboss.forge.parser.java.util.Refactory; +import org.jboss.forge.project.Project; +import org.jboss.forge.project.facets.JavaSourceFacet; +import org.jboss.forge.project.facets.WebResourceFacet; +import org.jboss.forge.project.services.ResourceFactory; +import org.jboss.forge.resources.FileResource; +import org.jboss.forge.resources.java.JavaResource; +import org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspector; +import org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectorConfig; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; +import org.jboss.forge.shell.util.Streams; +import org.junit.Test; +import org.metawidget.util.XmlUtils; +import org.metawidget.util.simple.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import static org.junit.Assert.*; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; +import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyle; +import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyleConfig; +import org.jboss.forge.scaffold.faces.metawidget.processor.ForgeInspectionResultProcessor; +import static org.metawidget.inspector.InspectionResultConstants.*; + +/** + * + * @author Thomas Frühbeck + */ +public class PrimaryKeyFacesScaffoldTest extends AbstractFacesScaffoldTest { + + @Inject + private ResourceFactory factory; + + @Test + public void testGenerateFromLegacyPrimaryKey() throws Exception { + final String parentPrimaryKey = "parentPrimaryKey"; + final String parentPrimaryKeyCC = StringUtils.capitalize(parentPrimaryKey); + + Project project = setupScaffoldProject(); + + queueInputLines(""); + generateAlternateEntity(project, "com.test.model", "Parent", parentPrimaryKey); + + getShell().execute("entity --named Child"); + getShell().execute("field string --named name"); + getShell().execute("field manyToOne --named parent --fieldType com.test.model.Parent.java --inverseFieldName children"); + + queueInputLines("", "", ""); + getShell().execute("scaffold from-entity com.test.model.* --scaffoldType faces"); + + WebResourceFacet web = project.getFacet(WebResourceFacet.class); + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + // Code + JavaResource parentBean = java.getJavaResource("com.test.view.ParentBean"); + JavaResource childBean = java.getJavaResource("com.test.view.ChildBean"); + + String parentContent = Streams.toString(parentBean.getResourceInputStream()); + assertTrue(parentContent.contains("id=\" + this.parent.get" + parentPrimaryKeyCC + "()")); + assertTrue(parentContent.contains("valueOf(((Parent) value).get" + parentPrimaryKeyCC + "()")); + + String childContent = Streams.toString(childBean.getResourceInputStream()); + assertTrue(childContent.contains("this.child.getId()")); + + // View + FileResource view = web.getWebResource("scaffold/parent/view.xhtml"); + assertTrue(view.exists()); + String contents = Streams.toString(view.getResourceInputStream()); + assertTrue(contents.contains( + "template=\"/resources/scaffold/page.xhtml")); + + view = web.getWebResource("scaffold/parent/search.xhtml"); + contents = Streams.toString(view.getResourceInputStream()); + assertTrue(view.exists()); + assertTrue(contents.contains("")); + + view = web.getWebResource("scaffold/child/view.xhtml"); + contents = Streams.toString(view.getResourceInputStream()); + assertTrue(view.exists()); + assertTrue(contents.contains("childBean.child.parent." + parentPrimaryKey)); +} + + private JavaResource generateAlternateEntity(Project project, String pkg, String entityName, String primaryKey) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaClass javaClass = JavaParser.create(JavaClass.class).setPackage(pkg).setName(entityName).setPublic().addAnnotation(Entity.class).getOrigin().addInterface(Serializable.class); + + String idName = primaryKey; + if (idName == null) { + StringUtils.decapitalize(entityName + "Id"); + } + + Field id = javaClass.addField("private String " + idName + " = null;"); + id.addAnnotation(Id.class); + id.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + id.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + + Refactory.createGetterAndSetter(javaClass, id); + + Field name = javaClass.addField("private String name = null;"); + Refactory.createGetterAndSetter(javaClass, name); + + Refactory.createToStringFromFields(javaClass, id); + Refactory.createHashCodeAndEquals(javaClass); + + return java.saveJavaSource(javaClass); + } + + @Test + public void testPrimaryKeys() throws Exception { + Project project = initializeJavaProject(); + queueInputLines("HIBERNATE", "JBOSS_AS7", ""); + getShell().execute("persistence setup"); + + for (PrimaryKeyTestBase testClass : new PrimaryKeyTestBase[]{ + new PrimaryKeyFieldTest(), new PrimaryKeyPropertyTest(), new PrimaryKeyPropertyAssignedTest()}) { + testPrimaryKey(project, testClass); + } + } + + public void testPrimaryKey(Project project, PrimaryKeyTestBase testClass) throws Exception { + + final String parentPrimaryKey = "primaryKey"; + final String parentPrimaryKeyCC = StringUtils.capitalize(parentPrimaryKey); + + ForgeInspectorConfig config = new ForgeInspectorConfig(); + config.setAnnotationLookup(new AnnotationLookup(project)); + config.setPropertyStyle(new ForgePropertyStyle(new ForgePropertyStyleConfig().setProject(project))); + ForgeInspectionResultProcessor processor = new ForgeInspectionResultProcessor(); + + generatePkEntity(project, "org.test", "Parent", parentPrimaryKey, testClass); + + String xml = new ForgeInspector(config).inspect(null, "org.test.Parent"); + xml = processor.processInspectionResult(xml, null, project, xml, new String[]{}); + + Document document = XmlUtils.documentFromString(xml); + assertEquals("inspection-result", document.getFirstChild().getNodeName()); + Element entity = (Element) document.getFirstChild().getFirstChild(); + assertEquals(ENTITY, entity.getNodeName()); + + Map attributes = XmlUtils.getAttributesAsMap(entity); + assertEquals(parentPrimaryKey, attributes.get(PRIMARY_KEY)); + + NodeList properties = entity.getElementsByTagName(PROPERTY); + for (int i = 0; i < properties.getLength(); i++) { + Element prop = (Element) properties.item(i); + attributes = XmlUtils.getAttributesAsMap(prop); + + if (!(testClass instanceof PrimaryKeyPropertyAssignedTest)) { + assertTrue(attributes.containsKey(PRIMARY_KEY_GENERATED)); + } + } + Element property = (Element) entity.getFirstChild(); + attributes = XmlUtils.getAttributesAsMap(property); + assertEquals(parentPrimaryKey, attributes.get(PRIMARY_KEY)); + assertEquals(parentPrimaryKey, attributes.get(ENTITY_PRIMARY_KEY)); + + } + + private JavaResource generatePkEntity(Project project, String pkg, String entityName, String primaryKey, PrimaryKeyTestBase pkTest) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaClass javaClass = JavaParser.create(JavaClass.class).setPackage(pkg).setName(entityName).setPublic().addAnnotation(Entity.class).getOrigin().addInterface(Serializable.class); + + String idName = primaryKey; + if (idName == null) { + StringUtils.decapitalize(entityName + "Id"); + } + + Field id = javaClass.addField("private String " + idName + " = null;"); + if (pkTest.field) { + id.addAnnotation(Id.class); + if (pkTest.generated) { + id.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + id.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + } + } + + + + Refactory.createGetterAndSetter(javaClass, id); + if (!pkTest.field) { + Method getPk = javaClass.getMethod("get" + StringUtils.capitalize(idName)); + getPk.addAnnotation(Id.class); + if (pkTest.generated) { + getPk.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + getPk.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + } + } + + Field name = javaClass.addField("private String name = null;"); + Refactory.createGetterAndSetter(javaClass, name); + Field type = javaClass.addField("private String type = null;"); + Refactory.createGetterAndSetter(javaClass, type); + + return java.saveJavaSource(javaClass); + } + + + class PrimaryKeyTestBase { + + public boolean generated, field; + } + + class PrimaryKeyFieldTest extends PrimaryKeyTestBase { + + { + generated = true; + field = true; + } + } + + class PrimaryKeyPropertyTest extends PrimaryKeyTestBase { + + { + generated = true; + field = false; + } + } + + class PrimaryKeyPropertyAssignedTest extends PrimaryKeyTestBase { + + { + generated = false; + field = true; + } + } +} diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java index 1e5280b052..e1accb29af 100644 --- a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java @@ -72,7 +72,7 @@ public void testRelationships() assertEquals("manyToOne", property.getAttribute(NAME)); assertEquals("#{forgeInspectorTest$BarBean.all}", property.getAttribute(FACES_LOOKUP)); assertEquals("#{forgeInspectorTest$BarBean.converter}", property.getAttribute(FACES_CONVERTER_ID)); - assertEquals(3, property.getAttributes().getLength()); + assertEquals(4, property.getAttributes().getLength()); property = XmlUtils.getNextSiblingElement(property); assertEquals(PROPERTY, property.getNodeName()); From 95e0dd4235b3d661c2974ed40a5489a874771fe9 Mon Sep 17 00:00:00 2001 From: ThomasF Date: Tue, 20 Mar 2012 08:11:10 +0100 Subject: [PATCH 2/3] fixed targetDir handling --- .../petclinic/FacesScaffoldPetClinicTest.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java index 6375df30ac..38142d22f4 100644 --- a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java @@ -54,7 +54,8 @@ public class FacesScaffoldPetClinicTest extends AbstractFacesScaffoldTest public void testGenerate() throws Exception { Project current = getShell().getCurrentProject(); - Project project = setupScaffoldProject("petClinic"); + final String targetDir = "petClinic"; + Project project = setupScaffoldProject(targetDir); queueInputLines(""); getShell().execute("entity --named Owner"); @@ -97,7 +98,7 @@ public void testGenerate() throws Exception // Check search screen has h:message - FileResource search = web.getWebResource("scaffold/pet/search.xhtml"); + FileResource search = web.getWebResource(targetDir+"/pet/search.xhtml"); Assert.assertTrue(search.exists()); String contents = Streams.toString(search.getResourceInputStream()); @@ -111,14 +112,14 @@ public void testGenerate() throws Exception // Check search screen has boolean graphic - metawidget = "\t\t\t\t\t\r\n"; + metawidget = "\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\r\n"; Assert.assertTrue(contents.contains(metawidget)); - metawidget = "\t\t\t\t\t\r\n"; + metawidget = "\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\r\n"; @@ -127,7 +128,7 @@ public void testGenerate() throws Exception // Check create screen has h:selectBooleanCheckbox - FileResource create = web.getWebResource("scaffold/pet/create.xhtml"); + FileResource create = web.getWebResource(targetDir+"/pet/create.xhtml"); Assert.assertTrue(create.exists()); contents = Streams.toString(create.getResourceInputStream()); @@ -141,7 +142,7 @@ public void testGenerate() throws Exception // Check view screen has boolean graphic - FileResource view = web.getWebResource("scaffold/pet/view.xhtml"); + FileResource view = web.getWebResource(targetDir+"/pet/view.xhtml"); Assert.assertTrue(view.exists()); contents = Streams.toString(view.getResourceInputStream()); From 4f67378801f9c3bc3866c86a5cb54f00e1e8d50f Mon Sep 17 00:00:00 2001 From: ThomasF Date: Tue, 20 Mar 2012 01:42:26 +0100 Subject: [PATCH 3/3] enable detection of legacy primary key fields --- dist/src/main/resources/bin/forge | 2 +- .../forge/scaffold/faces/FacesScaffold.java | 370 ++++++++---------- .../metawidget/config/ForgeConfigReader.java | 11 +- .../ForgeInspectionResultConstants.java | 10 + .../metawidget/inspector/ForgeInspector.java | 117 ++++-- .../inspector/ForgeInspectorConfig.java | 65 +++ .../ForgeInspectionResultProcessor.java | 87 ++++ .../widgetbuilder/EntityWidgetBuilder.java | 27 +- .../QueryByExampleWidgetBuilder.java | 17 +- .../scaffold/faces/util/AnnotationLookup.java | 107 +++++ .../resources/scaffold/faces/BackingBean.jv | 10 +- .../scaffold/faces/metawidget-bean.xml | 20 +- .../scaffold/faces/metawidget-entity.xml | 18 +- .../scaffold/faces/metawidget-qbe.xml | 20 +- .../scaffold/faces/metawidget-search.xml | 20 +- .../faces/PrimaryKeyFacesScaffoldTest.java | 242 ++++++++++++ .../inspector/ForgeInspectorTest.java | 2 +- .../petclinic/FacesScaffoldPetClinicTest.java | 13 +- 18 files changed, 888 insertions(+), 270 deletions(-) create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java create mode 100644 scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java create mode 100644 scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java diff --git a/dist/src/main/resources/bin/forge b/dist/src/main/resources/bin/forge index db464e6c5e..e78ba7cb01 100644 --- a/dist/src/main/resources/bin/forge +++ b/dist/src/main/resources/bin/forge @@ -168,6 +168,6 @@ if $cygwin; then HOME=`cygpath --path --windows "$HOME"` fi -forge_exec_cmd="\"$JAVACMD\" $FORGE_OPTS \"-Dforge.home=${FORGE_HOME}\" \"-Dforge.shell.colorEnabled=true\" -jar \"${FORGE_HOME}/jboss-modules.jar\" -modulepath \"${FORGE_HOME}/modules:${HOME}/.forge/plugins\:$PLUGIN_DIR" org.jboss.forge" +forge_exec_cmd="\"$JAVACMD\" $FORGE_OPTS \"-Dforge.home=${FORGE_HOME}\" \"-Dforge.shell.colorEnabled=true\" -jar \"${FORGE_HOME}/jboss-modules.jar\" -modulepath \"${FORGE_HOME}/modules:${HOME}/.forge/plugins\:$PLUGIN_DIR\" org.jboss.forge" eval $forge_exec_cmd "$QUOTED_ARGS" diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java index 4649528cee..6b6f282b54 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/FacesScaffold.java @@ -33,14 +33,12 @@ import javax.enterprise.event.Event; import javax.inject.Inject; import javax.persistence.CascadeType; +import javax.persistence.Id; import javax.persistence.OneToOne; import org.jboss.forge.env.Configuration; import org.jboss.forge.parser.JavaParser; -import org.jboss.forge.parser.java.Annotation; -import org.jboss.forge.parser.java.Field; -import org.jboss.forge.parser.java.JavaClass; -import org.jboss.forge.parser.java.Method; +import org.jboss.forge.parser.java.*; import org.jboss.forge.parser.xml.Node; import org.jboss.forge.parser.xml.XMLParser; import org.jboss.forge.project.Project; @@ -94,33 +92,30 @@ import org.w3c.dom.NamedNodeMap; /** - * Facet to generate a Java Server Faces UI. - *

- * This facet utilizes Metawidget internally. This enables the use of the Metawidget - * SPI (pluggable WidgetBuilders, Layouts etc) for customizing the generated User Interface. For more information on - * writing Metawidget plugins, see the Metawidget documentation. - *

- * This Facet does not require Metawidget to be in the final project. + * Facet to generate a Java Server Faces UI.

This facet utilizes Metawidget internally. This enables the use + * of the Metawidget SPI (pluggable WidgetBuilders, Layouts etc) for customizing + * the generated User Interface. For more information on writing Metawidget + * plugins, see the Metawidget + * documentation.

This Facet does not require Metawidget to be + * in the final project. * * @author Lincoln Baxter, III * @author Richard Kennard */ - @Alias("faces") -@RequiresFacet({ WebResourceFacet.class, - DependencyFacet.class, - PersistenceFacet.class, - EJBFacet.class, - CDIFacet.class, - FacesFacet.class }) -public class FacesScaffold extends BaseFacet implements ScaffoldProvider -{ +@RequiresFacet({WebResourceFacet.class, + DependencyFacet.class, + PersistenceFacet.class, + EJBFacet.class, + CDIFacet.class, + FacesFacet.class}) +public class FacesScaffold extends BaseFacet implements ScaffoldProvider { // // Private statics // private static final String XMLNS_PREFIX = "xmlns:"; - private static final String BACKING_BEAN_TEMPLATE = "scaffold/faces/BackingBean.jv"; private static final String VIEW_UTILS_TEMPLATE = "scaffold/faces/ViewUtils.jv"; private static final String TAGLIB_TEMPLATE = "scaffold/faces/forge.taglib.xml"; @@ -128,44 +123,34 @@ public class FacesScaffold extends BaseFacet implements ScaffoldProvider private static final String CREATE_TEMPLATE = "scaffold/faces/create.xhtml"; private static final String SEARCH_TEMPLATE = "scaffold/faces/search.xhtml"; private static final String NAVIGATION_TEMPLATE = "scaffold/faces/page.xhtml"; - private static final String ERROR_TEMPLATE = "scaffold/faces/error.xhtml"; private static final String INDEX_TEMPLATE = "scaffold/faces/index.xhtml"; - private final Dependency richfaces3UI = DependencyBuilder.create("org.richfaces.ui:richfaces-ui"); private final Dependency richfaces3Impl = DependencyBuilder.create("org.richfaces.framework:richfaces-impl"); private final Dependency richfaces4UI = DependencyBuilder.create("org.richfaces.ui:richfaces-components-ui"); private final Dependency richfaces4Impl = DependencyBuilder.create("org.richfaces.core:richfaces-core-impl"); - // // Protected members (nothing is private, to help subclassing) // - protected CompiledTemplateResource backingBeanTemplate; protected int backingBeanTemplateQbeMetawidgetIndent; - protected CompiledTemplateResource viewUtilsTemplate; protected CompiledTemplateResource taglibTemplate; protected CompiledTemplateResource viewTemplate; protected Map viewTemplateNamespaces; protected int viewTemplateEntityMetawidgetIndent; - protected CompiledTemplateResource createTemplate; protected Map createTemplateNamespaces; protected int createTemplateEntityMetawidgetIndent; - protected CompiledTemplateResource searchTemplate; protected Map searchTemplateNamespaces; protected int searchTemplateSearchMetawidgetIndent; protected int searchTemplateBeanMetawidgetIndent; - protected CompiledTemplateResource navigationTemplate; protected int navigationTemplateIndent; - protected CompiledTemplateResource errorTemplate; protected CompiledTemplateResource indexTemplate; protected TemplateResolver resolver; - protected final ShellPrompt prompt; protected final TemplateCompiler compiler; protected final Event install; @@ -173,13 +158,15 @@ public class FacesScaffold extends BaseFacet implements ScaffoldProvider protected StaticHtmlMetawidget searchMetawidget; protected StaticHtmlMetawidget beanMetawidget; protected StaticJavaMetawidget qbeMetawidget; +// @Inject AnnotationLookup annotationLookup; +// @Inject RelationResolverWidgetProcessor relationResolver; +// @Inject RelationResolverWidgetProcessorConfig relationResolverConfig; private Configuration config; // // Constructor // - @Inject public FacesScaffold(final Configuration config, final ShellPrompt prompt, @@ -193,8 +180,7 @@ public FacesScaffold(final Configuration config, this.resolver = new ClassLoaderTemplateResolver(FacesScaffold.class.getClassLoader()); - if (this.compiler != null) - { + if (this.compiler != null) { this.compiler.getTemplateResolverFactory().addResolver(this.resolver); } } @@ -202,7 +188,6 @@ public FacesScaffold(final Configuration config, // // Public methods // - @Override public List> setup(String targetDir, final Resource template, final boolean overwrite) { @@ -213,16 +198,14 @@ public List> setup(String targetDir, final Resource template, fin } /** - * Overridden to setup the Metawidgets. - *

- * Metawidgets must be configured per project and per Forge invocation. It is not sufficient to simply - * configure them in setup because the user may restart Forge and not run scaffold setup a - * second time. + * Overridden to setup the Metawidgets.

Metawidgets must be configured + * per project and per Forge invocation. It is not sufficient to + * simply configure them in + * setup because the user may restart Forge and not run + * scaffold setup a second time. */ - @Override - public void setProject(Project project) - { + public void setProject(Project project) { super.setProject(project); ForgeConfigReader configReader = new ForgeConfigReader(this.config, this.project); @@ -242,6 +225,7 @@ public void setProject(Project project) this.qbeMetawidget = new StaticJavaMetawidget(); this.qbeMetawidget.setConfigReader(configReader); this.qbeMetawidget.setConfig("scaffold/faces/metawidget-qbe.xml"); + } @Override @@ -256,8 +240,7 @@ public List> generateFromEntity(String targetDir, final Resource // Track the list of resources generated List> result = new ArrayList>(); - try - { + try { JavaSourceFacet java = this.project.getFacet(JavaSourceFacet.class); WebResourceFacet web = this.project.getFacet(WebResourceFacet.class); @@ -266,20 +249,22 @@ public List> generateFromEntity(String targetDir, final Resource context.put("entity", entity); String ccEntity = StringUtils.decapitalize(entity.getName()); context.put("ccEntity", ccEntity); + setPrimaryKeyMetaData(context, entity); // Prepare qbeMetawidget this.qbeMetawidget.setPath(entity.getQualifiedName()); StringWriter stringWriter = new StringWriter(); this.qbeMetawidget.write(stringWriter, this.backingBeanTemplateQbeMetawidgetIndent); + context.put("qbeMetawidget", stringWriter.toString().trim()); context.put("qbeMetawidgetImports", - CollectionUtils.toString(this.qbeMetawidget.getImports(), ";\r\nimport ", true, false)); + CollectionUtils.toString(this.qbeMetawidget.getImports(), ";\r\nimport ", true, false)); // Create the Backing Bean for this entity JavaClass viewBean = JavaParser.parse(JavaClass.class, this.backingBeanTemplate.render(context)); viewBean.setPackage(java.getBasePackage() + ".view"); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, java.getJavaResource(viewBean), viewBean.toString(), - overwrite)); + overwrite)); // Set new context for view generation context = getTemplateContext(template); @@ -287,6 +272,7 @@ public List> generateFromEntity(String targetDir, final Resource context.put("beanName", beanName); context.put("ccEntity", ccEntity); context.put("entityName", StringUtils.uncamelCase(entity.getName())); + setPrimaryKeyMetaData(context, entity); // Prepare entityMetawidget this.entityMetawidget.setValue(StaticFacesUtils.wrapExpression(beanName + "." + ccEntity)); @@ -316,7 +302,7 @@ public List> generateFromEntity(String targetDir, final Resource this.beanMetawidget.setValue(StaticFacesUtils.wrapExpression(beanName + ".pageItems")); this.beanMetawidget.setPath(viewBean.getQualifiedName() + "/pageItems"); writeSearchAndBeanMetawidget(context, this.searchTemplateSearchMetawidgetIndent, - this.searchTemplateBeanMetawidgetIndent, this.searchTemplateNamespaces); + this.searchTemplateBeanMetawidgetIndent, this.searchTemplateNamespaces); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource(targetDir + "/" + ccEntity + "/search.xhtml"), @@ -329,19 +315,17 @@ public List> generateFromEntity(String targetDir, final Resource JavaClass viewUtils = JavaParser.parse(JavaClass.class, this.viewUtilsTemplate.render(context)); viewUtils.setPackage(viewBean.getPackage()); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, java.getJavaResource(viewUtils), viewUtils.toString(), - true)); + true)); context.put("viewPackage", viewBean.getPackage()); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, - web.getWebResource("WEB-INF/classes/META-INF/forge.taglib.xml"), - this.taglibTemplate.render(context), true)); + web.getWebResource("WEB-INF/classes/META-INF/forge.taglib.xml"), + this.taglibTemplate.render(context), true)); createInitializers(entity); this.project.getFacet(JavaSourceFacet.class).saveJavaSource(entity); - } - catch (Exception e) - { + } catch (Exception e) { throw new RuntimeException("Error generating default scaffolding: " + e.getMessage(), e); } return result; @@ -349,21 +333,18 @@ public List> generateFromEntity(String targetDir, final Resource @Override @SuppressWarnings("unchecked") - public boolean install() - { + public boolean install() { if (!(this.project.hasFacet(WebResourceFacet.class) && this.project.hasFacet(PersistenceFacet.class) - && this.project.hasFacet(CDIFacet.class) && this.project.hasFacet(FacesFacet.class))) - { + && this.project.hasFacet(CDIFacet.class) && this.project.hasFacet(FacesFacet.class))) { this.install.fire(new InstallFacets(WebResourceFacet.class, PersistenceFacet.class, CDIFacet.class, - FacesFacet.class)); + FacesFacet.class)); } return true; } @Override - public boolean isInstalled() - { + public boolean isInstalled() { return true; } @@ -388,39 +369,39 @@ public List> generateIndex(String targetDir, final Resource templ this.indexTemplate.render(context), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("error.xhtml"), - this.errorTemplate.render(context), overwrite)); + this.errorTemplate.render(context), overwrite)); // Static resources result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/add.png"), - getClass().getResourceAsStream("/scaffold/faces/add.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/add.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/background.gif"), - getClass().getResourceAsStream("/scaffold/faces/background.gif"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/background.gif"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/false.png"), - getClass().getResourceAsStream("/scaffold/faces/false.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/false.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/favicon.ico"), - getClass().getResourceAsStream("/scaffold/faces/favicon.ico"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/favicon.ico"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/forge-logo.png"), - getClass().getResourceAsStream("/scaffold/faces/forge-logo.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/forge-logo.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/forge-style.css"), - getClass().getResourceAsStream("/scaffold/faces/forge-style.css"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/forge-style.css"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/jboss-community.png"), - getClass().getResourceAsStream("/scaffold/faces/jboss-community.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/jboss-community.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/remove.png"), - getClass().getResourceAsStream("/scaffold/faces/remove.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/remove.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/search.png"), - getClass().getResourceAsStream("/scaffold/faces/search.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/search.png"), overwrite)); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, web.getWebResource("/resources/true.png"), - getClass().getResourceAsStream("/scaffold/faces/true.png"), overwrite)); + getClass().getResourceAsStream("/scaffold/faces/true.png"), overwrite)); return result; } @@ -432,14 +413,12 @@ public List> getGeneratedResources(String targetDir) } @Override - public AccessStrategy getAccessStrategy() - { + public AccessStrategy getAccessStrategy() { return new FacesAccessStrategy(this.project); } @Override - public TemplateStrategy getTemplateStrategy() - { + public TemplateStrategy getTemplateStrategy() { return new FacesTemplateStrategy(this.project); } @@ -448,14 +427,13 @@ public List> generateTemplates(String targetDir, final boolean overw { List> result = new ArrayList>(); - try - { + try { WebResourceFacet web = this.project.getFacet(WebResourceFacet.class); result.add(ScaffoldUtil.createOrOverwrite(this.prompt, - web.getWebResource("/resources/scaffold/paginator.xhtml"), - getClass().getResourceAsStream("/scaffold/faces/paginator.xhtml"), - overwrite)); + web.getWebResource("/resources/scaffold/paginator.xhtml"), + getClass().getResourceAsStream("/scaffold/faces/paginator.xhtml"), + overwrite)); result.add(generateNavigation(targetDir, overwrite)); } @@ -470,91 +448,72 @@ public List> generateTemplates(String targetDir, final boolean overw // // Protected methods (nothing is private, to help subclassing) // - - protected void loadTemplates() - { - if (this.backingBeanTemplate == null) - { + protected void loadTemplates() { + if (this.backingBeanTemplate == null) { this.backingBeanTemplate = this.compiler.compile(BACKING_BEAN_TEMPLATE); String template = Streams.toString(this.backingBeanTemplate.getSourceTemplateResource().getInputStream()); this.backingBeanTemplateQbeMetawidgetIndent = parseIndent(template, "@{qbeMetawidget}"); } - if (this.viewUtilsTemplate == null) - { + if (this.viewUtilsTemplate == null) { this.viewUtilsTemplate = this.compiler.compile(VIEW_UTILS_TEMPLATE); } - if (this.taglibTemplate == null) - { + if (this.taglibTemplate == null) { this.taglibTemplate = this.compiler.compile(TAGLIB_TEMPLATE); } - if (this.viewTemplate == null) - { + if (this.viewTemplate == null) { this.viewTemplate = this.compiler.compile(VIEW_TEMPLATE); String template = Streams.toString(this.viewTemplate.getSourceTemplateResource().getInputStream()); this.viewTemplateNamespaces = parseNamespaces(template); this.viewTemplateEntityMetawidgetIndent = parseIndent(template, "@{metawidget}"); } - if (this.createTemplate == null) - { + if (this.createTemplate == null) { this.createTemplate = this.compiler.compile(CREATE_TEMPLATE); String template = Streams.toString(this.createTemplate.getSourceTemplateResource().getInputStream()); this.createTemplateNamespaces = parseNamespaces(template); this.createTemplateEntityMetawidgetIndent = parseIndent(template, "@{metawidget}"); } - if (this.searchTemplate == null) - { + if (this.searchTemplate == null) { this.searchTemplate = this.compiler.compile(SEARCH_TEMPLATE); String template = Streams.toString(this.searchTemplate.getSourceTemplateResource().getInputStream()); this.searchTemplateNamespaces = parseNamespaces(template); this.searchTemplateSearchMetawidgetIndent = parseIndent(template, "@{searchMetawidget}"); this.searchTemplateBeanMetawidgetIndent = parseIndent(template, "@{beanMetawidget}"); } - if (this.navigationTemplate == null) - { + if (this.navigationTemplate == null) { this.navigationTemplate = this.compiler.compile(NAVIGATION_TEMPLATE); String template = Streams.toString(this.navigationTemplate.getSourceTemplateResource().getInputStream()); this.navigationTemplateIndent = parseIndent(template, "@{navigation}"); } - if (this.errorTemplate == null) - { + if (this.errorTemplate == null) { this.errorTemplate = this.compiler.compile(ERROR_TEMPLATE); } - if (this.indexTemplate == null) - { + if (this.indexTemplate == null) { this.indexTemplate = this.compiler.compile(INDEX_TEMPLATE); } } - protected void setupRichFaces() - { + protected void setupRichFaces() { if ((this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3UI) - && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3Impl)) - || (this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4UI) - && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4Impl))) - { - this.entityMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.entityMetawidget - .getWidgetBuilder())); + && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces3Impl)) + || (this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4UI) + && this.project.getFacet(DependencyFacet.class).hasEffectiveDependency(this.richfaces4Impl))) { + this.entityMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.entityMetawidget.getWidgetBuilder())); - this.searchMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.searchMetawidget - .getWidgetBuilder())); + this.searchMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.searchMetawidget.getWidgetBuilder())); - this.beanMetawidget - .setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.beanMetawidget - .getWidgetBuilder())); + this.beanMetawidget.setWidgetBuilder(insertRichFacesWidgetBuilder((CompositeWidgetBuilder) this.beanMetawidget.getWidgetBuilder())); } } /** - * Locates a ReadOnlyWidgetBuilder in the list of WidgetBuilders, and inserts a - * RichFacesWidgetBuilder after it (unless there's a RichFacesWidgetBuilder in there - * already). + * Locates a + * ReadOnlyWidgetBuilder in the list of WidgetBuilders, and + * inserts a + * RichFacesWidgetBuilder after it (unless there's a + * RichFacesWidgetBuilder in there already). */ - protected CompositeWidgetBuilder insertRichFacesWidgetBuilder( - final CompositeWidgetBuilder compositeWidgetBuilder) - { + final CompositeWidgetBuilder compositeWidgetBuilder) { // Get the current WidgetBuilders... WidgetBuilder[] existingWidgetBuilders = compositeWidgetBuilder.getWidgetBuilders(); @@ -563,19 +522,16 @@ protected CompositeWidgetBuilder ins int addAt = 0; - for (int loop = 0; loop < existingWidgetBuilders.length; loop++) - { + for (int loop = 0; loop < existingWidgetBuilders.length; loop++) { // ...(abort if there's already a RichFacesWidgetBuilder)... // Use an Object loop variable here to avoid a nasty Java/Generics compiler bug Object widgetBuilder = existingWidgetBuilders[loop]; - if (widgetBuilder instanceof RichFacesWidgetBuilder) - { + if (widgetBuilder instanceof RichFacesWidgetBuilder) { return compositeWidgetBuilder; } - if (widgetBuilder instanceof ReadOnlyWidgetBuilder) - { + if (widgetBuilder instanceof ReadOnlyWidgetBuilder) { addAt = loop + 1; } } @@ -583,55 +539,41 @@ protected CompositeWidgetBuilder ins // ...and insert our RichFacesWidgetBuilder just after it @SuppressWarnings("unchecked") - WidgetBuilder[] newWidgetBuilders = (WidgetBuilder[]) ArrayUtils - .addAt(existingWidgetBuilders, addAt, - new RichFacesWidgetBuilder()); + WidgetBuilder[] newWidgetBuilders = (WidgetBuilder[]) ArrayUtils.addAt(existingWidgetBuilders, addAt, + new RichFacesWidgetBuilder()); return new CompositeWidgetBuilder( - new CompositeWidgetBuilderConfig() - .setWidgetBuilders(newWidgetBuilders)); + new CompositeWidgetBuilderConfig().setWidgetBuilders(newWidgetBuilders)); } - protected void createInitializers(final JavaClass entity) - { - for (Field field : entity.getFields()) - { - if (field.hasAnnotation(OneToOne.class)) - { + protected void createInitializers(final JavaClass entity) { + for (Field field : entity.getFields()) { + if (field.hasAnnotation(OneToOne.class)) { Annotation oneToOne = field.getAnnotation(OneToOne.class); - if (oneToOne.getStringValue("mappedBy") == null) - { + if (oneToOne.getStringValue("mappedBy") == null) { oneToOne.setEnumValue("cascade", CascadeType.ALL); } String methodName = "new" + field.getTypeInspector().getName(); - if (!entity.hasMethodSignature(methodName)) - { - entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic() - .setBody("this." + field.getName() + " = new " + field.getType() + "();"); + if (!entity.hasMethodSignature(methodName)) { + entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic().setBody("this." + field.getName() + " = new " + field.getType() + "();"); } } } - for (Method method : entity.getMethods()) - { - if (method.hasAnnotation(OneToOne.class)) - { + for (Method method : entity.getMethods()) { + if (method.hasAnnotation(OneToOne.class)) { Annotation oneToOne = method.getAnnotation(OneToOne.class); - if (oneToOne.getStringValue("mappedBy") == null) - { + if (oneToOne.getStringValue("mappedBy") == null) { oneToOne.setEnumValue("cascade", CascadeType.ALL); } String methodName = "new" + method.getReturnTypeInspector().getName(); - if (!entity.hasMethodSignature(methodName)) - { - entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic() - .setBody("this." + method.getName() + " = new " + method.getReturnType() + "();"); + if (!entity.hasMethodSignature(methodName)) { + entity.addMethod().setName(methodName).setReturnTypeVoid().setPublic().setBody("this." + method.getName() + " = new " + method.getReturnType() + "();"); } } } } - protected HashMap getTemplateContext(final Resource template) - { + protected HashMap getTemplateContext(final Resource template) { HashMap context; context = new HashMap(); context.put("template", template); @@ -639,8 +581,7 @@ protected HashMap getTemplateContext(final Resource template) return context; } - protected void setupWebXML() - { + protected void setupWebXML() { ServletFacet servlet = this.project.getFacet(ServletFacet.class); Node webXML = removeConflictingErrorPages(servlet); @@ -658,20 +599,16 @@ protected void setupWebXML() servlet.saveConfig(servletConfig); } - protected Node removeConflictingErrorPages(final ServletFacet servlet) - { + protected Node removeConflictingErrorPages(final ServletFacet servlet) { Node webXML = XMLParser.parse(servlet.getConfigFile().getResourceInputStream()); Node root = webXML.getRoot(); List errorPages = root.get("error-page"); - for (String code : Arrays.asList("404", "500")) - { - for (Node errorPage : errorPages) - { + for (String code : Arrays.asList("404", "500")) { + for (Node errorPage : errorPages) { if (code.equals(errorPage.getSingle("error-code").getText()) - && this.prompt.promptBoolean("Your web.xml already contains an error page for " + code - + " status codes, replace it?")) - { + && this.prompt.promptBoolean("Your web.xml already contains an error page for " + code + + " status codes, replace it?")) { root.removeChild(errorPage); } } @@ -705,37 +642,32 @@ protected Resource generateNavigation(final String targetDir, final boolean o Map context = CollectionUtils.newHashMap(); context.put("navigation", writer.toString().trim()); - if (this.navigationTemplate == null) - { + if (this.navigationTemplate == null) { loadTemplates(); } - return ScaffoldUtil.createOrOverwrite(this.prompt, (FileResource) getTemplateStrategy() - .getDefaultTemplate(), - this.navigationTemplate.render(context), - overwrite); + return ScaffoldUtil.createOrOverwrite(this.prompt, (FileResource) getTemplateStrategy().getDefaultTemplate(), + this.navigationTemplate.render(context), + overwrite); } /** - * Parses the given XML and determines what namespaces it already declares. These are later removed from the list of - * namespaces that Metawidget introduces. + * Parses the given XML and determines what namespaces it already declares. + * These are later removed from the list of namespaces that Metawidget + * introduces. */ - - protected Map parseNamespaces(final String template) - { + protected Map parseNamespaces(final String template) { Map namespaces = CollectionUtils.newHashMap(); Document document = XmlUtils.documentFromString(template); Element element = document.getDocumentElement(); NamedNodeMap attributes = element.getAttributes(); - for (int loop = 0, length = attributes.getLength(); loop < length; loop++) - { + for (int loop = 0, length = attributes.getLength(); loop < length; loop++) { org.w3c.dom.Node node = attributes.item(loop); String nodeName = node.getNodeName(); int indexOf = nodeName.indexOf(XMLNS_PREFIX); - if (indexOf == -1) - { + if (indexOf == -1) { continue; } @@ -746,18 +678,15 @@ protected Map parseNamespaces(final String template) } /** - * Parses the given XML and determines the indent of the given String namespaces that Metawidget introduces. + * Parses the given XML and determines the indent of the given String + * namespaces that Metawidget introduces. */ - - protected int parseIndent(final String template, final String indentOf) - { + protected int parseIndent(final String template, final String indentOf) { int indent = 0; int indexOf = template.indexOf(indentOf); - while ((indexOf >= 0) && (template.charAt(indexOf) != '\n')) - { - if (template.charAt(indexOf) == '\t') - { + while ((indexOf >= 0) && (template.charAt(indexOf) != '\n')) { + if (template.charAt(indexOf) == '\t') { indent++; } @@ -770,10 +699,8 @@ protected int parseIndent(final String template, final String indentOf) /** * Writes the entity Metawidget and its namespaces into the given context. */ - protected void writeEntityMetawidget(final Map context, final int entityMetawidgetIndent, - final Map existingNamespaces) - { + final Map existingNamespaces) { StringWriter stringWriter = new StringWriter(); this.entityMetawidget.write(stringWriter, entityMetawidgetIndent); context.put("metawidget", stringWriter.toString().trim()); @@ -784,13 +711,12 @@ protected void writeEntityMetawidget(final Map context, final in } /** - * Writes the search Metawidget, the bean Metawidget and their namespaces into the given context. + * Writes the search Metawidget, the bean Metawidget and their namespaces + * into the given context. */ - protected void writeSearchAndBeanMetawidget(final Map context, final int searchMetawidgetIndent, - final int beanMetawidgetIndent, - final Map existingNamespaces) - { + final int beanMetawidgetIndent, + final Map existingNamespaces) { StringWriter stringWriter = new StringWriter(); this.searchMetawidget.write(stringWriter, searchMetawidgetIndent); context.put("searchMetawidget", stringWriter.toString().trim()); @@ -805,12 +731,10 @@ protected void writeSearchAndBeanMetawidget(final Map context, f context.put("metawidgetNamespaces", namespacesToString(namespaces)); } - protected String namespacesToString(final Map namespaces) - { + protected String namespacesToString(final Map namespaces) { StringBuilder builder = new StringBuilder(); - for (Map.Entry entry : namespaces.entrySet()) - { + for (Map.Entry entry : namespaces.entrySet()) { // At the start, break out of the current quote. Field must be in quotes so that we're valid XML builder.append("\"\r\n\txmlns:"); @@ -821,4 +745,42 @@ protected String namespacesToString(final Map namespaces) return builder.toString(); } + + private void setPrimaryKeyMetaData(Map context, final JavaClass entity) { + String pkName = "id"; + String pkType = "Long"; + String nullablePkType = "Long"; + for (Member m : entity.getMembers()) { + if (m.hasAnnotation(Id.class)) { + if (m instanceof Field) { + Field field = (Field) m; + pkName = field.getName(); + pkType = field.getType(); + break; + } else if (m instanceof Member) { + Method method = (Method) m; + pkName = method.getName().substring(3); + if (method.getName().startsWith("get")) { + pkType = method.getReturnType(); + } else { + pkType = ((Parameter) method.getParameters().get(0)).getType(); + } + break; + } + } + } + + if ("int".equals(pkType)) { + nullablePkType = Integer.class.getSimpleName(); + } else if ("short".equals(pkType)) { + nullablePkType = Short.class.getSimpleName(); + } else if ("byte".equals(pkType)) { + nullablePkType = Byte.class.getSimpleName(); + } + + context.put("primaryKey", pkName); + context.put("primaryKeyCC", StringUtils.capitalize(pkName)); + context.put("primaryKeyType", pkType); + context.put("nullablePrimaryKeyType", nullablePkType); + } } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java index 021b410434..5dba48d9ab 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/config/ForgeConfigReader.java @@ -23,6 +23,7 @@ import org.jboss.forge.env.Configuration; import org.jboss.forge.project.Project; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; import org.metawidget.config.impl.BaseConfigReader; /** @@ -42,12 +43,15 @@ public class ForgeConfigReader private static final String PROJECT_ELEMENT_NAME = "forgeProject"; + private static final String ANNOTATION_LOOKUP = "annotationLookup"; + // // Private members // private Configuration config; private Project project; + private AnnotationLookup annotationLookup; // // Constructor @@ -57,6 +61,7 @@ public ForgeConfigReader(Configuration config, Project project) { this.config = config; this.project = project; + this.annotationLookup = new AnnotationLookup(project); } // @@ -66,7 +71,7 @@ public ForgeConfigReader(Configuration config, Project project) @Override protected boolean isNative(String name) { - if (PROJECT_ELEMENT_NAME.equals(name)) + if (PROJECT_ELEMENT_NAME.equals(name) || ANNOTATION_LOOKUP.equals(name)) { return true; } @@ -86,6 +91,9 @@ protected Object createNative(String name, Class namespace, String recordedTe { return this.project; } + if (ANNOTATION_LOOKUP.equals(name)) { + return this.annotationLookup; + } if(CONFIG_ELEMENT_NAME.equals(name)) { @@ -94,4 +102,5 @@ protected Object createNative(String name, Class namespace, String recordedTe return super.createNative(name, namespace, recordedText); } + } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java index a85e7c99ec..6d7ed0c9f4 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectionResultConstants.java @@ -37,6 +37,16 @@ public final class ForgeInspectionResultConstants public static final String ONE_TO_ONE = "one-to-one"; + public static final String PRIMARY_KEY = "primary-key"; + + public static final String PRIMARY_KEY_NOT_GENERATED = "primary-key-not-generated"; + + public static final String ENTITY_PRIMARY_KEY = "entity-primary-key"; + + public static final String REVERSE_PRIMARY_KEY = "reverse-primary-key"; + + public static final String REVERSE_PRIMARY_KEY_TYPE = "reverse-primary-key-type"; + // // Private constructor // diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java index 770581d495..7358571653 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspector.java @@ -21,6 +21,7 @@ */ package org.jboss.forge.scaffold.faces.metawidget.inspector; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; import static org.metawidget.inspector.InspectionResultConstants.*; import static org.metawidget.inspector.faces.StaticFacesInspectionResultConstants.*; @@ -28,15 +29,12 @@ import java.util.List; import java.util.Map; -import javax.persistence.Embedded; -import javax.persistence.ManyToMany; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; +import javax.persistence.*; import org.jboss.forge.parser.java.EnumConstant; import org.jboss.forge.parser.java.JavaEnum; import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyle.ForgeProperty; +import org.jboss.solder.logging.Logger; import org.metawidget.inspector.impl.BaseObjectInspector; import org.metawidget.inspector.impl.BaseObjectInspectorConfig; import org.metawidget.inspector.impl.propertystyle.Property; @@ -50,76 +48,65 @@ * * @author Richard Kennard */ - public class ForgeInspector - extends BaseObjectInspector -{ + extends BaseObjectInspector { + + ForgeInspectorConfig config; + Logger log = Logger.getLogger(getClass()); + // // Constructor // - - public ForgeInspector() - { - this(new BaseObjectInspectorConfig()); + public ForgeInspector() { + super(new BaseObjectInspectorConfig()); } - public ForgeInspector(BaseObjectInspectorConfig config) - { + public ForgeInspector(ForgeInspectorConfig config) { super(config); + this.config = config; } // // Protected methods // - @Override protected Map inspectProperty(Property property) - throws Exception - { + throws Exception { Map attributes = CollectionUtils.newHashMap(); // OneToOne - if (property.isAnnotationPresent(OneToOne.class) || property.isAnnotationPresent(Embedded.class)) - { + if (property.isAnnotationPresent(OneToOne.class) || property.isAnnotationPresent(Embedded.class)) { attributes.put(ONE_TO_ONE, TRUE); } // ManyToOne - if (property.isAnnotationPresent(ManyToOne.class)) - { - attributes - .put(FACES_LOOKUP, - StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property - .getType())) + "Bean.all")); - - attributes - .put(FACES_CONVERTER_ID, - StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property - .getType())) + "Bean.converter")); + if (property.isAnnotationPresent(ManyToOne.class)) { + attributes.put(FACES_LOOKUP, + StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property.getType())) + "Bean.all")); + + attributes.put(FACES_CONVERTER_ID, + StaticFacesUtils.wrapExpression(StringUtils.decapitalize(ClassUtils.getSimpleName(property.getType())) + "Bean.converter")); } // OneToMany and ManyToMany - if (property.isAnnotationPresent(OneToMany.class) || property.isAnnotationPresent(ManyToMany.class)) - { + if (property.isAnnotationPresent(OneToMany.class) || property.isAnnotationPresent(ManyToMany.class)) { attributes.put(N_TO_MANY, TRUE); } // Enums - if ( property instanceof ForgeProperty ) { + if (property instanceof ForgeProperty) { List> enumConstants = ((ForgeProperty) property).getEnumConstants(); - if (enumConstants != null) - { + if (enumConstants != null) { List lookup = CollectionUtils.newArrayList(); - for (EnumConstant anEnum : enumConstants) - { + for (EnumConstant anEnum : enumConstants) { lookup.add(anEnum.getName()); } @@ -127,6 +114,62 @@ protected Map inspectProperty(Property property) } } + // do @Id specific handling + if (null != property.getAnnotation(Id.class)) { + attributes.put(PRIMARY_KEY, property.getName()); + + if (null != property.getAnnotation(GeneratedValue.class)) { + attributes.put(PRIMARY_KEY_NOT_GENERATED, FALSE); + } else { + attributes.put(PRIMARY_KEY_NOT_GENERATED, TRUE); + } + } + + if (null != property.getAnnotation(ManyToOne.class)) { + attributes.put(REVERSE_PRIMARY_KEY_TYPE, property.getType()); + } + + if (attributes.containsKey(PRIMARY_KEY) && !TRUE.equals(attributes.get(PRIMARY_KEY_NOT_GENERATED))) { + // if primary key is not generated it cannot be hidden in view + attributes.remove(HIDDEN); + attributes.put(REQUIRED, TRUE); + } + + if (config != null && config.getAnnotationLookup() != null) { + final AnnotationLookup annotationLookup = config.getAnnotationLookup(); + + if (attributes.containsKey(REVERSE_PRIMARY_KEY_TYPE) && null != annotationLookup) { + try { + final String reverseKey = annotationLookup.getFieldName(Id.class, attributes.get(REVERSE_PRIMARY_KEY_TYPE)); + attributes.put(REVERSE_PRIMARY_KEY, reverseKey); + } catch (Exception e) { + throw new RuntimeException("cannot resolve reverse primary key", e); + } + } + } + + return attributes; + } + + @Override + protected Map inspectEntity(String declaredClass, String actualClass) throws Exception { + Map attributes = CollectionUtils.newHashMap(); + Map superMap = super.inspectEntity(declaredClass, actualClass); + if (superMap != null) + attributes.putAll(superMap); + + if (config != null && config.getAnnotationLookup() != null) { + final AnnotationLookup annotationLookup = config.getAnnotationLookup(); + + try { + final String primaryKey = annotationLookup.getFieldName(Id.class, declaredClass); + attributes.put(PRIMARY_KEY, primaryKey); + } catch (Exception e) { + log.debug("cannot resolve primary key for class "+declaredClass, e); + } + } return attributes; } + + } diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java new file mode 100644 index 0000000000..afe9c572c2 --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorConfig.java @@ -0,0 +1,65 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.metawidget.inspector; + +import org.jboss.forge.project.Project; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; +import org.metawidget.config.iface.NeedsResourceResolver; +import org.metawidget.config.iface.ResourceResolver; +import org.metawidget.inspector.impl.BaseObjectInspectorConfig; + +/** + * + * @author Thomas Frühbeck + */ +public class ForgeInspectorConfig extends BaseObjectInspectorConfig implements NeedsResourceResolver { + + ResourceResolver resolver; + Project project; + AnnotationLookup annotationLookup; + + @Override + public void setResourceResolver(ResourceResolver resourceResolver) { + this.resolver = resourceResolver; + } + + public ResourceResolver getResolver() { + return resolver; + } + + public void setProject(Project project) { + this.project = project; + } + + public Project getProject() { + return project; + } + + public void setAnnotationLookup(AnnotationLookup annotationLookup) { + this.annotationLookup = annotationLookup; + } + + public AnnotationLookup getAnnotationLookup() { + return annotationLookup; + } + +} diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java new file mode 100644 index 0000000000..786066f26f --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/processor/ForgeInspectionResultProcessor.java @@ -0,0 +1,87 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.metawidget.processor; + +import java.util.Map; +import static org.metawidget.inspector.InspectionResultConstants.*; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; +import org.jboss.forge.project.Project; +import org.metawidget.inspectionresultprocessor.iface.InspectionResultProcessor; +import org.metawidget.statically.StaticMetawidget; +import org.metawidget.statically.javacode.StaticJavaMetawidget; +import org.metawidget.util.XmlUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * + * @author Thomas Frühbeck + */ +public class ForgeInspectionResultProcessor implements InspectionResultProcessor { + + private Project project; + + public ForgeInspectionResultProcessor() { + } + + public void setProject(Project project) { + this.project = project; + } + + @Override + public String processInspectionResult(String inspectionResult, StaticMetawidget metawidget, Object toInspect, String type, String... names) { + + Document document = XmlUtils.documentFromString(inspectionResult); + NodeList entities = document.getElementsByTagName(ENTITY); + + if (entities.getLength() > 0) { + for (int i=0; i attributes = XmlUtils.getAttributesAsMap(entity); + + String primaryKey = attributes.get(PRIMARY_KEY); + if (null != primaryKey) { + + NodeList properties = document.getElementsByTagName(PROPERTY); + if (properties.getLength() > 0) { + for (int j=0; j propAttribs = XmlUtils.getAttributesAsMap(property); + propAttribs.put(ENTITY_PRIMARY_KEY, primaryKey); + + XmlUtils.setMapAsAttributes(property, propAttribs); + } + } + } + } + } + + inspectionResult = XmlUtils.documentToString(document, false); + + return inspectionResult; + } + +} diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java index 2c764625f0..4eb9a4293f 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/EntityWidgetBuilder.java @@ -151,10 +151,12 @@ public StaticXmlWidget buildWidget(String elementName, Map attri (StaticUIMetawidget) metawidget); } + String reverseKey = getReversePrimaryKey(attributes); + Param param = new Param(); param.putAttribute("name", "id"); param.putAttribute("value", - StaticFacesUtils.wrapExpression(StaticFacesUtils.unwrapExpression(link.getValue()) + ".id")); + StaticFacesUtils.wrapExpression(StaticFacesUtils.unwrapExpression(link.getValue()) + "." + reverseKey)); link.getChildren().add(param); return link; @@ -257,6 +259,27 @@ public StaticXmlWidget buildWidget(String elementName, Map attri // Protected methods // + protected String getReversePrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(REVERSE_PRIMARY_KEY)) + reverseKey = attributes.get(REVERSE_PRIMARY_KEY); + return reverseKey; + } + + protected String getPrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(PRIMARY_KEY)) + reverseKey = attributes.get(PRIMARY_KEY); + return reverseKey; + } + + protected String getEntityPrimaryKey(Map attributes) { + String reverseKey = "id"; + if (attributes.containsKey(ENTITY_PRIMARY_KEY)) + reverseKey = attributes.get(ENTITY_PRIMARY_KEY); + return reverseKey; + } + /** * Overridden to add row creation/deletion. */ @@ -541,7 +564,7 @@ protected void addColumnComponent(HtmlDataTable dataTable, Map t Param param = new Param(); param.putAttribute("name", "id"); - param.putAttribute("value", StaticFacesUtils.wrapExpression(dataTable.getAttribute("var") + ".id")); + param.putAttribute("value", StaticFacesUtils.wrapExpression(dataTable.getAttribute("var") + "." + getEntityPrimaryKey(columnAttributes))); link.getChildren().add(param); link.getChildren().add(column.getChildren().remove(1)); column.getChildren().add(link); diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java index fc45440967..8517885314 100644 --- a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/metawidget/widgetbuilder/QueryByExampleWidgetBuilder.java @@ -16,6 +16,7 @@ package org.jboss.forge.scaffold.faces.metawidget.widgetbuilder; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; import static org.metawidget.inspector.InspectionResultConstants.*; import static org.metawidget.inspector.faces.StaticFacesInspectionResultConstants.*; @@ -50,7 +51,7 @@ public StaticJavaWidget buildWidget(String elementName, Map attr // Suppress - if (TRUE.equals(attributes.get(HIDDEN))) + if (TRUE.equals(attributes.get(HIDDEN)) && !Boolean.valueOf(attributes.get(PRIMARY_KEY_NOT_GENERATED))) { return new StaticJavaStub(); } @@ -74,13 +75,13 @@ public StaticJavaWidget buildWidget(String elementName, Map attr return toReturn; } - // int + // int or short - if (int.class.equals(clazz)) + if (int.class.equals(clazz) || short.class.equals(clazz) || byte.class.equals(clazz)) { StaticJavaStub toReturn = new StaticJavaStub(); toReturn.getChildren().add( - new JavaStatement("int " + name + " = this.search.get" + StringUtils.capitalize(name) + "()")); + new JavaStatement(clazz.getSimpleName() + " " + name + " = this.search.get" + StringUtils.capitalize(name) + "()")); JavaStatement ifNotEmpty = new JavaStatement("if (" + name + " != 0)"); ifNotEmpty.getChildren().add( new JavaStatement("predicatesList.add(builder.equal(root.get(\"" + name + "\"), " + name + "))")); @@ -108,12 +109,16 @@ public StaticJavaWidget buildWidget(String elementName, Map attr if (attributes.containsKey(FACES_LOOKUP)) { - StaticJavaStub toReturn = new StaticJavaStub(); + String reverseKey = "Id"; + if (attributes.containsKey(REVERSE_PRIMARY_KEY)) + reverseKey = StringUtils.capitalize(attributes.get(REVERSE_PRIMARY_KEY)); + + StaticJavaStub toReturn = new StaticJavaStub(); JavaStatement getValue = new JavaStatement(ClassUtils.getSimpleName(type) + " " + name + " = this.search.get" + StringUtils.capitalize(name) + "()"); getValue.putImport(type); toReturn.getChildren().add(getValue); - JavaStatement ifNotEmpty = new JavaStatement("if (" + name + " != null && " + name + ".getId() != null)"); + JavaStatement ifNotEmpty = new JavaStatement("if (" + name + " != null && " + name + ".get" + reverseKey + "() != null)"); ifNotEmpty.getChildren().add( new JavaStatement("predicatesList.add(builder.equal(root.get(\"" + name + "\"), " + name + "))")); toReturn.getChildren().add(ifNotEmpty); diff --git a/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java new file mode 100644 index 0000000000..cfe2a96fe0 --- /dev/null +++ b/scaffold-faces/src/main/java/org/jboss/forge/scaffold/faces/util/AnnotationLookup.java @@ -0,0 +1,107 @@ +/* + * JBoss, Home of Professional Open Source + * Copyright 2011, Red Hat, Inc., and individual contributors + * by the @authors tag. See the copyright.txt in the distribution for a + * full listing of individual contributors. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + */ +package org.jboss.forge.scaffold.faces.util; + +import java.io.FileNotFoundException; +import org.jboss.forge.parser.java.Field; +import org.jboss.forge.parser.java.JavaSource; +import org.jboss.forge.parser.java.Member; +import org.jboss.forge.parser.java.Method; +import org.jboss.forge.project.Project; +import org.jboss.forge.project.facets.JavaSourceFacet; +import org.metawidget.util.simple.StringUtils; + +/** + * utility for easy lookup of fields or properties in related entities of the domain model + * @author Thomas Frühbeck + */ +public class AnnotationLookup { + + public static final String JAVA_EXTENSION = ".java"; + + private Project project; + + public AnnotationLookup(Project project) { + this.project = project; + } + + /** + * lookup the annotated member of the class + * @param annotation + * @param qualifiedType + * @return + * @throws FileNotFoundException + */ + public Member lookup (Class annotation, String qualifiedType) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaSource javaSource = java.getJavaResource(qualifiedType).getJavaSource(); + + Member member = lookup(javaSource, annotation); + return member; + } + + /** + * convert the member to a field name, assumes JavaBeans notation + * @param member + * @return + */ + public String getFieldName(Member member) { + if (null == member) + return null; + if (member instanceof Method) { + String methodName = member.getName(); + return StringUtils.decapitalize(methodName.substring(3)); + } else if (member instanceof Field) { + return member.getName(); + } + return null; + } + + /** + * get the field name of the annotated member of the class + * @param annotation + * @param qualifiedType + * @return + * @throws FileNotFoundException + */ + public String getFieldName (Class annotation, String qualifiedType) throws FileNotFoundException { + Member member = lookup(annotation, qualifiedType); + return getFieldName(member); + } + + /** + * find a member annotated with this annotation. + * @param javaSource + * @param ann + * @return + */ + public Member lookup(JavaSource javaSource, Class ann) { + //@TODO Is not prepared for multiple PrimKeys + for (Member member : javaSource.getMembers()) { + if (member.hasAnnotation(ann)) { + return member; + } + } + return null; + } + +} diff --git a/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv b/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv index 30c24043da..b706c30032 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv +++ b/scaffold-faces/src/main/resources/scaffold/faces/BackingBean.jv @@ -45,13 +45,13 @@ public class @{entity.getName()}Bean implements Serializable { * Support creating and retrieving @{entity.getName()} entities */ - private Long id; + private @{nullablePrimaryKeyType} id; - public Long getId() { + public @{nullablePrimaryKeyType} getId() { return this.id; } - public void setId(Long id) { + public void setId(@{nullablePrimaryKeyType} id) { this.id = id; } @@ -103,7 +103,7 @@ public class @{entity.getName()}Bean implements Serializable { return "search?faces-redirect=true"; } else { this.entityManager.merge(this.@{ccEntity}); - return "view?faces-redirect=true&id=" + this.@{ccEntity}.getId(); + return "view?faces-redirect=true&id=" + this.@{ccEntity}.get@{primaryKeyCC}(); } } catch( Exception e ) { FacesContext.getCurrentInstance().addMessage(null, new FacesMessage( e.getMessage() )); @@ -234,7 +234,7 @@ public class @{entity.getName()}Bean implements Serializable { return ""; } - return String.valueOf(((@{entity.getName()}) value).getId()); + return String.valueOf(((@{entity.getName()}) value).get@{primaryKeyCC}()); } }; } diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml index 9650a0cd79..32555ce1c4 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-bean.xml @@ -25,10 +25,16 @@ - + + + + + + + @@ -45,7 +51,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml index 8d3c545aea..f03a29a675 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-entity.xml @@ -25,10 +25,16 @@ - + + + + + + + @@ -44,6 +50,16 @@ + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml index 03e3582cc5..90fac2db26 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-qbe.xml @@ -24,10 +24,16 @@ - + + + + + + + @@ -44,7 +50,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml index 69baabe4d8..1e9f8f7c45 100644 --- a/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml +++ b/scaffold-faces/src/main/resources/scaffold/faces/metawidget-search.xml @@ -24,10 +24,16 @@ - + + + + + + + @@ -44,7 +50,17 @@ - + + + + + + + + + + + diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java new file mode 100644 index 0000000000..8d8e7714ad --- /dev/null +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/PrimaryKeyFacesScaffoldTest.java @@ -0,0 +1,242 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.jboss.forge.scaffold.faces; + +import java.io.FileNotFoundException; +import java.io.Serializable; +import java.util.Map; +import javax.inject.Inject; +import javax.persistence.*; +import junit.framework.Assert; +import org.jboss.arquillian.protocol.servlet.arq514hack.descriptors.impl.web.Strings; +import org.jboss.forge.parser.JavaParser; +import org.jboss.forge.parser.java.Field; +import org.jboss.forge.parser.java.JavaClass; +import org.jboss.forge.parser.java.Method; +import org.jboss.forge.parser.java.util.Refactory; +import org.jboss.forge.project.Project; +import org.jboss.forge.project.facets.JavaSourceFacet; +import org.jboss.forge.project.facets.WebResourceFacet; +import org.jboss.forge.project.services.ResourceFactory; +import org.jboss.forge.resources.FileResource; +import org.jboss.forge.resources.java.JavaResource; +import org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspector; +import org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectorConfig; +import org.jboss.forge.scaffold.faces.util.AnnotationLookup; +import org.jboss.forge.shell.util.Streams; +import org.junit.Test; +import org.metawidget.util.XmlUtils; +import org.metawidget.util.simple.StringUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; +import static org.junit.Assert.*; +import static org.jboss.forge.scaffold.faces.metawidget.inspector.ForgeInspectionResultConstants.*; +import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyle; +import org.jboss.forge.scaffold.faces.metawidget.inspector.propertystyle.ForgePropertyStyleConfig; +import org.jboss.forge.scaffold.faces.metawidget.processor.ForgeInspectionResultProcessor; +import static org.metawidget.inspector.InspectionResultConstants.*; + +/** + * + * @author Thomas Frühbeck + */ +public class PrimaryKeyFacesScaffoldTest extends AbstractFacesScaffoldTest { + + @Inject + private ResourceFactory factory; + + @Test + public void testGenerateFromLegacyPrimaryKey() throws Exception { + final String parentPrimaryKey = "parentPrimaryKey"; + final String parentPrimaryKeyCC = StringUtils.capitalize(parentPrimaryKey); + + Project project = setupScaffoldProject(); + + queueInputLines(""); + generateAlternateEntity(project, "com.test.model", "Parent", parentPrimaryKey); + + getShell().execute("entity --named Child"); + getShell().execute("field string --named name"); + getShell().execute("field manyToOne --named parent --fieldType com.test.model.Parent.java --inverseFieldName children"); + + queueInputLines("", "", ""); + getShell().execute("scaffold from-entity com.test.model.* --scaffoldType faces"); + + WebResourceFacet web = project.getFacet(WebResourceFacet.class); + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + // Code + JavaResource parentBean = java.getJavaResource("com.test.view.ParentBean"); + JavaResource childBean = java.getJavaResource("com.test.view.ChildBean"); + + String parentContent = Streams.toString(parentBean.getResourceInputStream()); + assertTrue(parentContent.contains("id=\" + this.parent.get" + parentPrimaryKeyCC + "()")); + assertTrue(parentContent.contains("valueOf(((Parent) value).get" + parentPrimaryKeyCC + "()")); + + String childContent = Streams.toString(childBean.getResourceInputStream()); + assertTrue(childContent.contains("this.child.getId()")); + + // View + FileResource view = web.getWebResource("scaffold/parent/view.xhtml"); + assertTrue(view.exists()); + String contents = Streams.toString(view.getResourceInputStream()); + assertTrue(contents.contains( + "template=\"/resources/scaffold/page.xhtml")); + + view = web.getWebResource("scaffold/parent/search.xhtml"); + contents = Streams.toString(view.getResourceInputStream()); + assertTrue(view.exists()); + assertTrue(contents.contains("")); + + view = web.getWebResource("scaffold/child/view.xhtml"); + contents = Streams.toString(view.getResourceInputStream()); + assertTrue(view.exists()); + assertTrue(contents.contains("childBean.child.parent." + parentPrimaryKey)); +} + + private JavaResource generateAlternateEntity(Project project, String pkg, String entityName, String primaryKey) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaClass javaClass = JavaParser.create(JavaClass.class).setPackage(pkg).setName(entityName).setPublic().addAnnotation(Entity.class).getOrigin().addInterface(Serializable.class); + + String idName = primaryKey; + if (idName == null) { + StringUtils.decapitalize(entityName + "Id"); + } + + Field id = javaClass.addField("private String " + idName + " = null;"); + id.addAnnotation(Id.class); + id.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + id.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + + Refactory.createGetterAndSetter(javaClass, id); + + Field name = javaClass.addField("private String name = null;"); + Refactory.createGetterAndSetter(javaClass, name); + + Refactory.createToStringFromFields(javaClass, id); + Refactory.createHashCodeAndEquals(javaClass); + + return java.saveJavaSource(javaClass); + } + + @Test + public void testPrimaryKeys() throws Exception { + Project project = initializeJavaProject(); + queueInputLines("HIBERNATE", "JBOSS_AS7", ""); + getShell().execute("persistence setup"); + + for (PrimaryKeyTestBase testClass : new PrimaryKeyTestBase[]{ + new PrimaryKeyFieldTest(), new PrimaryKeyPropertyTest(), new PrimaryKeyPropertyAssignedTest()}) { + testPrimaryKey(project, testClass); + } + } + + public void testPrimaryKey(Project project, PrimaryKeyTestBase testClass) throws Exception { + + final String parentPrimaryKey = "primaryKey"; + final String parentPrimaryKeyCC = StringUtils.capitalize(parentPrimaryKey); + + ForgeInspectorConfig config = new ForgeInspectorConfig(); + config.setAnnotationLookup(new AnnotationLookup(project)); + config.setPropertyStyle(new ForgePropertyStyle(new ForgePropertyStyleConfig().setProject(project))); + ForgeInspectionResultProcessor processor = new ForgeInspectionResultProcessor(); + + generatePkEntity(project, "org.test", "Parent", parentPrimaryKey, testClass); + + String xml = new ForgeInspector(config).inspect(null, "org.test.Parent"); + xml = processor.processInspectionResult(xml, null, project, xml, new String[]{}); + + Document document = XmlUtils.documentFromString(xml); + assertEquals("inspection-result", document.getFirstChild().getNodeName()); + Element entity = (Element) document.getFirstChild().getFirstChild(); + assertEquals(ENTITY, entity.getNodeName()); + + Map attributes = XmlUtils.getAttributesAsMap(entity); + assertEquals(parentPrimaryKey, attributes.get(PRIMARY_KEY)); + + NodeList properties = entity.getElementsByTagName(PROPERTY); + for (int i = 0; i < properties.getLength(); i++) { + Element prop = (Element) properties.item(i); + attributes = XmlUtils.getAttributesAsMap(prop); + + if (!(testClass instanceof PrimaryKeyPropertyAssignedTest)) { + assertTrue(attributes.containsKey(PRIMARY_KEY_NOT_GENERATED)); + } + } + Element property = (Element) entity.getFirstChild(); + attributes = XmlUtils.getAttributesAsMap(property); + assertEquals(parentPrimaryKey, attributes.get(PRIMARY_KEY)); + assertEquals(parentPrimaryKey, attributes.get(ENTITY_PRIMARY_KEY)); + + } + + private JavaResource generatePkEntity(Project project, String pkg, String entityName, String primaryKey, PrimaryKeyTestBase pkTest) throws FileNotFoundException { + JavaSourceFacet java = project.getFacet(JavaSourceFacet.class); + JavaClass javaClass = JavaParser.create(JavaClass.class).setPackage(pkg).setName(entityName).setPublic().addAnnotation(Entity.class).getOrigin().addInterface(Serializable.class); + + String idName = primaryKey; + if (idName == null) { + StringUtils.decapitalize(entityName + "Id"); + } + + Field id = javaClass.addField("private String " + idName + " = null;"); + if (pkTest.field) { + id.addAnnotation(Id.class); + if (pkTest.generated) { + id.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + id.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + } + } + + + + Refactory.createGetterAndSetter(javaClass, id); + if (!pkTest.field) { + Method getPk = javaClass.getMethod("get" + StringUtils.capitalize(idName)); + getPk.addAnnotation(Id.class); + if (pkTest.generated) { + getPk.addAnnotation(GeneratedValue.class).setEnumValue("strategy", GenerationType.AUTO); + getPk.addAnnotation(Column.class).setStringValue("name", idName).setLiteralValue("updatable", "false").setLiteralValue("nullable", "false"); + } + } + + Field name = javaClass.addField("private String name = null;"); + Refactory.createGetterAndSetter(javaClass, name); + Field type = javaClass.addField("private String type = null;"); + Refactory.createGetterAndSetter(javaClass, type); + + return java.saveJavaSource(javaClass); + } + + + class PrimaryKeyTestBase { + + public boolean generated, field; + } + + class PrimaryKeyFieldTest extends PrimaryKeyTestBase { + + { + generated = true; + field = true; + } + } + + class PrimaryKeyPropertyTest extends PrimaryKeyTestBase { + + { + generated = true; + field = false; + } + } + + class PrimaryKeyPropertyAssignedTest extends PrimaryKeyTestBase { + + { + generated = false; + field = true; + } + } +} diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java index 1e5280b052..e1accb29af 100644 --- a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/metawidget/inspector/ForgeInspectorTest.java @@ -72,7 +72,7 @@ public void testRelationships() assertEquals("manyToOne", property.getAttribute(NAME)); assertEquals("#{forgeInspectorTest$BarBean.all}", property.getAttribute(FACES_LOOKUP)); assertEquals("#{forgeInspectorTest$BarBean.converter}", property.getAttribute(FACES_CONVERTER_ID)); - assertEquals(3, property.getAttributes().getLength()); + assertEquals(4, property.getAttributes().getLength()); property = XmlUtils.getNextSiblingElement(property); assertEquals(PROPERTY, property.getNodeName()); diff --git a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java index 6375df30ac..38142d22f4 100644 --- a/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java +++ b/scaffold-faces/src/test/java/org/jboss/forge/scaffold/faces/scenario/petclinic/FacesScaffoldPetClinicTest.java @@ -54,7 +54,8 @@ public class FacesScaffoldPetClinicTest extends AbstractFacesScaffoldTest public void testGenerate() throws Exception { Project current = getShell().getCurrentProject(); - Project project = setupScaffoldProject("petClinic"); + final String targetDir = "petClinic"; + Project project = setupScaffoldProject(targetDir); queueInputLines(""); getShell().execute("entity --named Owner"); @@ -97,7 +98,7 @@ public void testGenerate() throws Exception // Check search screen has h:message - FileResource search = web.getWebResource("scaffold/pet/search.xhtml"); + FileResource search = web.getWebResource(targetDir+"/pet/search.xhtml"); Assert.assertTrue(search.exists()); String contents = Streams.toString(search.getResourceInputStream()); @@ -111,14 +112,14 @@ public void testGenerate() throws Exception // Check search screen has boolean graphic - metawidget = "\t\t\t\t\t\r\n"; + metawidget = "\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\r\n"; Assert.assertTrue(contents.contains(metawidget)); - metawidget = "\t\t\t\t\t\r\n"; + metawidget = "\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\t\r\n"; metawidget += "\t\t\t\t\t\r\n"; @@ -127,7 +128,7 @@ public void testGenerate() throws Exception // Check create screen has h:selectBooleanCheckbox - FileResource create = web.getWebResource("scaffold/pet/create.xhtml"); + FileResource create = web.getWebResource(targetDir+"/pet/create.xhtml"); Assert.assertTrue(create.exists()); contents = Streams.toString(create.getResourceInputStream()); @@ -141,7 +142,7 @@ public void testGenerate() throws Exception // Check view screen has boolean graphic - FileResource view = web.getWebResource("scaffold/pet/view.xhtml"); + FileResource view = web.getWebResource(targetDir+"/pet/view.xhtml"); Assert.assertTrue(view.exists()); contents = Streams.toString(view.getResourceInputStream());