/* * Copyright 2012 PRODYNA AG * * Licensed under the Eclipse Public License (EPL), Version 1.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php or * http://www.nabucco.org/License.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.nabucco.framework.generator.compiler.transformation.xml.service; import java.io.File; import java.util.ArrayList; import java.util.List; import org.nabucco.framework.generator.compiler.constants.NabuccoXmlTemplateConstants; import org.nabucco.framework.generator.compiler.transformation.common.annotation.service.NabuccoServiceType; import org.nabucco.framework.generator.compiler.transformation.common.annotation.service.NabuccoTransactionType; import org.nabucco.framework.generator.compiler.transformation.util.NabuccoTransformationUtility; import org.nabucco.framework.generator.compiler.transformation.xml.constants.EjbJarConstants; import org.nabucco.framework.generator.compiler.transformation.xml.visitor.NabuccoToXmlVisitorContext; import org.nabucco.framework.generator.compiler.transformation.xml.visitor.NabuccoToXmlVisitorSupport; import org.nabucco.framework.generator.compiler.visitor.NabuccoVisitorException; import org.nabucco.framework.generator.parser.syntaxtree.ServiceStatement; import org.nabucco.framework.mda.logger.MdaLogger; import org.nabucco.framework.mda.logger.MdaLoggingFactory; import org.nabucco.framework.mda.model.MdaModel; import org.nabucco.framework.mda.model.xml.XmlDocument; import org.nabucco.framework.mda.model.xml.XmlModel; import org.nabucco.framework.mda.model.xml.XmlModelException; import org.nabucco.framework.mda.template.xml.XmlTemplate; import org.nabucco.framework.mda.template.xml.XmlTemplateException; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * NabuccoToXmlComponentRelationEjbJarVisitor * * @author Nicolas Moser, PRODYNA AG */ class NabuccoToXmlServiceEjbJarVisitor extends NabuccoToXmlVisitorSupport implements EjbJarConstants { private static MdaLogger logger = MdaLoggingFactory.getInstance().getLogger(NabuccoToXmlServiceEjbJarVisitor.class); private String interfaceName; private List<Element> persistenceList = new ArrayList<Element>(); /** * Creates a new {@link NabuccoToXmlAdapterEjbJarVisitor} instance. * * @param visitorContext * the visitor context */ public NabuccoToXmlServiceEjbJarVisitor(NabuccoToXmlVisitorContext visitorContext) { super(visitorContext); } @Override public void visit(ServiceStatement nabuccoService, MdaModel<XmlModel> target) { this.interfaceName = nabuccoService.nodeToken2.tokenImage; String componentName = super.getProjectName(null, null); try { // Final document XmlDocument document = super.extractDocument(NabuccoXmlTemplateConstants.EJB_JAR_FRAGMENT_TEMPLATE); this.createResourceReferences(nabuccoService); this.modifyFragment(document); this.createServiceTransactionAttribute(document, nabuccoService); this.createOperationTransactionAttributes(document, nabuccoService); // File creation document.setProjectName(componentName); document.setConfFolder(super.getConfFolder() + FRAGMENT + File.separator); target.getModel().getDocuments().add(document); } catch (XmlModelException me) { throw new NabuccoVisitorException("Error during XML DOM service modification.", me); } catch (XmlTemplateException te) { throw new NabuccoVisitorException("Error during XML template service processing.", te); } super.visit(nabuccoService, target); } /** * Create the transaction attribute of the service. * * @param document * the xml document * @param nabuccoService * the nbc service * * @throws XmlModelException * when the DOM cannot be modified */ private void createServiceTransactionAttribute(XmlDocument document, ServiceStatement nabuccoService) throws XmlModelException { NabuccoServiceType serviceType = NabuccoServiceType.valueOf(nabuccoService); switch (serviceType) { case RESOURCE: { Element element = (Element) document.getElementsByXPath(XPATH_FRAGMENT_TRANSACTION_ATTRIBUTE).get(0); element.setTextContent(NabuccoTransactionType.NOT_SUPPORTED.getValue()); break; } } } /** * Modyfies the EJB-JAR document's name and attributes. * * @param document * the EJB-JAR XML document * * @throws XmlModelException * @throws XmlTemplateException */ private void modifyFragment(XmlDocument document) throws XmlModelException, XmlTemplateException { document.getDocument().getDocumentElement().setAttribute(NAME, this.interfaceName); Element session = this.createSessionElement(document); // PostConstruct, PreDestroy this.addLifecycleMethods(document, session); } /** * Creates the session tag for this fragment * * @param document * the xml document to extract the session * * @return the session element * * @throws XmlModelException */ private Element createSessionElement(XmlDocument document) throws XmlModelException { String name = this.interfaceName + IMPLEMENTATION; String interfacePackage = this.getVisitorContext().getPackage(); String ejbName = interfacePackage + PKG_SEPARATOR + this.interfaceName; String implName = NabuccoTransformationUtility.toImpl(interfacePackage) + PKG_SEPARATOR + name; Element session = (Element) document.getElementsByXPath(XPATH_FRAGMENT_SESSION).get(0); session.getElementsByTagName(EJB_NAME).item(0).setTextContent(ejbName); session.getElementsByTagName(EJB_LOCAL).item(0).setTextContent(ejbName + LOCAL); session.getElementsByTagName(EJB_REMOTE).item(0).setTextContent(ejbName + REMOTE); session.getElementsByTagName(EJB_CLASS).item(0).setTextContent(implName); ((Element) document.getElementsByXPath(XPATH_FRAGMENT_EJB_NAME).get(0)).setTextContent(ejbName); for (Element ejbReference : this.persistenceList) { session.appendChild(document.getDocument().importNode(ejbReference, true)); } // Add session to the document document.getDocument().importNode(session, true); return session; } /** * Adds postConstruct and preDestroy deployment descriptor elements to the session. * * @param document * the xml document * @param sessionElement * the session element * * @throws XmlTemplateException */ private void addLifecycleMethods(XmlDocument document, Element sessionElement) throws XmlTemplateException { // Template XmlTemplate ejbTemplate = this.getVisitorContext().getTemplate(NabuccoXmlTemplateConstants.EJB_JAR_TEMPLATE); Element postConstruct = (Element) ejbTemplate.copyNodesByXPath(XPATH_POST_CONSTRUCT).get(0); Element preDestroy = (Element) ejbTemplate.copyNodesByXPath(XPATH_PRE_DESTROY).get(0); sessionElement.appendChild(document.getDocument().importNode(postConstruct, true)); sessionElement.appendChild(document.getDocument().importNode(preDestroy, true)); } /** * Creates the reference to the entity manager. * * @param nabuccoService * the nabucco service to evalue * * @throws XmlTemplateException * when the DOM cannot be manipulated */ private void createResourceReferences(ServiceStatement nabuccoService) throws XmlTemplateException { NabuccoServiceType serviceType = NabuccoServiceType.valueOf(nabuccoService); switch (serviceType) { case PERSISTENCE: { String name = NabuccoTransformationUtility.firstToLower(ENTITY_MANAGER); Element persistenceRef = this.createPersistenceRefElement(name); this.persistenceList.add(persistenceRef); break; } case RESOURCE: { Element resourceRef = this.createResourceRefElement(SESSION_CONTEXT, IMPORT_SESSION_CONTEXT, JNDI_SESSION_CONTEXT); this.persistenceList.add(resourceRef); break; } case BUSINESS: { // Nothing to inject. break; } default: logger.warning("Service Type " + serviceType + " is not supported."); } } /** * Creates a persistence-ref-element tag for the service. This represents the entity-manager * reference. * * @param name * name of the entity manager reference * * @return the persistence-ref XML element * * @throws XmlTemplateException */ private Element createPersistenceRefElement(String name) throws XmlTemplateException { // Template XmlTemplate ejbTemplate = this.getVisitorContext().getTemplate(NabuccoXmlTemplateConstants.EJB_JAR_TEMPLATE); Element persistenceRef = (Element) ejbTemplate.copyNodesByXPath(XPATH_PERSISTENCE_REF).get(0); // Persistence Context persistenceRef.getElementsByTagName(PERSISTENCE_REF_NAME).item(0) .setTextContent(PERSISTENCE + XPATH_SEPARATOR + super.getDatasourceName()); // Persistence Unit persistenceRef.getElementsByTagName(PERSISTENCE_UNIT_NAME).item(0).setTextContent(super.getDatasourceName()); Element injectionElement = (Element) persistenceRef.getElementsByTagName(INJECTION_TARGET).item(0); String pkg = NabuccoTransformationUtility.toImpl(this.getVisitorContext().getPackage()); injectionElement.getElementsByTagName(INJECTION_TARGET_CLASS).item(0) .setTextContent(pkg + PKG_SEPARATOR + this.interfaceName + IMPLEMENTATION); injectionElement.getElementsByTagName(INJECTION_TARGET_NAME).item(0).setTextContent(name); return persistenceRef; } /** * Creates a resource-ref-element tag for the service. * * @param name * name of the resource reference * * @return the resource-ref XML element * * @throws XmlTemplateException */ private Element createResourceRefElement(String name, String type, String jndi) throws XmlTemplateException { // Template XmlTemplate ejbTemplate = this.getVisitorContext().getTemplate(NabuccoXmlTemplateConstants.EJB_JAR_TEMPLATE); Element resourceRef = (Element) ejbTemplate.copyNodesByXPath(XPATH_RESOURCE_REF).get(0); // <res-ref-name> Element element = super.getElementByTagName(resourceRef, RESOURCE_REF_NAME); element.setTextContent(name); // <res-type> element = super.getElementByTagName(resourceRef, RESOURCE_TYPE); element.setTextContent(type); // <mapped-name> element = super.getElementByTagName(resourceRef, RESOURCE_MAPPED_NAME); element.setTextContent(jndi); Element injectionElement = super.getElementByTagName(resourceRef, INJECTION_TARGET); String pkg = NabuccoTransformationUtility.toImpl(this.getVisitorContext().getPackage()); // <injection-target-class> element = super.getElementByTagName(injectionElement, INJECTION_TARGET_CLASS); element.setTextContent(pkg + PKG_SEPARATOR + this.interfaceName + IMPLEMENTATION); // <injection-target-name> element = super.getElementByTagName(injectionElement, INJECTION_TARGET_NAME); element.setTextContent(NabuccoTransformationUtility.firstToLower(name)); return resourceRef; } /** * Create the transaction attribute of the service operation. * * @param document * the xml document * @param nabuccoService * the nbc service * * @throws XmlModelException * when the DOM cannot be modified * @throws XmlTemplateException * when the XML template is not correct */ private void createOperationTransactionAttributes(XmlDocument document, ServiceStatement nabuccoService) throws XmlModelException, XmlTemplateException { String interfacePackage = this.getVisitorContext().getPackage(); String ejbName = interfacePackage + PKG_SEPARATOR + this.interfaceName; // Template XmlTemplate ejbTemplate = this.getVisitorContext().getTemplate(NabuccoXmlTemplateConstants.EJB_JAR_TEMPLATE); NabuccoToXmlServiceOperationEjbJarVisitor operationVisitor = new NabuccoToXmlServiceOperationEjbJarVisitor( ejbName, ejbTemplate); List<Element> containerTransactions = new ArrayList<Element>(); nabuccoService.accept(operationVisitor, containerTransactions); Node fragment = document.getElementsByXPath(XPATH_FRAGMENT).get(0); for (Element containerTransaction : containerTransactions) { fragment.appendChild(document.getDocument().importNode(containerTransaction, true)); } } }