/**
 *
 * Copyright 2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 *  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.apache.ws.scout.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import javax.xml.registry.JAXRException;
import javax.xml.registry.LifeCycleManager;
import javax.xml.registry.infomodel.Association;
import javax.xml.registry.infomodel.Classification;
import javax.xml.registry.infomodel.ClassificationScheme;
import javax.xml.registry.infomodel.Concept;
import javax.xml.registry.infomodel.EmailAddress;
import javax.xml.registry.infomodel.ExternalIdentifier;
import javax.xml.registry.infomodel.ExternalLink;
import javax.xml.registry.infomodel.InternationalString;
import javax.xml.registry.infomodel.Organization;
import javax.xml.registry.infomodel.PostalAddress;
import javax.xml.registry.infomodel.RegistryObject;
import javax.xml.registry.infomodel.Service;
import javax.xml.registry.infomodel.ServiceBinding;
import javax.xml.registry.infomodel.SpecificationLink;
import javax.xml.registry.infomodel.TelephoneNumber;
import javax.xml.registry.infomodel.User;

import org.apache.ws.scout.model.uddi.v2.AccessPoint;
import org.apache.ws.scout.model.uddi.v2.Address;
import org.apache.ws.scout.model.uddi.v2.AddressLine;
import org.apache.ws.scout.model.uddi.v2.BindingTemplate;
import org.apache.ws.scout.model.uddi.v2.BindingTemplates;
import org.apache.ws.scout.model.uddi.v2.BusinessDetail;
import org.apache.ws.scout.model.uddi.v2.BusinessEntity;
import org.apache.ws.scout.model.uddi.v2.BusinessService;
import org.apache.ws.scout.model.uddi.v2.BusinessServices;
import org.apache.ws.scout.model.uddi.v2.CategoryBag;
import org.apache.ws.scout.model.uddi.v2.Contact;
import org.apache.ws.scout.model.uddi.v2.Contacts;
import org.apache.ws.scout.model.uddi.v2.Description;
import org.apache.ws.scout.model.uddi.v2.DiscoveryURL;
import org.apache.ws.scout.model.uddi.v2.DiscoveryURLs;
import org.apache.ws.scout.model.uddi.v2.Email;
import org.apache.ws.scout.model.uddi.v2.HostingRedirector;
import org.apache.ws.scout.model.uddi.v2.IdentifierBag;
import org.apache.ws.scout.model.uddi.v2.InstanceDetails;
import org.apache.ws.scout.model.uddi.v2.KeyedReference;
import org.apache.ws.scout.model.uddi.v2.Name;
import org.apache.ws.scout.model.uddi.v2.OverviewDoc;
import org.apache.ws.scout.model.uddi.v2.Phone;
import org.apache.ws.scout.model.uddi.v2.ServiceInfo;
import org.apache.ws.scout.model.uddi.v2.TModel;
import org.apache.ws.scout.model.uddi.v2.TModelDetail;
import org.apache.ws.scout.model.uddi.v2.TModelInfo;
import org.apache.ws.scout.model.uddi.v2.TModelInstanceDetails;
import org.apache.ws.scout.model.uddi.v2.TModelInstanceInfo;
import org.apache.ws.scout.registry.infomodel.AssociationImpl;
import org.apache.ws.scout.registry.infomodel.ClassificationImpl;
import org.apache.ws.scout.registry.infomodel.ClassificationSchemeImpl;
import org.apache.ws.scout.registry.infomodel.ConceptImpl;
import org.apache.ws.scout.registry.infomodel.EmailAddressImpl;
import org.apache.ws.scout.registry.infomodel.ExternalIdentifierImpl;
import org.apache.ws.scout.registry.infomodel.ExternalLinkImpl;
import org.apache.ws.scout.registry.infomodel.InternationalStringImpl;
import org.apache.ws.scout.registry.infomodel.KeyImpl;
import org.apache.ws.scout.registry.infomodel.OrganizationImpl;
import org.apache.ws.scout.registry.infomodel.PersonNameImpl;
import org.apache.ws.scout.registry.infomodel.PostalAddressImpl;
import org.apache.ws.scout.registry.infomodel.ServiceBindingImpl;
import org.apache.ws.scout.registry.infomodel.ServiceImpl;
import org.apache.ws.scout.registry.infomodel.SpecificationLinkImpl;
import org.apache.ws.scout.registry.infomodel.TelephoneNumberImpl;
import org.apache.ws.scout.registry.infomodel.UserImpl;

/**
 * Helper class that does UDDI->Jaxr Mapping
 *
 * @author <a href="mailto:anil@apache.org">Anil Saldhana</a>
 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
 */
public class ScoutUddiJaxrHelper
{
	public static Association getAssociation(Collection orgs,
			LifeCycleManager lcm)
	throws JAXRException
	{
		Association asso = new AssociationImpl(lcm);
		Object[] arr = orgs.toArray();
		asso.setSourceObject((RegistryObject)arr[0]);
		asso.setTargetObject((RegistryObject)arr[1]);
		return asso;
	}

	public static Organization getOrganization(BusinessEntity businessEntity,
			LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		List<Name> namesList = businessEntity.getName();
		List<Description> descriptionList = businessEntity.getDescription();

		Organization org = new OrganizationImpl(lifeCycleManager);
		if ((namesList != null) && (namesList.size() > 0)) {
			InternationalString is = null;
			for (int i = 0; i < namesList.size(); i++)  {
				Name n = namesList.get(i);
				if (is == null) {
					is = getIString(n.getLang(), n.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(n.getLang()), n.getValue());
				}
			}
			org.setName(is);
		}
		if ((descriptionList != null) && (descriptionList.size() > 0)) {
			InternationalString is = null;
			for (int i = 0; i < descriptionList.size(); i++)  {
				Description desc = descriptionList.get(i);
				if (is == null) {
					is = getIString(desc.getLang(), desc.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(desc.getLang()), desc.getValue());
				}
			}
			org.setDescription(is);
		}
		org.setKey(lifeCycleManager.createKey(businessEntity.getBusinessKey()));

		//Set Services also
		BusinessServices services = businessEntity.getBusinessServices();
		if(services != null)
		{
			List<BusinessService> bizServiceList = services.getBusinessService();
			for (BusinessService businessService : bizServiceList) {
				org.addService(getService(businessService, lifeCycleManager));
			}
		}

		/*
		 *  Users
		 *
		 *  we need to take the first contact and designate as the
		 *  'primary contact'.  Currently, the OrganizationImpl
		 *  class does that automatically as a safety in case
		 *  user forgets to set - lets be explicit here as to not
		 *  depend on that behavior
		 */

		Contacts contacts = businessEntity.getContacts();
		if(contacts != null)
		{
			List<Contact> contactList = contacts.getContact();
			if (contactList!=null) {
				boolean isFirst=true;
				for (Contact contact : contactList) {
					User user = new UserImpl(null);
					String pname = contact.getPersonName();
					user.setPersonName(new PersonNameImpl(pname));
					if (isFirst) {
						isFirst=false;
						org.setPrimaryContact(user);
					} else {
						org.addUser(user);
					}
				}
			}
		}

		//External Links
		DiscoveryURLs durls = businessEntity.getDiscoveryURLs();
		if (durls != null)
		{
			List<DiscoveryURL> discoveryURL_List = durls.getDiscoveryURL();
			for (DiscoveryURL discoveryURL : discoveryURL_List) {
				ExternalLink link = new ExternalLinkImpl(lifeCycleManager);
				link.setExternalURI(discoveryURL.getValue());
				org.addExternalLink(link);
			}
		}

		org.addExternalIdentifiers(getExternalIdentifiers(businessEntity.getIdentifierBag(), lifeCycleManager));
		org.addClassifications(getClassifications(businessEntity.getCategoryBag(), lifeCycleManager));

		return org;
	}


	public static Organization getOrganization(BusinessDetail bizdetail,
			LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		List<BusinessEntity> bizEntityList = bizdetail.getBusinessEntity();
		if (bizEntityList.size() != 1) {
			throw new JAXRException("Unexpected count of organizations in BusinessDetail: " + bizEntityList.size());
		}
		BusinessEntity entity = bizEntityList.get(0);
		List<Name> namesList = entity.getName();
		List<Description> descriptionList = entity.getDescription();

		Organization org = new OrganizationImpl(lifeCycleManager);
		if ((namesList != null) && (namesList.size() > 0)) {
			InternationalString is = null;
			for (int i = 0; i < namesList.size(); i++)  {
				Name n = namesList.get(i);
				if (is == null) {
					is = getIString(n.getLang(), n.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(n.getLang()), n.getValue());
				}
			}
			org.setName(is);
		}
		if ((descriptionList != null) && (descriptionList.size() > 0)) {
			InternationalString is = null;
			for (int i = 0; i < descriptionList.size(); i++)  {
				Description desc = descriptionList.get(i);
				if (is == null) {
					is = getIString(desc.getLang(), desc.getValue(), lifeCycleManager);
				} else {
					is.setValue(getLocale(desc.getLang()), desc.getValue());
				}
			}
			org.setDescription(is);
		}

		org.setKey(lifeCycleManager.createKey(entity.getBusinessKey()));

		//Set Services also
		BusinessServices services = entity.getBusinessServices();
		List<BusinessService> bizServiceList = services.getBusinessService();
		for (BusinessService businessService : bizServiceList) {
			org.addService(getService(businessService, lifeCycleManager));
		}

		/*
		 *  Users
		 *
		 *  we need to take the first contact and designate as the
		 *  'primary contact'.  Currently, the OrganizationImpl
		 *  class does that automatically as a safety in case
		 *  user forgets to set - lets be explicit here as to not
		 *  depend on that behavior
		 */
		Contacts contacts = entity.getContacts();
		List<Contact> contactList = contacts.getContact();
		boolean isFirst=true;
		for (Contact contact : contactList) {
			User user = new UserImpl(null);
			String pname = contact.getPersonName();
			user.setType(contact.getUseType());
			user.setPersonName(new PersonNameImpl(pname));

			List<Email> emailList = contact.getEmail();
			ArrayList<EmailAddress> tempEmails = new ArrayList<EmailAddress>();
			for (Email email : emailList) {
				tempEmails.add(new EmailAddressImpl(email.getValue(), null));
			}
			user.setEmailAddresses(tempEmails);

			List<Address> addressList = contact.getAddress();
			ArrayList<PostalAddress> tempAddresses = new ArrayList<PostalAddress>();
			for (Address address : addressList) {
				ArrayList<AddressLine> addressLineList = new ArrayList<AddressLine>(address.getAddressLine());
				AddressLine[] alines = new AddressLine[addressLineList.size()];
				addressLineList.toArray(alines);

				PostalAddress pa = getPostalAddress(alines);
				tempAddresses.add(pa);
			}
			user.setPostalAddresses(tempAddresses);

			List<Phone> phoneList = contact.getPhone();
			ArrayList<TelephoneNumber> tempPhones = new ArrayList<TelephoneNumber>();
			for (Phone phone : phoneList) {
				TelephoneNumberImpl tni = new TelephoneNumberImpl();
				tni.setType(phone.getUseType());
				tni.setNumber(phone.getValue());
				tempPhones.add(tni);
			}
			user.setTelephoneNumbers(tempPhones);
			if (isFirst) {
				isFirst=false;
				org.setPrimaryContact(user);
			} else {
				org.addUser(user);
			}
		}

		//External Links
		DiscoveryURLs durls = entity.getDiscoveryURLs();
		if (durls != null)
		{
			List<DiscoveryURL> discoveryURL_List = durls.getDiscoveryURL();
			for (DiscoveryURL discoveryURL : discoveryURL_List) {
				ExternalLink link = new ExternalLinkImpl(lifeCycleManager);
				link.setExternalURI(discoveryURL.getValue());
				org.addExternalLink(link);
			}
		}

		org.addExternalIdentifiers(getExternalIdentifiers(entity.getIdentifierBag(), lifeCycleManager));
		org.addClassifications(getClassifications(entity.getCategoryBag(), lifeCycleManager));

		return org;
	}

	private static PostalAddress getPostalAddress(AddressLine[] addressLineArr) throws JAXRException {
		PostalAddress pa = new PostalAddressImpl();
		HashMap<String, String> hm = new HashMap<String, String>();
		for (AddressLine anAddressLineArr : addressLineArr) {
			hm.put(anAddressLineArr.getKeyName(), anAddressLineArr.getKeyValue());
		}

		if (hm.containsKey("STREET_NUMBER")) {
			pa.setStreetNumber(hm.get("STREET_NUMBER"));
		}

		if (hm.containsKey("STREET")) {
			pa.setStreet(hm.get("STREET"));
		}

		if (hm.containsKey("CITY")) {
			pa.setCity(hm.get("CITY"));
		}

		if (hm.containsKey("COUNTRY")) {
			pa.setCountry(hm.get("COUNTRY"));
		}

		if (hm.containsKey("POSTALCODE")) {
			pa.setPostalCode(hm.get("POSTALCODE"));
		}

		if (hm.containsKey("STATE")) {
			pa.setStateOrProvince(hm.get("STATE"));
		}

		return pa;
	}

	private static InternationalString getIString(String lang, String str, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		if (str!=null) {
			return lifeCycleManager.createInternationalString(getLocale(lang), str);
		} else {
			return null;
		}
	}

	public static InternationalString getIString(String str, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		return lifeCycleManager.createInternationalString(str);
	}

	public static Service getService(BusinessService businessService, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Service serve = new ServiceImpl(lifeCycleManager);

		String keystr = businessService.getServiceKey();

		if (keystr != null)
		{
			serve.setKey(lifeCycleManager.createKey(keystr));
		}

		List<Name> namesList = businessService.getName();
		List<Description> descriptionList = businessService.getDescription();

		InternationalString is = null;
		for (int i = 0; i < namesList.size(); i++) {
			Name n = namesList.get(i);
			if (is == null) {
				is = lifeCycleManager.createInternationalString(getLocale(n.getLang()), n.getValue());
			} else {
				is.setValue(getLocale(n.getLang()), n.getValue());
			}
		}
		serve.setName(is);
		
		InternationalString dis = null;
		for (int i = 0; i < namesList.size(); i++) {
			Description desc = descriptionList.get(i);
			if (dis == null) {
				dis = lifeCycleManager.createInternationalString(getLocale(desc.getLang()), desc.getValue());
			} else {
				dis.setValue(getLocale(desc.getLang()), desc.getValue());
			}
		}
		serve.setDescription(dis);
		
		//Populate the ServiceBindings for this Service
		BindingTemplates bts = businessService.getBindingTemplates();
		List<BindingTemplate> bindingTemplateList = bts.getBindingTemplate();
		for (BindingTemplate bindingTemplate : bindingTemplateList) {
			serve.addServiceBinding(getServiceBinding(bindingTemplate, lifeCycleManager));
		}
		serve.addClassifications(getClassifications(businessService.getCategoryBag(), lifeCycleManager));

		return serve;
	}

	public static Service getService(ServiceInfo serviceInfo, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Service service = new ServiceImpl(lifeCycleManager);

		String keystr = serviceInfo.getServiceKey();

		if (keystr != null)
		{
			service.setKey(lifeCycleManager.createKey(keystr));
		}

		List<Name> namesList = serviceInfo.getName();
		InternationalString is = null;
		for (int i = 0; i < namesList.size(); i++) {
			Name n = namesList.get(i);
			if (is == null) {
				is = lifeCycleManager.createInternationalString(getLocale(n.getLang()), n.getValue());
			} else {
				is.setValue(getLocale(n.getLang()), n.getValue());
			}
		}
		service.setName(is);

		return service;
	}

	public static ServiceBinding getServiceBinding(BindingTemplate businessTemplate, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		ServiceBinding serviceBinding = new ServiceBindingImpl(lifeCycleManager);

		String keystr = businessTemplate.getServiceKey();
		if (keystr != null)
		{
			Service svc = new ServiceImpl(lifeCycleManager);
			svc.setKey(lifeCycleManager.createKey(keystr));
			((ServiceBindingImpl)serviceBinding).setService(svc);
		}
		String bindingKey = businessTemplate.getBindingKey();
		if(bindingKey != null) serviceBinding.setKey(new KeyImpl(bindingKey));

		//Access URI
		AccessPoint access = businessTemplate.getAccessPoint();
		if (access != null) serviceBinding.setAccessURI(access.getValue());

		//Description
		Description desc = null;
		if (businessTemplate.getDescription().size()>0) desc = businessTemplate.getDescription().get(0);
		if (desc!=null) {
			serviceBinding.setDescription(new InternationalStringImpl(desc.getValue()));
		}
		/**Section D.10 of JAXR 1.0 Specification */

		TModelInstanceDetails details = businessTemplate.getTModelInstanceDetails();
		List<TModelInstanceInfo> tmodelInstanceInfoList = details.getTModelInstanceInfo();

		for (TModelInstanceInfo info: tmodelInstanceInfoList)
		{
			if (info!=null && info.getInstanceDetails()!=null) {
				InstanceDetails idetails = info.getInstanceDetails();
				Collection<ExternalLink> elinks = getExternalLinks(idetails.getOverviewDoc(),lifeCycleManager);
				SpecificationLink slink = new SpecificationLinkImpl(lifeCycleManager);
				slink.addExternalLinks(elinks);
				serviceBinding.addSpecificationLink(slink); 

				ConceptImpl c = new ConceptImpl(lifeCycleManager);
				c.setExternalLinks(elinks);
				c.setKey(lifeCycleManager.createKey(info.getTModelKey())); 
				c.setName(lifeCycleManager.createInternationalString(idetails.getInstanceParms()));
				c.setValue(idetails.getInstanceParms());

				slink.setSpecificationObject(c);
			}
		}

		HostingRedirector hr = businessTemplate.getHostingRedirector();
		if(hr != null)
		{
			ServiceBinding sb = lifeCycleManager.createServiceBinding();
			sb.setKey(new KeyImpl(hr.getBindingKey()));
			serviceBinding.setTargetBinding(sb);
		}

		return serviceBinding;
	}

	public static Concept getConcept(TModelDetail tModelDetail, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		List<TModel> tmodelList = tModelDetail.getTModel();
		for (TModel tmodel : tmodelList) {
			concept.setKey(lifeCycleManager.createKey(tmodel.getTModelKey()));
			concept.setName(lifeCycleManager.createInternationalString(getLocale(tmodel.getName().getLang()),
					tmodel.getName().getValue()));

			Description desc = getDescription(tmodel);
			if( desc != null ) {
				concept.setDescription(lifeCycleManager.createInternationalString(getLocale(desc.getLang()), 
						desc.getValue()));
			}

			concept.addExternalIdentifiers(getExternalIdentifiers(tmodel.getIdentifierBag(), lifeCycleManager));
			concept.addClassifications(getClassifications(tmodel.getCategoryBag(), lifeCycleManager));
		}
		return concept;
	}

	public static Concept getConcept(TModel tmodel, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		concept.setKey(lifeCycleManager.createKey(tmodel.getTModelKey()));
		concept.setName(lifeCycleManager.createInternationalString(getLocale(tmodel.getName().getLang()),
				tmodel.getName().getValue()));

		Description desc = getDescription(tmodel);
		if (desc != null) {
			concept.setDescription(lifeCycleManager.createInternationalString(getLocale(desc.getLang()), 
					desc.getValue()));
		}

		concept.addExternalIdentifiers(getExternalIdentifiers(tmodel.getIdentifierBag(), lifeCycleManager));
		concept.addClassifications(getClassifications(tmodel.getCategoryBag(), lifeCycleManager));

		return concept;
	}

	public static Concept getConcept(TModelInfo tModelInfo, LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		Concept concept = new ConceptImpl(lifeCycleManager);
		concept.setKey(lifeCycleManager.createKey(tModelInfo.getTModelKey()));
		concept.setName(lifeCycleManager.createInternationalString(getLocale(tModelInfo.getName().getLang()), 
				tModelInfo.getName().getValue()));

		return concept;
	}

	private static Description getDescription( TModel tmodel )
	{
		Description desc = null;
		if (tmodel.getDescription().size()>0) desc=tmodel.getDescription().get(0);
		return desc;
	}

	/**
	 * Classifications - going to assume all are external since UDDI does not use "Concepts".
	 * @param categoryBag categories
	 * @param lifeCycleManager lifecycleManager
	 * @return Collection Classifications
	 * @throws JAXRException on error
	 */
	public static Collection getClassifications(CategoryBag categoryBag, LifeCycleManager lifeCycleManager) 
	throws JAXRException {
		Collection<Classification> classifications = null;
		if (categoryBag != null) {
			classifications = new ArrayList<Classification>();
			List<KeyedReference> keyedReferenceList = categoryBag.getKeyedReference();
			for (KeyedReference keyedReference : keyedReferenceList) {
				Classification classification = new ClassificationImpl(lifeCycleManager);
				classification.setValue(keyedReference.getKeyValue());
				classification.setName(new InternationalStringImpl(keyedReference.getKeyName()));
				String tmodelKey = keyedReference.getTModelKey();
				if (tmodelKey != null) {
					ClassificationScheme scheme = new ClassificationSchemeImpl(lifeCycleManager);
					scheme.setKey(new KeyImpl(tmodelKey));
					classification.setClassificationScheme(scheme);
				}
				classifications.add(classification);
			}
		}
		return classifications;
	}

	public static Collection<ExternalLink> getExternalLinks(OverviewDoc overviewDoc , LifeCycleManager lifeCycleManager)
	throws JAXRException
	{
		ArrayList<ExternalLink> alist = new ArrayList<ExternalLink>(1);
		if(overviewDoc != null)
		{
			String descStr = "";
			Description desc = null;
			if (overviewDoc.getDescription().size()>0) desc = overviewDoc.getDescription().get(0);
			if (desc !=null) descStr = desc.getValue();
			alist.add(lifeCycleManager.createExternalLink(overviewDoc.getOverviewURL(),descStr));
		}

		return alist;
	}

	/**
	 * External Identifiers
	 * @param identifierBag identifiers
	 * @param lifeCycleManager lifecycleManager
	 * @return Collection ExternalIdentifier
	 * @throws JAXRException on error
	 */

	public static Collection getExternalIdentifiers(IdentifierBag identifierBag, LifeCycleManager lifeCycleManager) 
	throws JAXRException {
		Collection<ExternalIdentifier> extidentifiers = null;
		if (identifierBag != null) {
			extidentifiers = new ArrayList<ExternalIdentifier>();

			List<KeyedReference> keyedReferenceList = identifierBag.getKeyedReference();
			for (KeyedReference keyedReference : keyedReferenceList) {
				ExternalIdentifier extId = new ExternalIdentifierImpl(lifeCycleManager);
				extId.setValue(keyedReference.getKeyValue());
				extId.setName(new InternationalStringImpl(keyedReference.getKeyName()));

				String tmodelKey = keyedReference.getTModelKey();
				if (tmodelKey != null) {
					ClassificationScheme scheme = new ClassificationSchemeImpl(lifeCycleManager);
					scheme.setKey(new KeyImpl(tmodelKey));
					extId.setIdentificationScheme(scheme);
				}
				extidentifiers.add(extId);
			}
		}
		return extidentifiers;
	}

	private static Locale getLocale(String lang) {
		if (lang == null || lang.trim().length() == 0) {
			return Locale.getDefault();
		} else if (lang.equalsIgnoreCase(Locale.getDefault().getLanguage())) {
			return Locale.getDefault();
		} else {
			return new Locale(lang);
		} 
	}

}