Java tutorial
/* * Copyright 2011 - DigitalFace.ca. All Rights Reserved * Licensed under the GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 (http://www.gnu.org/licenses/gpl.txt). */ package ca.digitalface.jasperoo; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.StringWriter; import java.io.Writer; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import java.util.StringTokenizer; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; import org.jvnet.inflector.Noun; import org.osgi.service.component.ComponentContext; import org.springframework.roo.classpath.PhysicalTypeDetails; import org.springframework.roo.classpath.PhysicalTypeIdentifier; import org.springframework.roo.classpath.PhysicalTypeMetadata; import org.springframework.roo.classpath.PhysicalTypeMetadataProvider; import org.springframework.roo.classpath.TypeLocationService; import org.springframework.roo.classpath.details.annotations.AnnotationMetadataBuilder; import org.springframework.roo.classpath.details.FieldMetadata; import org.springframework.roo.classpath.details.MemberFindingUtils; import org.springframework.roo.classpath.details.MutableClassOrInterfaceTypeDetails; import org.springframework.roo.metadata.MetadataService; import org.springframework.roo.model.JavaPackage; import org.springframework.roo.model.JavaSymbolName; import org.springframework.roo.model.JavaType; import org.springframework.roo.process.manager.FileManager; import org.springframework.roo.process.manager.MutableFile; import org.springframework.roo.project.Dependency; import org.springframework.roo.project.Path; import org.springframework.roo.project.PathResolver; import org.springframework.roo.project.ProjectMetadata; import org.springframework.roo.project.ProjectOperations; import org.springframework.roo.shell.Shell; import org.springframework.roo.support.util.Assert; import org.springframework.roo.support.util.StringUtils; import org.springframework.roo.support.util.TemplateUtils; import org.springframework.roo.support.util.XmlElementBuilder; import org.springframework.roo.support.util.XmlUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import ca.digitalface.jasperoo.utils.TokenReplacementFileCopyUtils; /** * Implementation of Jasperoo Operations. * * @since 1.1 */ @Component @Service public class JasperooOperationsImpl implements JasperooOperations { /** * MetadataService offers access to Roo's metadata model, use it to retrieve * any available metadata by its MID */ @Reference private MetadataService metadataService; /** * Use the PhysicalTypeMetadataProvider to access information about a * physical type in the project */ @Reference private PhysicalTypeMetadataProvider physicalTypeMetadataProvider; /** * Use ProjectOperations to install new dependencies, plugins, properties, * etc into the project configuration */ @Reference private ProjectOperations projectOperations; /** * Use TypeLocationService to find types which are annotated with a given * annotation in the project */ @Reference private TypeLocationService typeLocationService; /** * Use the FileManager to manipulate the files in the target project. */ @Reference private FileManager fileManager; /** * Use the PathResolver to facilitate access to the various project source areas of the target project. */ @Reference private PathResolver pathResolver; /** * The is the Roo shell. */ @Reference private Shell shell; // Use the Unix separator as we are using this to retrieve files with the classloader. (Was File.separatorChar) private static char separator = '/'; private ComponentContext context; protected void activate(ComponentContext context) { this.context = context; } /** * Entity types not in this list will be converted to String by default in the report. */ private static String[] jasperFacetValidTypes = new String[] { "java.lang.Boolean", "java.lang.Byte", "java.util.Date", "java.sql.Timestamp", "java.sql.Time", "java.lang.Double", "java.lang.Float", "java.lang.Integer", "java.lang.Long", "java.lang.Short", "java.math.BigDecimal", "java.lang.Number", "java.lang.String" }; private static String[] validReportFormats = new String[] { "csv", "html", "odt", "pdf", "rtf", "xls", "xml" }; /** {@inheritDoc} */ public boolean isCommandAvailable(String commandName) { boolean bReady = false; bReady = projectOperations.isProjectAvailable(); return bReady; } /** {@inheritDoc} */ public void addReportByType(JavaType javaType, String finder, String entityPackage, String controllerPackage) { // Use Roo's Assert type for null checks Assert.notNull(javaType, "Java type required"); String id = physicalTypeMetadataProvider.findIdentifier(javaType); if (id == null) { throw new IllegalArgumentException( "Cannot locate source for '" + javaType.getFullyQualifiedTypeName() + "'"); } // Obtain the physical type and itd mutable details PhysicalTypeMetadata ptm = (PhysicalTypeMetadata) metadataService.get(id); Assert.notNull(ptm, "Java source code unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(id)); PhysicalTypeDetails ptd = ptm.getMemberHoldingTypeDetails(); Assert.notNull(ptd, "Java source code details unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(id)); Assert.isInstanceOf(MutableClassOrInterfaceTypeDetails.class, ptd, "Java source code is immutable for type " + PhysicalTypeIdentifier.getFriendlyName(id)); MutableClassOrInterfaceTypeDetails mutableTypeDetails = (MutableClassOrInterfaceTypeDetails) ptd; if (null == MemberFindingUtils.getAnnotationOfType(mutableTypeDetails.getAnnotations(), new JavaType(RooJasperoo.class.getName()))) { JavaType rooJasperoo = new JavaType(RooJasperoo.class.getName()); if (!mutableTypeDetails.getAnnotations().contains(rooJasperoo)) { AnnotationMetadataBuilder annotationBuilder = new AnnotationMetadataBuilder(rooJasperoo); mutableTypeDetails.addTypeAnnotation(annotationBuilder.build()); } } // Compute the Fully Qualified Name for the source JavaType String fqEntityName = physicalTypeMetadataProvider.findIdentifier(javaType); if (fqEntityName == null) { throw new IllegalArgumentException( "Cannot locate source for '" + javaType.getFullyQualifiedTypeName() + "'"); } // The entity name is used all over. String entityName = fqEntityName.substring(fqEntityName.lastIndexOf(".") + 1); shell.executeCommand("focus --class " + entityPackage + "." + entityName); shell.executeCommand("finder add --finderName find" + getPlural(entityName) + "ById"); // copy templates, copy jrxml, update ReportController, update // views.properties, insert i18n messages copyAddFilesIntoProject(entityName, finder, entityPackage, controllerPackage); //manipulate report templates modifyListReportTemplate(javaType, entityName); modifyDetailReportTemplate(javaType, entityName); /* * We probably don't want this, but we won't remove it permanently until we're sure. * // generate menu entry * addMenuEntry(entityName.toLowerCase()); * insertI18nAddMessages(entityName); */ } /** {@inheritDoc} */ public void addReportsForAll(String entityPackage, String controllerPackage) { // Use the TypeLocationService to scan project for all types with a // specific annotation for (JavaType type : typeLocationService .findTypesWithAnnotation(new JavaType("org.springframework.roo.addon.javabean.RooJavaBean"))) { addReportByType(type, null, entityPackage, controllerPackage); } } /** {@inheritDoc} */ public void extend(String formats) { if (StringUtils.hasText(formats)) { StringTokenizer stFormats = new StringTokenizer(formats, ",", false); while (stFormats.hasMoreTokens()) { String format = stFormats.nextToken().trim(); if (Arrays.asList(validReportFormats).contains(format)) { modifyListTagx(format); modifyShowTagx(format); } else { System.out.println( "JASPEROO: '" + format + "' is not a valid report format, it will be ignored."); } } } } /** {@inheritDoc} */ public void setup(String controllerPackage, String formats) { // Add all new dependencies to pom.xml projectOperations .addDependency(new Dependency("org.springframework", "spring-context", "${spring.version}")); projectOperations.addDependency(new Dependency("jasperreports", "jasperreports", "3.5.3")); projectOperations.addDependency(new Dependency("org.apache.poi", "poi", "3.2-FINAL")); projectOperations.addDependency(new Dependency("org.springframework.roo.wrapping", "org.springframework.roo.wrapping.inflector", "0.7.0.0001")); String currentJasperooVersion = context.getBundleContext().getBundle().getHeaders().get("Bundle-Version") .toString(); projectOperations .addDependency(new Dependency("ca.digitalface", "ca.digitalface.jasperoo", currentJasperooVersion)); //add pluginNode to pom String pomPath = pathResolver.getIdentifier(Path.ROOT, "pom.xml"); MutableFile mutablePomXml = null; Document pomDoc; try { if (fileManager.exists(pomPath)) { mutablePomXml = fileManager.updateFile(pomPath); pomDoc = XmlUtils.getDocumentBuilder().parse(mutablePomXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + pomPath); } } catch (Exception e) { throw new IllegalStateException(e); } Element pluginNode = new XmlElementBuilder("plugin", pomDoc) .addChild(new XmlElementBuilder("groupId", pomDoc).setText("org.codehaus.mojo").build()) .addChild(new XmlElementBuilder("artifactId", pomDoc).setText("jasperreports-maven-plugin").build()) .addChild(new XmlElementBuilder("configuration", pomDoc) .addChild(new XmlElementBuilder("sourceDirectory", pomDoc) .setText("src/main/webapp/WEB-INF/reports").build()) .addChild(new XmlElementBuilder("outputDirectory", pomDoc) .setText("src/main/webapp/WEB-INF/reports").build()) .build()) .addChild(new XmlElementBuilder("executions", pomDoc) .addChild(new XmlElementBuilder("execution", pomDoc) .addChild(new XmlElementBuilder("phase", pomDoc).setText("compile").build()) .addChild(new XmlElementBuilder("goals", pomDoc).addChild( new XmlElementBuilder("goal", pomDoc).setText("compile-reports").build()) .build()) .build()) .build()) .addChild( new XmlElementBuilder("dependencies", pomDoc) .addChild(new XmlElementBuilder("dependency", pomDoc) .addChild(new XmlElementBuilder("groupId", pomDoc).setText("jasperreports") .build()) .addChild(new XmlElementBuilder("artifactId", pomDoc) .setText("jasperreports").build()) .addChild(new XmlElementBuilder("version", pomDoc).setText("3.5.3").build()) .build()) .addChild(new XmlElementBuilder("dependency", pomDoc) .addChild(new XmlElementBuilder("groupId", pomDoc) .setText("org.apache.log4j").build()) .addChild(new XmlElementBuilder("artifactId", pomDoc) .setText("com.springsource.org.apache.log4j").build()) .addChild( new XmlElementBuilder("version", pomDoc).setText("1.2.15").build()) .build()) .build()) .build(); Node pluginsNode = pomDoc.getDocumentElement().getElementsByTagName("plugins").item(0); pluginsNode.appendChild(pluginNode); XmlUtils.writeXml(mutablePomXml.getOutputStream(), pomDoc); //add jasperReportsMultiFormatView to applicationContext String applicationContext = pathResolver.getIdentifier(Path.SRC_MAIN_RESOURCES, "META-INF/spring/applicationContext.xml"); MutableFile mutableConfigXml = null; Document webConfigDoc; try { if (fileManager.exists(applicationContext)) { mutableConfigXml = fileManager.updateFile(applicationContext); webConfigDoc = XmlUtils.getDocumentBuilder().parse(mutableConfigXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + applicationContext); } } catch (Exception e) { throw new IllegalStateException(e); } Element jasperReportsMultiFormatView = new XmlElementBuilder("bean", webConfigDoc) .addAttribute("id", "jasperReportsMultiFormatView") .addAttribute("name", "jasperReportsMultiFormatViewBean") .addAttribute("class", "ca.digitalface.jasperoo.reports.CustomJasperReportsMultiFormatView") .build(); webConfigDoc.getDocumentElement().appendChild(jasperReportsMultiFormatView); XmlUtils.writeXml(mutableConfigXml.getOutputStream(), webConfigDoc); String webMVCConfig = pathResolver.getIdentifier(Path.SRC_MAIN_RESOURCES, "META-INF/spring/applicationContext.xml"); MutableFile mutableWebMVCConfig = null; Document webMVCConfigDoc; try { if (fileManager.exists(webMVCConfig)) { mutableWebMVCConfig = fileManager.updateFile(webMVCConfig); webMVCConfigDoc = XmlUtils.getDocumentBuilder().parse(mutableWebMVCConfig.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + webMVCConfig); } } catch (Exception e) { throw new IllegalStateException(e); } Element viewResolver = new XmlElementBuilder("bean", webMVCConfigDoc).addAttribute("id", "viewResolver") .addAttribute("class", "org.springframework.web.servlet.view.ResourceBundleViewResolver") .addChild(new XmlElementBuilder("property", webMVCConfigDoc).addAttribute("name", "basename") .addAttribute("value", "views").build()) .build(); webMVCConfigDoc.getDocumentElement().appendChild(viewResolver); XmlUtils.writeXml(mutableWebMVCConfig.getOutputStream(), webMVCConfigDoc); //create Report Controller shell.executeCommand("class --class ~.web.ReportController"); //copy templates/files String classesFolder = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/classes"); if (!fileManager.exists(classesFolder)) { fileManager.createDirectory(classesFolder); } String viewsProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/classes/views.properties"); if (!fileManager.exists(viewsProperties)) { fileManager.createFile(viewsProperties); } String reportsFolder = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/reports"); if (!fileManager.exists(reportsFolder)) { fileManager.createDirectory(reportsFolder); } copySetupFilesIntoProject(controllerPackage); setupListTagx(); extend(formats); } /** * Populates the host project with the files required to setup the addon, and calls for the insertion of the requires i18n messages. * * @param controllerPackage The location of the Web Controllers. Default: "~.web" */ private void copySetupFilesIntoProject(String controllerPackage) { ProjectMetadata projectMetadata = (ProjectMetadata) metadataService .get(ProjectMetadata.getProjectIdentifier()); JavaPackage topLevelPackage = projectMetadata.getTopLevelPackage(); String finalControllerPackage = controllerPackage.replace("~", topLevelPackage.getFullyQualifiedPackageName()); String reportsJavaFolder = "ca.digitalface.jasperoo.reports"; Properties properties = new Properties(); properties.put("__TOP_LEVEL_PACKAGE__", topLevelPackage.getFullyQualifiedPackageName()); properties.put("__CONTROLLER_PACKAGE__", finalControllerPackage); Map<String, String> templateMap = new HashMap<String, String>(); templateMap.put( pathResolver.getIdentifier(Path.SRC_MAIN_JAVA, reportsJavaFolder.replace('.', separator) + separator + "CustomJasperReportsMultiFormatView.java"), "CustomJasperReportsMultiFormatView.java-template"); templateMap.put( pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF" + separator + "classes" + separator + "jasperoo.properties"), "jasperoo.properties-template"); templateMap.put( pathResolver.getIdentifier(Path.SRC_MAIN_JAVA, finalControllerPackage.replace('.', separator) + separator + "ReportController.java"), "ReportController.java-template"); for (Entry<String, String> template : templateMap.entrySet()) { MutableFile mutableFile = null; String path = template.getKey(); String file = template.getValue(); try { if (fileManager.exists(path)) mutableFile = fileManager.updateFile(path); else mutableFile = fileManager.createFile(path); TokenReplacementFileCopyUtils.replaceAndCopy(TemplateUtils.getTemplate(getClass(), file), mutableFile.getOutputStream(), properties); } catch (IOException ioe) { throw new IllegalStateException(ioe); } } insertI18nSetupMessages(); Map<String, String> imageMap = new HashMap<String, String>(); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-csv.png"), "images" + separator + "report-csv.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-html.png"), "images" + separator + "report-html.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-list.png"), "images" + separator + "report-list.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-odt.png"), "images" + separator + "report-odt.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-pdf.png"), "images" + separator + "report-pdf.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-rtf.png"), "images" + separator + "report-rtf.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-xls.png"), "images" + separator + "report-xls.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report-xml.png"), "images" + separator + "report-xml.png"); imageMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "images" + separator + "report.png"), "images" + separator + "report.png"); for (Entry<String, String> image : imageMap.entrySet()) { String path = image.getKey(); String file = image.getValue(); try { File target = new File(path); FileOutputStream fosTarget = new FileOutputStream(target); TokenReplacementFileCopyUtils.replaceAndCopy(TemplateUtils.getTemplate(getClass(), file), fosTarget); } catch (IOException ioe) { throw new IllegalStateException(ioe); } } } /** * Copies the files required for the requested report, updates the * ReportController declares the new views required by the requested report * and inserted the required i18n messages. * * @param entityName The name of the entity being added. * @param finder The finder to use to generate the recordset. * @param entityPackage The location of the Entities. Default: "~.domain". * @param controllerPackage The location of the Web Controllers. Default: "~.web" */ private void copyAddFilesIntoProject(String entityName, String finder, String entityPackage, String controllerPackage) { ProjectMetadata projectMetadata = (ProjectMetadata) metadataService .get(ProjectMetadata.getProjectIdentifier()); JavaPackage topLevelPackage = projectMetadata.getTopLevelPackage(); String finalEntityPackage = entityPackage.replace("~", topLevelPackage.getFullyQualifiedPackageName()); String listReportTitle = "label_" + finalEntityPackage.replace(".", "_") + "_" + entityName.toLowerCase() + "_plural"; String detailReportTitle = "label_" + finalEntityPackage.replace(".", "_") + "_" + entityName.toLowerCase(); String finalControllerPackage = controllerPackage.replace("~", topLevelPackage.getFullyQualifiedPackageName()); Properties properties = new Properties(); properties.put("__TOP_LEVEL_PACKAGE__", topLevelPackage.getFullyQualifiedPackageName()); properties.put("__ENTITY_LEVEL_PACKAGE__", finalEntityPackage); properties.put("__ENTITY_NAME__", entityName); properties.put("__ENTITY_NAME_LOWER__", entityName.toLowerCase()); properties.put("__LIST_REPORT_TITLE__", listReportTitle); properties.put("__DETAIL_REPORT_TITLE__", detailReportTitle); properties.put("__CONTROLLER_PACKAGE__", finalControllerPackage); Map<String, String> templateMap = new HashMap<String, String>(); templateMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF" + separator + "reports" + separator + entityName.toLowerCase() + "ReportList.jrxml"), "reportList.jrxml-template"); templateMap.put(pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF" + separator + "reports" + separator + entityName.toLowerCase() + "ReportDetail.jrxml"), "reportDetail.jrxml-template"); for (Entry<String, String> entry : templateMap.entrySet()) { MutableFile mutableFile = null; String path = entry.getKey(); String file = entry.getValue(); try { if (fileManager.exists(path)) mutableFile = fileManager.updateFile(path); else mutableFile = fileManager.createFile(path); TokenReplacementFileCopyUtils.replaceAndCopy(TemplateUtils.getTemplate(getClass(), file), mutableFile.getOutputStream(), properties); } catch (IOException ioe) { throw new IllegalStateException(ioe); } } insertViewDeclarations(entityName); insertJasperooMessages(listReportTitle, getPlural(entityName)); insertJasperooMessages(detailReportTitle, entityName); modifyReportController(entityName, finder, finalEntityPackage, finalControllerPackage); } /** * Each report is a new view, here, the required views are declared in the views.properties. * * @param entityName The Object upon which the report is based. */ private void insertViewDeclarations(String entityName) { String applicationProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/classes/views.properties"); MutableFile mutableApplicationProperties = null; try { if (fileManager.exists(applicationProperties)) { mutableApplicationProperties = fileManager.updateFile(applicationProperties); String originalData = convertStreamToString(mutableApplicationProperties.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableApplicationProperties.getOutputStream())); out.write(originalData); out.write(entityName.toLowerCase() + "ReportList.url=/WEB-INF/reports/" + entityName.toLowerCase() + "ReportList.jasper\n"); out.write(entityName.toLowerCase() + "ReportList.(class)=ca.digitalface.jasperoo.reports.CustomJasperReportsMultiFormatView\n"); out.write(entityName.toLowerCase() + "ReportDetail.url=/WEB-INF/reports/" + entityName.toLowerCase() + "ReportDetail.jasper\n"); out.write(entityName.toLowerCase() + "ReportDetail.(class)=ca.digitalface.jasperoo.reports.CustomJasperReportsMultiFormatView\n"); out.close(); } else { throw new IllegalStateException("Could not acquire " + applicationProperties); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } } /** * Modifies the "List" report template to add all of the fields in the * entity being listed. * * @param javaType The JavaType of the entity being listed. * @param entityName The name of the entity being listed. */ private void modifyDetailReportTemplate(JavaType javaType, String entityName) { String reportPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/reports/" + entityName.toLowerCase() + "ReportDetail.jrxml"); MutableFile mutableReportXml = null; Document reportDoc; try { if (fileManager.exists(reportPath)) { mutableReportXml = fileManager.updateFile(reportPath); reportDoc = XmlUtils.getDocumentBuilder().parse(mutableReportXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + reportPath); } } catch (Exception e) { throw new IllegalStateException(e); } Element detailNode = (Element) reportDoc.getDocumentElement().getElementsByTagName("detail").item(0); Node detailBand = XmlUtils.findFirstElementByName("band", detailNode); // The id field is 20 px high, so we start there and add the field width on each pass. int offsetY = 20; // determine the total number of fields int fieldCount = getJavaTypeDetails(javaType).getDeclaredFields().size(); MutableClassOrInterfaceTypeDetails details = getJavaTypeDetails(javaType); List<JavaType> extendsTypes = details.getExtendsTypes(); // We need to know how many fields can be accessed from the hierarchy of this class. // Unfortunately, the list that comes back from getDeclaredFields is an "unmodifiableList", // so we can't just concatenate all lists and iterate through a super-list. boolean bExtender = extendsTypes != null && extendsTypes.size() > 0; while (bExtender) { JavaType tempType = details.getExtendsTypes().get(0); List<? extends FieldMetadata> fields = getJavaTypeDetails(tempType).getDeclaredFields(); fieldCount = fieldCount + fields.size(); details = getJavaTypeDetails(tempType); extendsTypes = details.getExtendsTypes(); bExtender = extendsTypes != null && extendsTypes.size() > 0; } details = getJavaTypeDetails(javaType); List<? extends FieldMetadata> fields = getJavaTypeDetails(javaType).getDeclaredFields(); bExtender = true; while (bExtender) { int fieldHeight = (641 - 20) / fieldCount; if (fieldHeight > 20) { fieldHeight = 20; } for (FieldMetadata fieldMetadata : fields) { JavaType fieldType = fieldMetadata.getFieldType(); boolean bValidType = Arrays.asList(jasperFacetValidTypes) .contains(fieldType.getFullyQualifiedTypeName()); JavaSymbolName fieldName = fieldMetadata.getFieldName(); insertJasperooMessages("jasperoo." + getPlural(entityName) + "." + fieldName.getSymbolName(), fieldName.getReadableSymbolName()); Element pageHeaderNode = XmlUtils.findFirstElementByName("pageHeader", reportDoc.getDocumentElement()); Element fieldNode = new XmlElementBuilder("field", reportDoc) .addAttribute("name", fieldName.getSymbolName()) .addAttribute("class", fieldType.getFullyQualifiedTypeName()).build(); reportDoc.getDocumentElement().insertBefore(fieldNode, pageHeaderNode); if (!bValidType) { Element firstFieldNode = XmlUtils.findFirstElementByName("field", reportDoc.getDocumentElement()); Element importNode = new XmlElementBuilder("import", reportDoc) .addAttribute("value", fieldType.getFullyQualifiedTypeName()).build(); reportDoc.getDocumentElement().insertBefore(importNode, firstFieldNode); } Element headerTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc).addAttribute("x", "0") .addAttribute("y", String.valueOf(offsetY)).addAttribute("width", "125") .addAttribute("height", String.valueOf(fieldHeight)).build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild( new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", "java.lang.String").setText("$R{jasperoo." + getPlural(entityName) + "." + fieldName.getSymbolName() + "}") .build()) .build(); detailBand.appendChild(headerTextfield); Element detailTextfield = null; if (bValidType) { detailTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc).addAttribute("x", "126") .addAttribute("y", String.valueOf(offsetY)).addAttribute("width", "446") .addAttribute("height", String.valueOf(fieldHeight)).build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild(new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", fieldType.getFullyQualifiedTypeName()) .setText("$F{" + fieldName.getSymbolName() + "}").build()) .build(); } else { detailTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc).addAttribute("x", "126") .addAttribute("y", String.valueOf(offsetY)).addAttribute("width", "446") .addAttribute("height", String.valueOf(fieldHeight)).build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild(new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", "java.lang.String") .setText("$F{" + fieldName.getSymbolName() + "}.toString()").build()) .build(); } detailBand.appendChild(detailTextfield); offsetY += fieldHeight; } // Do we keep going? extendsTypes = details.getExtendsTypes(); bExtender = extendsTypes != null && extendsTypes.size() > 0; if (bExtender) { JavaType tempType = details.getExtendsTypes().get(0); details = getJavaTypeDetails(tempType); fields = details.getDeclaredFields(); } } XmlUtils.writeXml(mutableReportXml.getOutputStream(), reportDoc); } /** * Modifies the "List" report template to add all of the fields in the * entity being listed. * * @param javaType The JavaType of the entity being listed. * @param entityName The name of the entity being listed. */ private void modifyListReportTemplate(JavaType javaType, String entityName) { String reportPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/reports/" + entityName.toLowerCase() + "ReportList.jrxml"); MutableFile mutableReportXml = null; Document reportDoc; try { if (fileManager.exists(reportPath)) { mutableReportXml = fileManager.updateFile(reportPath); reportDoc = XmlUtils.getDocumentBuilder().parse(mutableReportXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + reportPath); } } catch (Exception e) { throw new IllegalStateException(e); } Element columnHeaderNode = (Element) reportDoc.getDocumentElement().getElementsByTagName("columnHeader") .item(0); Element columnHeaderBand = XmlUtils.findFirstElementByName("band", columnHeaderNode); Element detailNode = (Element) reportDoc.getDocumentElement().getElementsByTagName("detail").item(0); Node detailBand = XmlUtils.findFirstElementByName("band", detailNode); // The id field is 30 px wide, so we start there and add the field width on each pass. int offsetX = 30; // determine the total number of fields int fieldCount = getJavaTypeDetails(javaType).getDeclaredFields().size(); MutableClassOrInterfaceTypeDetails details = getJavaTypeDetails(javaType); List<JavaType> extendsTypes = details.getExtendsTypes(); // We need to know how many fields can be accessed from the hierarchy of this class. // Unfortunately, the list that comes back from getDeclaredFields is an "unmodifiableList", // so we can't just concatenate all lists and iterate through a super-list. boolean bExtender = extendsTypes != null && extendsTypes.size() > 0; while (bExtender) { JavaType tempType = details.getExtendsTypes().get(0); List<? extends FieldMetadata> fields = getJavaTypeDetails(tempType).getDeclaredFields(); fieldCount = fieldCount + fields.size(); details = getJavaTypeDetails(tempType); extendsTypes = details.getExtendsTypes(); bExtender = extendsTypes != null && extendsTypes.size() > 0; } details = getJavaTypeDetails(javaType); List<? extends FieldMetadata> fields = getJavaTypeDetails(javaType).getDeclaredFields(); bExtender = true; while (bExtender) { int fieldWidth = (752 - 30) / fieldCount; for (FieldMetadata fieldMetadata : fields) { JavaType fieldType = fieldMetadata.getFieldType(); boolean bValidType = Arrays.asList(jasperFacetValidTypes) .contains(fieldType.getFullyQualifiedTypeName()); JavaSymbolName fieldName = fieldMetadata.getFieldName(); insertJasperooMessages("jasperoo." + getPlural(entityName) + "." + fieldName.getSymbolName(), fieldName.getReadableSymbolName()); Element pageHeaderNode = XmlUtils.findFirstElementByName("pageHeader", reportDoc.getDocumentElement()); Element fieldNode = new XmlElementBuilder("field", reportDoc) .addAttribute("name", fieldName.getSymbolName()) .addAttribute("class", fieldType.getFullyQualifiedTypeName()).build(); reportDoc.getDocumentElement().insertBefore(fieldNode, pageHeaderNode); if (!bValidType) { Element firstFieldNode = XmlUtils.findFirstElementByName("field", reportDoc.getDocumentElement()); Element importNode = new XmlElementBuilder("import", reportDoc) .addAttribute("value", fieldType.getFullyQualifiedTypeName()).build(); reportDoc.getDocumentElement().insertBefore(importNode, firstFieldNode); } Element headerTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc) .addAttribute("x", String.valueOf(offsetX)).addAttribute("y", "0") .addAttribute("width", String.valueOf(fieldWidth)).addAttribute("height", "20") .build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild( new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", "java.lang.String").setText("$R{jasperoo." + getPlural(entityName) + "." + fieldName.getSymbolName() + "}") .build()) .build(); columnHeaderBand.appendChild(headerTextfield); Element detailTextfield = null; if (bValidType) { detailTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc) .addAttribute("x", String.valueOf(offsetX)).addAttribute("y", "0") .addAttribute("width", String.valueOf(fieldWidth)).addAttribute("height", "20") .build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild(new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", fieldType.getFullyQualifiedTypeName()) .setText("$F{" + fieldName.getSymbolName() + "}").build()) .build(); } else { detailTextfield = new XmlElementBuilder("textField", reportDoc) .addChild(new XmlElementBuilder("reportElement", reportDoc) .addAttribute("x", String.valueOf(offsetX)).addAttribute("y", "0") .addAttribute("width", String.valueOf(fieldWidth)).addAttribute("height", "20") .build()) .addChild(new XmlElementBuilder("textElement", reportDoc).build()) .addChild(new XmlElementBuilder("textFieldExpression", reportDoc) .addAttribute("class", "java.lang.String") .setText("$F{" + fieldName.getSymbolName() + "}.toString()").build()) .build(); } detailBand.appendChild(detailTextfield); offsetX += fieldWidth; } // Do we keep going? extendsTypes = details.getExtendsTypes(); bExtender = extendsTypes != null && extendsTypes.size() > 0; if (bExtender) { JavaType tempType = details.getExtendsTypes().get(0); details = getJavaTypeDetails(tempType); fields = details.getDeclaredFields(); } } XmlUtils.writeXml(mutableReportXml.getOutputStream(), reportDoc); } /** * Inserts the required request handling method into the ReportController for a "List" report. * * @param entityName The Object upon which the report is based. * @param finalEntityPackage The properly formatted package of the entity in question. * @param finalControllerPackage The properly formatted package of the ReportController. */ private void modifyReportController(String entityName, String finder, String finalEntityPackage, String finalControllerPackage) { String controllerFile = pathResolver.getIdentifier(Path.SRC_MAIN_JAVA, finalControllerPackage.replace('.', separator) + separator + "ReportController.java"); MutableFile mutableControllerFile = null; try { if (fileManager.exists(controllerFile)) { mutableControllerFile = fileManager.updateFile(controllerFile); String originalData = convertStreamToString(mutableControllerFile.getInputStream()); originalData = originalData.substring(0, originalData.lastIndexOf("}")); String closingBrace = "}"; BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableControllerFile.getOutputStream())); if (originalData.contains("report" + entityName + "List") || originalData.contains("report" + entityName + "Detail")) { System.out.println("\nJASPEROO MANUAL INTERVENTION NEEDED!\n"); if (originalData.contains("report" + entityName + "List")) { System.out.println("-ReportController.java has more than one method named report" + entityName + "List()\n"); } if (originalData.contains("report" + entityName + "Detail")) { System.out.println("-ReportController.java has more than one method named report" + entityName + "Detail()\n"); } } out.write(originalData); out.write("\t@RequestMapping(value =\"/" + entityName.toLowerCase() + "List/{format}\", method = RequestMethod.GET)\n"); out.write("\tpublic String report" + entityName + "List(ModelMap modelMap, @PathVariable(\"format\") String format) {\n"); if (finder == null) { out.write("\t\tJRBeanCollectionDataSource jrDataSource = new JRBeanCollectionDataSource(" + finalEntityPackage + "." + entityName + ".findAll" + getPlural(entityName) + "(),false);\n"); } else { out.write("\t\tJRBeanCollectionDataSource jrDataSource = new JRBeanCollectionDataSource(" + finalEntityPackage + "." + entityName + "." + finder + "(),false);\n"); } out.write("\t\tmodelMap.put(\"reportData\", jrDataSource);\n"); out.write("\t\tmodelMap.put(\"format\", format);\n"); out.write("\t\treturn \"" + entityName.toLowerCase() + "ReportList\";\n"); out.write("\t}\n\n"); out.write("\t@RequestMapping(value =\"/" + entityName.toLowerCase() + "Detail/{id}/{format}\", method = RequestMethod.GET)\n"); out.write("\tpublic String report" + entityName + "Detail(ModelMap modelMap, @PathVariable(\"id\") Long id, @PathVariable(\"format\") String format) {\n"); out.write("\t\tJRBeanCollectionDataSource jrDataSource = new JRBeanCollectionDataSource(" + finalEntityPackage + "." + entityName + ".find" + getPlural(entityName) + "ById(id).getResultList(),false);\n"); out.write("\t\tmodelMap.put(\"reportData\", jrDataSource);\n"); out.write("\t\tmodelMap.put(\"format\", format);\n"); out.write("\t\treturn \"" + entityName.toLowerCase() + "ReportDetail\";\n"); out.write("\t}\n\n"); out.write(closingBrace); out.close(); } else { throw new IllegalStateException("Could not acquire " + controllerFile); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } } /** * Modifies the "List" report template to add all of the fields in the * entity being listed. * * @param javaType The JavaType of the entity being listed. * @param entityName The name of the entity being listed. */ private void modifyListTagx(String reportFormat) { String docPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/tags/form/list.tagx"); MutableFile mutableDocXml = null; Document targetDoc; try { if (fileManager.exists(docPath)) { mutableDocXml = fileManager.updateFile(docPath); targetDoc = XmlUtils.getDocumentBuilder().parse(mutableDocXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + docPath); } } catch (Exception e) { throw new IllegalStateException(e); } Node target = XmlUtils.findFirstElementByName("jsp:doBody", targetDoc.getDocumentElement()).getParentNode(); /* * <c:catch> * <c:if test="${not empty object.reportable}"> * <span> * <spring:url value="/reports/${fn:toLowerCase(typeName)}List/${itemId}/pdf" var="report_url" /> * <spring:url value="/resources/images/report.png" var="report_image_url" /> * <spring:message arguments="${typeName}" code="entity_list_report" var="report_label" htmlEscape="false" /> * <a href="${fn:escapeXml(report_url)}" alt="${fn:escapeXml(report_label)}" title="${fn:escapeXml(report_label)}"> * <img alt="${fn:escapeXml(report_label)}" class="image" src="${fn:escapeXml(report_image_url)}" title="${fn:escapeXml(report_label)}" /> * </a> * </span> * </c:if> * </c:catch> */ Element catchNode = new XmlElementBuilder("c:catch", targetDoc) .addChild( new XmlElementBuilder("c:if", targetDoc) .addAttribute("test", "${not empty items[0].reportable}") .addChild(new XmlElementBuilder("span", targetDoc) .addAttribute("style", "text-align:right;").build()) .addChild( new XmlElementBuilder("spring:url", targetDoc) .addAttribute("value", "/reports/${fn:toLowerCase(label)}List/" + reportFormat) .addAttribute("var", "report_url").build()) .addChild(new XmlElementBuilder("spring:url", targetDoc) .addAttribute("value", "/resources/images/report-" + reportFormat + ".png") .addAttribute("var", "report_image_url").build()) .addChild(new XmlElementBuilder("spring:message", targetDoc) .addAttribute("arguments", "${label}") .addAttribute("code", "entity_list_report") .addAttribute("var", "report_label").addAttribute("htmlEscape", "false") .build()) .addChild(new XmlElementBuilder("a", targetDoc) .addAttribute("href", "${fn:escapeXml(report_url)}") .addAttribute("alt", "${fn:escapeXml(report_label)}") .addAttribute("title", "${fn:escapeXml(report_label)}") .addChild(new XmlElementBuilder("img", targetDoc) .addAttribute("class", "image") .addAttribute("alt", "${fn:escapeXml(report_label)}") .addAttribute("title", "${fn:escapeXml(report_label)}") .addAttribute("src", "${fn:escapeXml(report_image_url)}").build()) .build()) .build()) .build(); target.appendChild(catchNode); XmlUtils.writeXml(mutableDocXml.getOutputStream(), targetDoc); } /** * Sets up the "List" tag. */ private void setupListTagx() { String docPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/tags/form/list.tagx"); MutableFile mutableDocXml = null; Document targetDoc; try { if (fileManager.exists(docPath)) { mutableDocXml = fileManager.updateFile(docPath); targetDoc = XmlUtils.getDocumentBuilder().parse(mutableDocXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + docPath); } } catch (Exception e) { throw new IllegalStateException(e); } Node target = XmlUtils.findFirstElementByName("jsp:doBody", targetDoc.getDocumentElement()).getParentNode(); /* * <c:catch> * <c:if test="${not empty object.reportable}"/> * <spring:message code="jasperoo_reports" htmlEscape="false" var="reports_label"/> * <b><c:out value="${reports_label} "/></b> * </c:if> * </c:catch> */ Element catchNode = new XmlElementBuilder("c:catch", targetDoc).addChild( new XmlElementBuilder("c:if", targetDoc).addAttribute("test", "${not empty items[0].reportable}") .addChild(new XmlElementBuilder("spring:message", targetDoc) .addAttribute("code", "jasperoo_reports").addAttribute("htmlEscape", "false") .addAttribute("var", "reports_label").build()) .addChild(new XmlElementBuilder("b", targetDoc) .addChild(new XmlElementBuilder("c:out", targetDoc) .addAttribute("value", "${reports_label} ").build()) .build()) .build()) .build(); target.appendChild(catchNode); XmlUtils.writeXml(mutableDocXml.getOutputStream(), targetDoc); } /** * Modifies the "List" report template to add all of the fields in the * entity being listed. * * @param javaType The JavaType of the entity being listed. * @param entityName The name of the entity being listed. */ private void modifyShowTagx(String reportFormat) { String docPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/tags/form/show.tagx"); MutableFile mutableDocXml = null; Document targetDoc; try { if (fileManager.exists(docPath)) { mutableDocXml = fileManager.updateFile(docPath); targetDoc = XmlUtils.getDocumentBuilder().parse(mutableDocXml.getInputStream()); } else { throw new IllegalStateException("Could not acquire " + docPath); } } catch (Exception e) { throw new IllegalStateException(e); } Element targetDiv = XmlUtils.findFirstElementByName("div", targetDoc.getDocumentElement()); /* * <c:catch> * <c:if test="${not empty object.reportable}"> * <span> * <spring:url value="/reports/${fn:toLowerCase(typeName)}Detail/${itemId}/pdf" var="report_url" /> * <spring:url value="/resources/images/report.png" var="report_image_url" /> * <spring:message arguments="${typeName}" code="entity_detail_report" var="report_label" htmlEscape="false" /> * <a href="${fn:escapeXml(report_url)}" alt="${fn:escapeXml(report_label)}" title="${fn:escapeXml(report_label)}"> * <img alt="${fn:escapeXml(report_label)}" class="image" src="${fn:escapeXml(report_image_url)}" title="${fn:escapeXml(report_label)}" /> * </a> * </span> * </c:if> * </c:catch> */ Element catchNode = new XmlElementBuilder("c:catch", targetDoc) .addChild( new XmlElementBuilder("c:if", targetDoc) .addAttribute("test", "${not empty object.reportable}") .addChild(new XmlElementBuilder("span", targetDoc).build()) .addChild(new XmlElementBuilder("spring:url", targetDoc) .addAttribute("value", "/reports/${fn:toLowerCase(typeName)}Detail/${itemId}/" + reportFormat) .addAttribute("var", "report_url").build()) .addChild(new XmlElementBuilder("spring:url", targetDoc) .addAttribute("value", "/resources/images/report-" + reportFormat + ".png") .addAttribute("var", "report_image_url").build()) .addChild(new XmlElementBuilder("spring:message", targetDoc) .addAttribute("arguments", "${typeName}") .addAttribute("code", "entity_detail_report") .addAttribute("var", "report_label") .addAttribute("htmlEscape", "false").build()) .addChild(new XmlElementBuilder("a", targetDoc) .addAttribute("href", "${fn:escapeXml(report_url)}") .addAttribute("alt", "${fn:escapeXml(report_label)}") .addAttribute("title", "${fn:escapeXml(report_label)}") .addChild(new XmlElementBuilder("img", targetDoc) .addAttribute("class", "image") .addAttribute("alt", "${fn:escapeXml(report_label)}") .addAttribute("title", "${fn:escapeXml(report_label)}") .addAttribute("src", "${fn:escapeXml(report_image_url)}") .build()) .build()) .build()) .build(); targetDiv.appendChild(catchNode); XmlUtils.writeXml(mutableDocXml.getOutputStream(), targetDoc); } /** * Manipulates the menu.jspx file to add the entries required for this report. * * @param lowerCaseEntityName The name of the entity in question, in lower case. */ private void addMenuEntry(String lowerCaseEntityName) { // add jasperReportsMultiFormatView to applicationContext String menuJSPX = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/views/menu.jspx"); MutableFile mutableMenuJSPX = null; Document menuDoc; try { if (fileManager.exists(menuJSPX)) { mutableMenuJSPX = fileManager.updateFile(menuJSPX); menuDoc = XmlUtils.getDocumentBuilder().parse(mutableMenuJSPX.getInputStream()); if (menuDoc == null) { throw new IllegalStateException("Could not acquire menuDoc"); } } else { throw new IllegalStateException("Could not acquire " + menuJSPX); } } catch (Exception e) { throw new IllegalStateException(e); } Element menuItemPDF = new XmlElementBuilder("menu:item", menuDoc) .addAttribute("id", "i_" + lowerCaseEntityName + "_list_pdf") .addAttribute("messageCode", "global_menu_list") .addAttribute("url", "/reports/" + lowerCaseEntityName + "List/pdf").build(); Element reportsNode = XmlUtils.findFirstElement("menu/category[@id = 'c_reports']", menuDoc.getDocumentElement()); if (reportsNode == null) { reportsNode = new XmlElementBuilder("menu:category", menuDoc).addAttribute("id", "c_reports") .addChild(menuItemPDF).build(); Element menu = XmlUtils.findFirstElementByName("menu:menu", menuDoc.getDocumentElement()); menu.appendChild(reportsNode); } else { reportsNode.appendChild(menuItemPDF); } Element menuItemXLS = new XmlElementBuilder("menu:item", menuDoc) .addAttribute("id", "i_" + lowerCaseEntityName + "_list_xls") .addAttribute("messageCode", "global_menu_list") .addAttribute("url", "/reports/" + lowerCaseEntityName + "List/xls").build(); reportsNode.appendChild(menuItemXLS); XmlUtils.writeXml(mutableMenuJSPX.getOutputStream(), menuDoc); } /** * Modify application.properties by adding the i18n messages that apply to all reports. */ private void insertI18nSetupMessages() { String applicationProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/i18n/application.properties"); MutableFile mutableApplicationProperties = null; try { if (fileManager.exists(applicationProperties)) { mutableApplicationProperties = fileManager.updateFile(applicationProperties); String originalData = convertStreamToString(mutableApplicationProperties.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableApplicationProperties.getOutputStream())); out.write(originalData); out.write("label_ca_digitalface_jasperoo_report=Report\n"); out.write("label_ca_digitalface_jasperoo_report_plural=Reports\n"); out.write("label_ca_digitalface_jasperoo_detail=Detail\n"); out.write("label_ca_digitalface_jasperoo_list=List\n"); out.write("menu_category_reports_label=Reports\n"); out.close(); } else { throw new IllegalStateException("Could not acquire " + applicationProperties); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } String messagesProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/i18n/messages.properties"); MutableFile mutableMessagesProperties = null; try { if (fileManager.exists(messagesProperties)) { mutableMessagesProperties = fileManager.updateFile(messagesProperties); String originalData = convertStreamToString(mutableMessagesProperties.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableMessagesProperties.getOutputStream())); out.write(originalData); out.write("\n\n"); out.write("#reports\n"); out.write("jasperoo_reports=Reports:\n"); out.write("entity_list_report={0} List Report\n"); out.write("entity_detail_report={0} Detail Report\n"); out.close(); } else { throw new IllegalStateException("Could not acquire " + messagesProperties); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } } /** * Modify application.properties by adding the i18n messages that apply to this report. * * @param entityName The name of the entity upon which the report is based. */ private void insertI18nAddMessages(String entityName) { String applicationProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/i18n/application.properties"); MutableFile mutableApplicationProperties = null; String entityNamePlural = getPlural(entityName); try { if (fileManager.exists(applicationProperties)) { mutableApplicationProperties = fileManager.updateFile(applicationProperties); String originalData = convertStreamToString(mutableApplicationProperties.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableApplicationProperties.getOutputStream())); out.write(originalData); out.write("menu_item_" + entityName.toLowerCase() + "_list_pdf_label=" + entityNamePlural + " (pdf)\n"); out.write("menu_item_" + entityName.toLowerCase() + "_list_xls_label=" + entityNamePlural + " (xls)\n"); out.close(); } else { throw new IllegalStateException("Could not acquire " + applicationProperties); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } } /** * The i18n messages that are displayed in reports are stored in a files * called "jasperoo.properties" in the "WEB-INF/classes" folder. This * method adds the requires messages for a given report. * * @param key The name of the key in question. * @param value The value of that message. */ private void insertJasperooMessages(String key, String value) { String applicationProperties = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF/classes/jasperoo.properties"); MutableFile mutableApplicationProperties = null; try { if (fileManager.exists(applicationProperties)) { mutableApplicationProperties = fileManager.updateFile(applicationProperties); String originalData = convertStreamToString(mutableApplicationProperties.getInputStream()); BufferedWriter out = new BufferedWriter( new OutputStreamWriter(mutableApplicationProperties.getOutputStream())); out.write(originalData); out.write(key + "=" + value + "\n"); out.close(); } else { throw new IllegalStateException("Could not acquire " + applicationProperties); } } catch (Exception e) { System.out.println("---> " + e.getMessage()); throw new IllegalStateException(e); } } /** * A utility method to convert an input stream to a String. * * @param source The source input stream. * @return The source as a String, or an empty String if the source is null * @throws IOException If unable to read stream. */ private String convertStreamToString(InputStream source) throws IOException { /* * To convert the InputStream to String we use the Reader.read(char[] * buffer) method. We iterate until the Reader return -1 which means * there's no more data to read. We use the StringWriter class to * produce the string. */ if (source != null) { Writer writer = new StringWriter(); char[] buffer = new char[1024]; try { Reader reader = new BufferedReader(new InputStreamReader(source, "UTF-8")); int n; while ((n = reader.read(buffer)) != -1) { writer.write(buffer, 0, n); } } finally { source.close(); } return writer.toString(); } else { return ""; } } /** * This method returns the plural of the term specified in English. * ATTENTION: this method does NOT take @RooPlural into account. * * @param term * The term to be pluralized * @return pluralized term */ private String getPlural(String term) { try { return Noun.pluralOf(term, Locale.ENGLISH); } catch (RuntimeException re) { // Inflector failed (see for example ROO-305), so don't pluralize it return term; } } /** * Gets the MutableClassOrInterfaceTypeDetails needed to query the fields * available for the JavaType specified. * * @param source The JavaType of the entity being queried. * @return MutableClassOrInterfaceTypeDetails of the JavaType specified. */ private MutableClassOrInterfaceTypeDetails getJavaTypeDetails(JavaType source) { MutableClassOrInterfaceTypeDetails result = null; // Retrieve metadata for the Java source type String fqEntityName = physicalTypeMetadataProvider.findIdentifier(source); if (fqEntityName == null) { throw new IllegalArgumentException( "Cannot locate source for '" + source.getFullyQualifiedTypeName() + "'"); } // Obtain the physical type and itd mutable details PhysicalTypeMetadata physicalTypeMetadata = (PhysicalTypeMetadata) metadataService.get(fqEntityName); Assert.notNull(physicalTypeMetadata, "Java source code unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(fqEntityName)); // Obtain physical type details for the target type PhysicalTypeDetails physicalTypeDetails = physicalTypeMetadata.getMemberHoldingTypeDetails(); Assert.notNull(physicalTypeDetails, "Java source code details unavailable for type " + PhysicalTypeIdentifier.getFriendlyName(fqEntityName)); // Test if the type is an MutableClassOrInterfaceTypeDetails Assert.isInstanceOf(MutableClassOrInterfaceTypeDetails.class, physicalTypeDetails, "Java source code is immutable for type " + PhysicalTypeIdentifier.getFriendlyName(fqEntityName)); result = (MutableClassOrInterfaceTypeDetails) physicalTypeDetails; return result; } }