from org.codehaus.jettison.json import JSONObject, JSONArray
from utilities import Util
from Property import Property
from JAASConfigurationEntry import JAASConfigurationEntry
from J2CAdminObject import J2CAdminObject
from J2CActivationSpec import J2CActivationSpec
from Connector import Connector
from ConnectionDefTemplateProps import ConnectionDefTemplateProps
from AdminObjectTemplateProps import AdminObjectTemplateProps
from ActivationSpecTemplateProps import ActivationSpecTemplateProps
from J2CConnectionFactory import J2CConnectionFactory
from WASConfLog import Log

__name_att__ = "websphere.j2cresourceadapter.name";

def export(objid, parentcontainmentpath, parentrespath):

  name = Util.getRequiredAttribute(objid, "name", 'J2CResourceAdapter');

  containmentpath = "%(parentconpath)sJ2CResourceAdapter:%(name)s/" % {'parentconpath':parentcontainmentpath, 'name':name }
  if not containmentpath.startswith("/"):
    containmentpath = "/" + containmentpath;

  dict = _export(objid, parentrespath, name);
  dict['conpath'] = containmentpath;
  return dict

def _export(objid, parentrespath, name = ""):
  Util.pushPathElement('J2CResourceAdapter')


  if parentrespath == "/":
    parentrespath = "";
  respath = "%(parentrespath)s/%(name)s" % { 'parentrespath':parentrespath, 'name':name }
  if not respath.startswith("/"):
    respath = "/" + respath;

  exportedObject = JSONObject();
  exportedObject.put("name", name);
  exportedObject.put("path", respath);
  exportedObject.put("teamMappings", JSONArray());
  exportedObject.put("inheritTeam", "true");
  exportedObject.put("description", "Discovered WebSphereJ2CResourceAdapter");
  exportedObject.put("roleName", "WebSphereJ2CResourceAdapter");

  roleProperties = JSONObject();

  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.providertype", objid, "providerType","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.archivepath", objid, "archivePath","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.hacapability", objid, "hACapability","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.isolatedclassloader", objid, "isolatedClassLoader","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.isenablehasupport", objid, "isEnableHASupport","J2CResourceAdapter");
  Util.addAttributePathPropertyToJson(roleProperties, "websphere.j2cresourceadapter.classpath", objid, "classpath","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.threadpoolalias", objid, "threadPoolAlias","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.singleton", objid, "singleton","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.description", objid, "description","J2CResourceAdapter");
  Util.addAttributePathPropertyToJson(roleProperties, "websphere.j2cresourceadapter.nativepath", objid, "nativepath","J2CResourceAdapter");
  Util.addAttributeToJsonIfNotNone(roleProperties, "websphere.j2cresourceadapter.name", objid, "name","J2CResourceAdapter");
  exportedObject.put("roleProperties", roleProperties);
  result = { 'object': exportedObject, 'respath':respath }
  extraObjects = [];
  typeFolders = {};
  extraObjects = Property.exportProperties(objid, respath, extraObjects, typeFolders, 'properties',"J2CResourceAdapter");

  j2cConnectionFactories = Util.getAssociatedObjects(objid, 'J2CConnectionFactory');
  for j2cConnectionFactory in j2cConnectionFactories:
    if len(j2cConnectionFactory) > 0:
      returndict = Util.createTypeFolder(respath, "J2CConnectionFactory", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, J2CConnectionFactory._export(j2cConnectionFactory, currespath));

  jaasLoginConfigurations = Util.parseConfigIdListAttribute(objid, 'jaasLoginConfiguration',"J2CResourceAdapter");
  for jaasLoginConfiguration in jaasLoginConfigurations:
    if len(jaasLoginConfiguration) > 0:
      returndict = Util.createTypeFolder(respath, "JAASConfigurationEntry", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      jaasLoginConfigurationName = Util.getOptionalAttribute(jaasLoginConfiguration, "alias", "JAASConfigurationEntry");
      Util.addAllFromExport(extraObjects, JAASConfigurationEntry._export(jaasLoginConfiguration, currespath, jaasLoginConfigurationName));

  j2cAdminObjects = Util.parseConfigIdListAttribute(objid, 'j2cAdminObjects',"J2CResourceAdapter");
  for j2cAdminObject in j2cAdminObjects:
    if len(j2cAdminObject) > 0:
      returndict = Util.createTypeFolder(respath, "J2CAdminObject", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, J2CAdminObject._export(j2cAdminObject, currespath));

  j2cActivationSpecs = Util.parseConfigIdListAttribute(objid, 'j2cActivationSpec',"J2CResourceAdapter");
  for j2cActivationSpec in j2cActivationSpecs:
    if len(j2cActivationSpec) > 0:
      returndict = Util.createTypeFolder(respath, "J2CActivationSpec", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      j2cActivationSpecName = Util.getOptionalAttribute(j2cActivationSpec, "name", "J2CActivationSpec");
      Util.addAllFromExport(extraObjects, J2CActivationSpec._export(j2cActivationSpec, currespath, j2cActivationSpecName));

  deploymentDescriptor = Util.getOptionalAttribute(objid, 'deploymentDescriptor', "J2CResourceAdapter");
  if deploymentDescriptor is not None and len(deploymentDescriptor) > 0:
   returndict = Util.createTypeFolder(respath, "Connector", typeFolders);
   currespath = returndict['path'];
   if returndict.has_key('object'):
     Util.addFromExport(extraObjects, returndict['object']);
   Util.addAllFromExport(extraObjects, Connector._export(deploymentDescriptor, currespath, "Deployment Descriptor"));

  i = 0;
  connectionDefTemplateProps = Util.parseConfigIdListAttribute(objid, 'connectionDefTemplateProps',"J2CResourceAdapter");
  for connectionDefTemplateProp in connectionDefTemplateProps:
    if len(connectionDefTemplateProp) > 0:
      returndict = Util.createTypeFolder(respath, "ConnectionDefTemplateProps", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, ConnectionDefTemplateProps._export(connectionDefTemplateProp, currespath, "Connection Def Template Props%s" % i));
      i = i + 1;

  i = 0;
  adminObjectTemplateProps = Util.parseConfigIdListAttribute(objid, 'adminObjectTemplateProps',"J2CResourceAdapter");
  for adminObjectTemplateProp in adminObjectTemplateProps:
    if len(adminObjectTemplateProp) > 0:
      returndict = Util.createTypeFolder(respath, "AdminObjectTemplateProps", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, AdminObjectTemplateProps._export(adminObjectTemplateProp, currespath, "Admin Object Template Props%s" % i));
      i = i + 1;

  i = 0;
  activationSpecTemplateProps = Util.parseConfigIdListAttribute(objid, 'activationSpecTemplateProps',"J2CResourceAdapter");
  for activationSpecTemplateProp in activationSpecTemplateProps:
    if len(activationSpecTemplateProp) > 0:
      returndict = Util.createTypeFolder(respath, "ActivationSpecTemplateProps", typeFolders);
      currespath = returndict['path'];
      if returndict.has_key('object'):
        Util.addFromExport(extraObjects, returndict['object']);
      Util.addAllFromExport(extraObjects, ActivationSpecTemplateProps._export(activationSpecTemplateProp, currespath, "Activation Spec Template Props%s" % i));
      i = i + 1;

  if len(extraObjects) != 0:
    result['extraObjects'] = extraObjects;
  Util.popPathElement('J2CResourceAdapter');
  return result;

def doImport(containmentpath, roleName, jsonobject):
  if not jsonobject.has("roleProperties"):
    raise Exception("J2CResourceAdapter resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");
  if not roleProperties.has("websphere.j2cresourceadapter.name"):
    raise Exception("Resource role properties does not contain websphere.j2cresourceadapter.name!");

  objid = Util.getid(containmentpath);
  if objid == None or len(objid) == 0:
    index = containmentpath.rindex('/',0,len(containmentpath)-2)+1;
    parentconpath = containmentpath[0:index];
    parentid = Util.getid(parentconpath);
    if parentid == None or len(parentid) == 0:
      raise Exception("Parent does not exist to create Server on.");
    objid = create(parentid, jsonobject);
  else:
    update(objid,jsonobject);
  return objid;

def create(parentid, jsonobject):
  Util.pushPathElement('J2CResourceAdapter')
  if not jsonobject.has("roleProperties"):
    raise Exception("J2CResourceAdapter resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  properties = [];
  properties.append(["deploymentDescriptor",[["vendorName","temp"]]]) # force the creation of the deploymentDescriptor because its "readOnly"
  Util.addIfNotNone(properties, "providerType", roleProperties.optString("websphere.j2cresourceadapter.providertype", None));
  Util.addIfNotNone(properties, "archivePath", roleProperties.optString("websphere.j2cresourceadapter.archivepath", None));
  Util.addIfNotNone(properties, "hACapability", roleProperties.optString("websphere.j2cresourceadapter.hacapability", None));
  Util.addIfNotNone(properties, "isolatedClassLoader", roleProperties.optString("websphere.j2cresourceadapter.isolatedclassloader", None));
  Util.addIfNotNone(properties, "isEnableHASupport", roleProperties.optString("websphere.j2cresourceadapter.isenablehasupport", None));
  Util.addPathProperty(properties, "classpath", roleProperties.optString("websphere.j2cresourceadapter.classpath", None));
  Util.addIfNotNone(properties, "threadPoolAlias", roleProperties.optString("websphere.j2cresourceadapter.threadpoolalias", None));
  Util.addIfNotNone(properties, "singleton", roleProperties.optString("websphere.j2cresourceadapter.singleton", None));
  Util.addIfNotNone(properties, "description", roleProperties.optString("websphere.j2cresourceadapter.description", None));
  Util.addPathProperty(properties, "nativepath", roleProperties.optString("websphere.j2cresourceadapter.nativepath", None));
  Util.addIfNotNone(properties, "name", roleProperties.optString("websphere.j2cresourceadapter.name", None));
  print "Creating J2CResourceAdapter with attributes";
  for prop in properties:
    print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };
  objid = Util.create("J2CResourceAdapter", parentid, properties);

  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));
    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereJAASConfigurationEntry":
        JAASConfigurationEntry.create(objid, curjsonobject);
      elif currole == "WebSphereConnector":
        #current assumption is no more than one connector per j2cresadapter
        another = Util.getOptionalAttribute(objid, 'deploymentDescriptor', 'J2CResourceAdapter');
        Log.debug("deploymentDescriptor = %s" % another);
        connector = Util.getAssociatedObjects(objid, 'Connector');
        if connector is None or len(connector) < 1:
          Connector.create(objid, curjsonobject);
          pass;
        else:
          Connector.update(connector[0], curjsonobject);
      else:
        propertyObject = Property.createObjIfRole(objid, curjsonobject, currole);

    # ActivationSpecTemplateProps MUST be created after Connector because it may depend on it for references
    # Connector creates Resource Adapters creates InboundResourceAdapter creates MessageAdapter creates MessageListener creates ActivationSpec
    # ActivationSpecTemplateProps references ActivationSpec
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereActivationSpecTemplateProps":
        ActivationSpecTemplateProps.create(objid, curjsonobject);

    # J2CActivationSpec MUST be created after Connector because it may depend on it for references
    # Connector creates Resource Adapters creates InboundResourceAdapter creates MessageAdapter creates MessageListener creates ActivationSpec
    # J2CActivationSpec references ActivationSpec
    # J2CActivationSpec MUST also be created after ActivationSpecTemplateProps because J2CActivationSpec inherits properties from ActivationSpecTemplateProps
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CActivationSpec":
        J2CActivationSpec.create(objid, curjsonobject);

    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereConnectionDefTemplateProps":
        ConnectionDefTemplateProps.create(objid, curjsonobject);
      elif currole == "WebSphereAdminObjectTemplateProps":
        AdminObjectTemplateProps.create(objid, curjsonobject);

    # J2CAdminObject objects MUST be created after ConnectionDefTemplateProps & AdminObjectTemplateProps
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CAdminObject":
        J2CAdminObject.create(objid, curjsonobject);

    # J2CConnectionFactory objects should be created last due to references
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CConnectionFactory":
        J2CConnectionFactory.create(objid, curjsonobject);

  Util.popPathElement('J2CResourceAdapter');
  return objid;

def update(objid,jsonobject):
  Util.pushPathElement('J2CResourceAdapter')
  if not jsonobject.has("roleProperties"):
    raise Exception("J2CResourceAdapter resource has no role properties!");

  roleProperties = jsonobject.getJSONObject("roleProperties");

  atts = [];
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.providertype", None), "providerType","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.archivepath", None), "archivePath","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.hacapability", None), "hACapability","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.isolatedclassloader", None), "isolatedClassLoader","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.isenablehasupport", None), "isEnableHASupport","J2CResourceAdapter");
  Util.addPathAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.classpath", None), "classpath","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.threadpoolalias", None), "threadPoolAlias","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.singleton", None), "singleton","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.description", None), "description","J2CResourceAdapter");
  Util.addPathAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.nativepath", None), "nativepath","J2CResourceAdapter");
  Util.addAttIfChanged(objid, atts, roleProperties.optString("websphere.j2cresourceadapter.name", None), "name","J2CResourceAdapter");
  if len(atts) != 0:
    print "Modifying J2CResourceAdapter with attributes:"
    for prop in atts:
      print "%(name)s = %(value)s" % { 'name': prop[0], 'value': prop[1] };

    Util.modify(objid, atts);
  else:   
    print "J2CResourceAdapter configuration up to date.";

  Property.removeProperties(objid, 'properties',"J2CResourceAdapter");

  j2cConnectionFactories = Util.getAssociatedObjects(objid, 'J2CConnectionFactory');
  for j2cConnectionFactory in j2cConnectionFactories:
    if len(j2cConnectionFactory) > 0:
      Util.remove(j2cConnectionFactory);

  jaasLoginConfigurations = Util.parseConfigIdListAttribute(objid, 'jaasLoginConfiguration',"J2CResourceAdapter");
  for jaasLoginConfiguration in jaasLoginConfigurations:
    if len(jaasLoginConfiguration) > 0:
      Util.remove(jaasLoginConfiguration);

  j2cAdminObjects = Util.parseConfigIdListAttribute(objid, 'j2cAdminObjects',"J2CResourceAdapter");
  for j2cAdminObject in j2cAdminObjects:
    if len(j2cAdminObject) > 0:
      Util.remove(j2cAdminObject);

  j2cActivationSpecs = Util.parseConfigIdListAttribute(objid, 'j2cActivationSpec',"J2CResourceAdapter");
  for j2cActivationSpec in j2cActivationSpecs:
    if len(j2cActivationSpec) > 0:
      Util.remove(j2cActivationSpec);

  connectionDefTemplateProps = Util.parseConfigIdListAttribute(objid, 'connectionDefTemplateProps',"J2CResourceAdapter");
  for connectionDefTemplateProp in connectionDefTemplateProps:
    if len(connectionDefTemplateProp) > 0:
      Util.remove(connectionDefTemplateProp);

  adminObjectTemplateProps = Util.parseConfigIdListAttribute(objid, 'adminObjectTemplateProps',"J2CResourceAdapter");
  for adminObjectTemplateProp in adminObjectTemplateProps:
    if len(adminObjectTemplateProp) > 0:
      Util.remove(adminObjectTemplateProp);

  activationSpecTemplateProps = Util.parseConfigIdListAttribute(objid, 'activationSpecTemplateProps',"J2CResourceAdapter");
  for activationSpecTemplateProp in activationSpecTemplateProps:
    if len(activationSpecTemplateProp) > 0:
      Util.remove(activationSpecTemplateProp);

  if jsonobject.has('children'):
    children = Util.getHighestChildrenWithRole(jsonobject.getJSONArray('children'));
    for curjsonobject in children[:]:
      currole = curjsonobject.getString("roleName");
      if currole == "WebSphereJAASConfigurationEntry":
        JAASConfigurationEntry.create(objid, curjsonobject);
      elif currole == "WebSphereConnector":
        another = Util.getOptionalAttribute(objid, 'deploymentDescriptor', 'J2CResourceAdapter');
        Log.debug("deploymentDescriptor = %s" % another);
        connector = Util.getAssociatedObjects(objid, 'Connector');
        if connector is None or len(connector) < 1:
          Connector.create(objid, curjsonobject);
          pass;
        else:
          Connector.update(connector[0], curjsonobject);
      else:
        propertyObject = Property.createObjIfRole(objid, curjsonobject, currole);

    # ActivationSpecTemplateProps MUST be created after Connector because it may depend on it for references
    # Connector creates Resource Adapters creates InboundResourceAdapter creates MessageAdapter creates MessageListener creates ActivationSpec
    # ActivationSpecTemplateProps references ActivationSpec
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereActivationSpecTemplateProps":
        ActivationSpecTemplateProps.create(objid, curjsonobject);

    # J2CActivationSpec MUST be created after Connector because it may depend on it for references
    # Connector creates Resource Adapters creates InboundResourceAdapter creates MessageAdapter creates MessageListener creates ActivationSpec
    # J2CActivationSpec references ActivationSpec
    # J2CActivationSpec MUST also be created after ActivationSpecTemplateProps because J2CActivationSpec inherits properties from ActivationSpecTemplateProps
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CActivationSpec":
        J2CActivationSpec.create(objid, curjsonobject);

    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereConnectionDefTemplateProps":
        ConnectionDefTemplateProps.create(objid, curjsonobject);
      elif currole == "WebSphereAdminObjectTemplateProps":
        AdminObjectTemplateProps.create(objid, curjsonobject);

    # J2CAdminObject objects MUST be created after ConnectionDefTemplateProps & AdminObjectTemplateProps
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CAdminObject":
        J2CAdminObject.create(objid, curjsonobject);

    # J2CConnectionFactory objects should be created last due to references
    for curjsonobject in children[:]:
      currole = curjsonobject.getString('roleName');
      if currole == "WebSphereJ2CConnectionFactory":
        J2CConnectionFactory.create(objid, curjsonobject);
  Util.popPathElement('J2CResourceAdapter');
