/*
 *
 * JBoss, the OpenSource J2EE webOS
 *
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.ejb3.test.dd.unit;

import org.jboss.ejb3.dd.*;

import java.net.URL;
import java.util.List;

import org.jboss.logging.Logger;
import org.jboss.xb.binding.ObjectModelFactory;
import org.jboss.xb.binding.Unmarshaller;
import org.jboss.xb.binding.UnmarshallerFactory;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * JUnit TestCase for JbossXB usage for ejb-jar.xml deployment descriptor for
 * version 1.4 schema
 * 
 * @version <tt>$Revision: 1.8.2.4 $</tt>
 * @author <a href="mailto:bdecoste@jboss.com">William DeCoste</a>
 */

public class EjbJarXmlTestCase extends TestCase
{

   private static final Logger log = Logger.getLogger(EjbJarXmlTestCase.class);

   public EjbJarXmlTestCase(String name)
   {

      super(name);

   }

   // Tests
   public void testUnmarshalDDXsd() throws Exception
   {
      // create an object model factory
      ObjectModelFactory factory = new EjbJarDDObjectFactory();
      URL xmlUrl = getResourceUrl("dd/ejb-jar.xml");
      assertNotNull(xmlUrl);
      Unmarshaller unmarshaller = UnmarshallerFactory.newInstance()
            .newUnmarshaller();
      EjbJarDD dd = (EjbJarDD) unmarshaller.unmarshal(xmlUrl.openStream(),
            factory, null);
      assertNotNull(dd);

      factory = new JBossDDObjectFactory(dd);
      xmlUrl = getResourceUrl("dd/jboss.xml");
      assertNotNull(xmlUrl);
      unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
      dd = (EjbJarDD) unmarshaller
            .unmarshal(xmlUrl.openStream(), factory, null);

      checkUnmarshalledDD(dd);
   }
   
   public void testUnmarshalMdb() throws Exception
   {
      // create an object model factory
      ObjectModelFactory factory = new EjbJarDDObjectFactory();
      URL xmlUrl = getResourceUrl("dd/mdb/META-INF/ejb-jar.xml");
      assertNotNull(xmlUrl);
      Unmarshaller unmarshaller = UnmarshallerFactory.newInstance()
            .newUnmarshaller();
      EjbJarDD dd = (EjbJarDD) unmarshaller.unmarshal(xmlUrl.openStream(),
            factory, null);
      assertNotNull(dd);

      factory = new JBossDDObjectFactory(dd);
      xmlUrl = getResourceUrl("dd/mdb/META-INF/jboss.xml");
      assertNotNull(xmlUrl);
      unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
      dd = (EjbJarDD) unmarshaller
            .unmarshal(xmlUrl.openStream(), factory, null);

      checkUnmarshalledMdb(dd);
   }

   private void checkUnmarshalledDD(EjbJarDD dd)
   {
      log.debug("unmarshalled DD: " + dd);

      assertEquals("2.1", dd.getVersion());
      assertEquals("DukesBankEJBJAR", dd.getDisplayName());

      EnterpriseBeans ejbs = dd.getEnterpriseBeans();
      assertNotNull(ejbs);
      assertEquals(7, ejbs.getEnterpriseBeans().size());
      EnterpriseBean ejb = (EnterpriseBean) ejbs.getEnterpriseBeans().get(0);
      assertEquals("AccountControllerBean", ejb.getEjbName());
      assertEquals("com.sun.ebank.ejb.account.AccountControllerHome", ejb
            .getHome());
      assertEquals("com.sun.ebank.ejb.account.AccountController", ejb
            .getRemote());
      assertEquals("com.sun.ebank.ejb.account.AccountControllerBean", ejb
            .getEjbClass());
      log.info("ejb.getLocal() " + ejb.getLocal());
      assertNull(ejb.getLocal());
      assertNull(ejb.getLocalHome());
      List<Invoker> invokers = ejb.getInvokers();
      assertEquals(1, invokers.size());
      Invoker invoker = invokers.get(0);
      assertEquals("test-stateful-invoker", invoker.getInvokerProxyBindingName());
      assertTrue(ejb instanceof SessionEnterpriseBean);
      SessionEnterpriseBean session = (SessionEnterpriseBean) ejb;
      assertEquals("Stateful", session.getSessionType());
      assertEquals("Container", session.getTransactionType());
      assertEquals("ebankAccountController", session.getJndiName());
      SecurityIdentity si = session.getSecurityIdentity();
      assertNotNull(si);
      assertTrue(si.isUseCallerIdentity());
      List ejblocalRefs = session.getEjbLocalRefs();
      assertEquals(3, ejblocalRefs.size());
      EjbLocalRef ejbLocalRef = (EjbLocalRef) ejblocalRefs.get(0);
      assertEquals("ejb/customer", ejbLocalRef.getEjbRefName());
      assertEquals("Entity", ejbLocalRef.getEjbRefType());
      assertEquals("com.sun.ebank.ejb.customer.LocalCustomerHome", ejbLocalRef
            .getLocalHome());
      assertEquals("com.sun.ebank.ejb.customer.LocalCustomer", ejbLocalRef
            .getLocal());
      assertEquals("CustomerBean", ejbLocalRef.getEjbLink());
      List resourceRefs = session.getResourceRefs();
      assertEquals(1, resourceRefs.size());
      ResourceRef resourceRef = (ResourceRef) resourceRefs.get(0);
      assertEquals("jdbc/BankDB", resourceRef.getResRefName());
      assertEquals("javax.sql.DataSource", resourceRef.getResType());
      assertEquals("Container", resourceRef.getResAuth());
      assertEquals("Shareable", resourceRef.getResSharingScope());

      ejb = (EnterpriseBean) ejbs.getEnterpriseBeans().get(1);
      assertEquals("CustomerBean", ejb.getEjbName());
      assertTrue(ejb instanceof EntityEnterpriseBean);
      assertEquals("Container", ((EntityEnterpriseBean) ejb)
            .getPersistenceType());

      Relationships relationships = dd.getRelationships();
      assertNotNull(relationships);
      List relations = relationships.getEjbRelations();
      assertEquals(2, relations.size());
      EjbRelation relation = (EjbRelation) relations.get(0);
      assertEquals("account-customer", relation.getEjbRelationName());
      List roles = relation.getEjbRelationshipRoles();
      assertEquals(2, roles.size());
      EjbRelationshipRole role = (EjbRelationshipRole) roles.get(0);
      assertEquals("customer-belongs-to-account", role
            .getEjbRelationshipRoleName());
      assertEquals("Many", role.getMultiplicity());
      assertFalse(role.isCascadeDelete());
      RelationshipRoleSource source = role.getRelationshipRoleSource();
      assertNotNull(source);
      assertEquals("CustomerBean", source.getEjbName());
      CmrField field = role.getCmrField();
      assertNotNull(field);
      assertEquals("accounts", field.getCmrFieldName());
      assertEquals("java.util.Collection", field.getCmrFieldType());

      AssemblyDescriptor descriptor = dd.getAssemblyDescriptor();
      assertNotNull(descriptor);
      List securityRoles = descriptor.getSecurityRoles();
      assertEquals(2, securityRoles.size());
      SecurityRole securityRole = (SecurityRole) securityRoles.get(0);
      assertEquals("bankCustomer", securityRole.getRoleName());
      List methodPermissions = descriptor.getMethodPermissions();
      assertEquals(7, methodPermissions.size());
      MethodPermission methodPermission = (MethodPermission) methodPermissions
            .get(0);
      List roleNames = methodPermission.getRoleNames();
      assertNotNull(roleNames);
      assertEquals(1, roleNames.size());
      assertEquals("bankCustomer", roleNames.get(0));
      List<Method> methods = methodPermission.getMethods();
      assertNotNull(methods);
      assertEquals(methods.size(), 1);
      Method method = methods.get(0);
      assertEquals("CustomerBean", method.getEjbName());
      assertEquals("*", method.getMethodName());
      List containerTransactions = descriptor.getContainerTransactions();
      assertEquals(7, containerTransactions.size());
      ContainerTransaction containerTransaction = (ContainerTransaction) containerTransactions
            .get(0);
      assertEquals("Required", containerTransaction.getTransAttribute());
      method = containerTransaction.getMethod();
      assertNotNull(method);
      assertEquals("AccountControllerBean", method.getEjbName());
      assertEquals("*", method.getMethodName());
      
      LoaderRepository loaderRepository = dd.getLoaderRepository();
      assertNotNull(loaderRepository);
      LoaderRepositoryConfig loaderRepositoryConfig = loaderRepository.getLoaderRepositoryConfig();
      assertNotNull(loaderRepositoryConfig);
      assertEquals("dot.com.LoaderRepository", loaderRepository.getLoaderRepositoryClass());
      assertEquals("dot.com.LoaderParser", loaderRepositoryConfig.getConfigParserClass());
      assertEquals("dot.com:loader=unique-archive-name", loaderRepository.getValue());
      assertEquals("java2ParentDelegaton=true", loaderRepositoryConfig.getValue());
      
      List<InvokerProxyBinding> invokerProxyBindings = dd.getInvokerProxyBindings();
      assertEquals(1, invokerProxyBindings.size());
      InvokerProxyBinding binding = invokerProxyBindings.get(0);
      assertEquals("test-stateful-invoker", binding.getName());
      ClientBeanInterceptors clientBeanInterceptors = binding.getClientBeanInterceptors();
      assertNotNull(clientBeanInterceptors);
      
      List<String> interceptors = clientBeanInterceptors.getInterceptors();
      assertEquals(5, interceptors.size());
      assertEquals("org.jboss.ejb3.remoting.IsLocalInterceptor", interceptors.get(0));
   }
   
   private void checkUnmarshalledMdb(EjbJarDD dd)
   {
      log.debug("unmarshalled DD: " + dd);

      EnterpriseBeans ejbs = dd.getEnterpriseBeans();
      assertNotNull(ejbs);
      assertEquals(9, ejbs.getEnterpriseBeans().size());
      EnterpriseBean ejb = (EnterpriseBean) ejbs.getEnterpriseBeans().get(0);
      assertEquals("ObjectMessageBean", ejb.getEjbName());
      assertEquals("org.jboss.ejb3.test.dd.mdb.ObjectMessageBean",ejb.getEjbClass());
      assertTrue(ejb instanceof MessageDrivenBean);
      MessageDrivenBean mdb = (MessageDrivenBean) ejb;
      assertEquals("AUTO_ACKNOWLEDGE", mdb.getAcknowledgeMode());
      assertEquals("Bean", mdb.getTransactionType());
      MessageDrivenDestination destination = mdb.getMessageDrivenDestination();
      assertNotNull(destination);
      assertEquals("javax.jms.Queue",destination.getDestinationType());
      assertEquals("NonDurable",destination.getSubscriptionDurability());
   }

   private static URL getResourceUrl(String name)
   {
      URL url = Thread.currentThread().getContextClassLoader()
            .getResource(name);
      if (url == null)
      {
         throw new IllegalStateException("Resource not found: " + name);
      }
      return url;
   }

   public static Test suite() throws Exception
   {
      return new TestSuite(EjbJarXmlTestCase.class);
   }

}
