/**
 *
 * 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.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import javax.xml.registry.JAXRException;
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.Key;
import javax.xml.registry.infomodel.LocalizedString;
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.Slot;
import javax.xml.registry.infomodel.SpecificationLink;
import javax.xml.registry.infomodel.TelephoneNumber;
import javax.xml.registry.infomodel.User;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.uddi.api_v3.*;
import org.apache.ws.scout.registry.infomodel.InternationalStringImpl;

/**
 * Helper class that does Jaxr->UDDI Mapping
 *
 * @author <a href="mailto:anil@apache.org">Anil Saldhana</a>
 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
 * @author <a href="mailto:kstam@apache.org">Kurt T Stam</a>
 * @author <a href="mailto:tcunning@apache.org">Tom Cunningham</a>
 */
public class ScoutJaxrUddiV3Helper 
{
    private static final String UDDI_ORG_TYPES = "uuid:C1ACF26D-9672-4404-9D70-39B756E62AB4";
	private static Log log = LogFactory.getLog(ScoutJaxrUddiV3Helper.class);
	private static ObjectFactory objectFactory = new ObjectFactory();
	
    /**
     * Get UDDI Address given JAXR Postal Address
     */
	public static Address getAddress(PostalAddress postalAddress) throws JAXRException {
		Address address = objectFactory.createAddress();

		AddressLine[] addarr = new AddressLine[7];

        String stnum = postalAddress.getStreetNumber();
        String st = postalAddress.getStreet();
        String city = postalAddress.getCity();
        String country = postalAddress.getCountry();
        String code = postalAddress.getPostalCode();
        String state = postalAddress.getStateOrProvince();
        String type = postalAddress.getType();

		AddressLine stnumAL = objectFactory.createAddressLine();
        stnumAL.setKeyName("STREET_NUMBER");
		if (stnum != null) {
			stnumAL.setKeyValue(stnum);
			stnumAL.setValue(stnum);
		}

		AddressLine stAL = objectFactory.createAddressLine();
        stAL.setKeyName("STREET");
		if (st != null) {
			stAL.setKeyValue(st);
			stAL.setValue(st);
		}

		AddressLine cityAL = objectFactory.createAddressLine();
        cityAL.setKeyName("CITY");
		if (city != null) {
			cityAL.setKeyValue(city);
			cityAL.setValue(city);
		}

		AddressLine countryAL = objectFactory.createAddressLine();
        countryAL.setKeyName("COUNTRY");
		if (country != null) {
			countryAL.setKeyValue(country);
			countryAL.setValue(country);
		}

		AddressLine codeAL = objectFactory.createAddressLine();
        codeAL.setKeyName("POSTALCODE");
		if (code != null) {
			codeAL.setKeyValue(code);
			codeAL.setValue(code);
		}

		AddressLine stateAL = objectFactory.createAddressLine();
        stateAL.setKeyName("STATE");
		if (state != null) {
			stateAL.setKeyValue(state);
			stateAL.setValue(state);
		}
		
        AddressLine typeAL = objectFactory.createAddressLine();
        typeAL.setKeyName("TYPE");
        if (type != null) {
                typeAL.setKeyValue(type);
                typeAL.setValue(type);
        }

		// Add the AddressLine to vector
		addarr[0] = stnumAL;
		addarr[1] = stAL;
		addarr[2] = cityAL;
		addarr[3] = countryAL;
		addarr[4] = codeAL;
		addarr[5] = stateAL;
		addarr[6] = typeAL;
		
		address.getAddressLine().addAll(Arrays.asList(addarr));

        return address;
    }

	public static BindingTemplate getBindingTemplateFromJAXRSB(
			ServiceBinding serviceBinding) throws JAXRException {
		BindingTemplate bt = objectFactory.createBindingTemplate();
		if (serviceBinding.getKey() != null && serviceBinding.getKey().getId() != null) {
			bt.setBindingKey(serviceBinding.getKey().getId());
		} else {
			bt.setBindingKey("");
		}
	
		try {
			// Set Access URI
            String accessuri = serviceBinding.getAccessURI();
			if (accessuri != null) {
				AccessPoint accessPoint = objectFactory.createAccessPoint();
                accessPoint.setUseType(getUseType(accessuri));
				accessPoint.setValue(accessuri);
                bt.setAccessPoint(accessPoint);
            }
            ServiceBinding sb = serviceBinding.getTargetBinding();
			if (sb != null) {
				HostingRedirector red = objectFactory.createHostingRedirector();
                Key key = sb.getKey();
				if (key != null && key.getId() != null) {
					red.setBindingKey(key.getId());
                } else {
                    red.setBindingKey("");
                }
                bt.setHostingRedirector(red);
            } else {
            	if (bt.getAccessPoint() == null) {
            		bt.setAccessPoint(objectFactory.createAccessPoint());
            	}
            }
			// TODO:Need to look further at the mapping b/w BindingTemplate and
			// Jaxr ServiceBinding

			// Get Service information
           Service svc = serviceBinding.getService();
			if (svc != null && svc.getKey() != null && svc.getKey().getId() != null) {
              bt.setServiceKey(svc.getKey().getId());
           }
			
			InternationalString idesc = serviceBinding.getDescription();
            
            addDescriptions(bt.getDescription(), idesc);

			// SpecificationLink
           Collection<SpecificationLink> slcol = serviceBinding.getSpecificationLinks();
			TModelInstanceDetails tid = objectFactory.createTModelInstanceDetails();
			if (slcol != null && !slcol.isEmpty()) {
              Iterator<SpecificationLink> iter = slcol.iterator();
				while (iter.hasNext()) {
					SpecificationLink slink = (SpecificationLink) iter.next();

					TModelInstanceInfo emptyTInfo = objectFactory.createTModelInstanceInfo();
					tid.getTModelInstanceInfo().add(emptyTInfo);

                    RegistryObject specificationObject = slink.getSpecificationObject();
					if (specificationObject.getKey() != null && specificationObject.getKey().getId() != null) {
						emptyTInfo.setTModelKey(specificationObject.getKey().getId());
                        if (specificationObject.getDescription()!=null) {
                            for (Object o : specificationObject.getDescription().getLocalizedStrings()) {
                                LocalizedString locDesc = (LocalizedString) o;
                                Description description = objectFactory.createDescription();
                                emptyTInfo.getDescription().add(description);
                                description.setValue(locDesc.getValue());
                                description.setLang(locDesc.getLocale().getLanguage());
                            }
                        }
                        Collection<ExternalLink> externalLinks = slink.getExternalLinks();
                        if (externalLinks!=null && externalLinks.size()>0) {
                            for (ExternalLink link : externalLinks) {
                                InstanceDetails ids = objectFactory.createInstanceDetails();
                                emptyTInfo.setInstanceDetails(ids);
                                if (link.getDescription()!=null) {
                                    Description description = objectFactory.createDescription();
                                    ids.getDescription().add(description);
                                    description.setValue(link.getDescription().getValue());
                                }
                                if (link.getExternalURI()!=null) {
                                    OverviewDoc overviewDoc = objectFactory.createOverviewDoc();
                                    ids.getOverviewDoc().add(overviewDoc);
                                    org.uddi.api_v3.OverviewURL ourl = new org.uddi.api_v3.OverviewURL();
                                    ourl.setValue(link.getExternalURI());
                                    overviewDoc.setOverviewURL(ourl);
                                }
                            } 
                        }
					}
              }
            }
			if (tid.getTModelInstanceInfo().size() != 0) {
				bt.setTModelInstanceDetails(tid);
			}
			log.debug("BindingTemplate=" + bt.toString());
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return bt;
    }

	public static PublisherAssertion getPubAssertionFromJAXRAssociation(
			Association association) throws JAXRException {
		PublisherAssertion pa = objectFactory.createPublisherAssertion();
		try {
			if (association.getSourceObject().getKey() != null && 
				association.getSourceObject().getKey().getId() != null) {
            pa.setFromKey(association.getSourceObject().getKey().getId());
			}
			
			if (association.getTargetObject().getKey() != null &&
				association.getTargetObject().getKey().getId() != null) {
            pa.setToKey(association.getTargetObject().getKey().getId());
			}
            Concept c = association.getAssociationType();
            String v = c.getValue();
			KeyedReference kr = objectFactory.createKeyedReference();
            Key key = c.getKey();
			if (key == null) {
				// TODO:Need to check this. If the concept is a predefined
				// enumeration, the key can be the parent classification scheme
                key = c.getClassificationScheme().getKey();
            }
			if (key != null && key.getId() != null) {
				kr.setTModelKey(key.getId());
			} 
            kr.setKeyName("Concept");

			if (v != null) {
				kr.setKeyValue(v);
			}

            pa.setKeyedReference(kr);
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return pa;
    }

	public static PublisherAssertion getPubAssertionFromJAXRAssociationKey(
			String key) throws JAXRException {
		PublisherAssertion pa = objectFactory.createPublisherAssertion();
		try {
			StringTokenizer token = new StringTokenizer(key, ":");
			if (token.hasMoreTokens()) {
               pa.setFromKey(getToken(token.nextToken()));
               pa.setToKey(getToken(token.nextToken()));
				KeyedReference kr = objectFactory.createKeyedReference();
				// Sometimes the Key is UUID:something
               String str = getToken(token.nextToken());
				if ("UUID".equals(str))
					str += ":" + getToken(token.nextToken());
               kr.setTModelKey(str);
               kr.setKeyName(getToken(token.nextToken()));
               kr.setKeyValue(getToken(token.nextToken()));
               pa.setKeyedReference(kr);
            }

		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return pa;
    }

	public static BusinessService getBusinessServiceFromJAXRService(
			Service service) throws JAXRException {
		BusinessService bs = objectFactory.createBusinessService();
		try {
			InternationalString iname = service.getName();
						
			addNames(bs.getName(), iname);
	         
            InternationalString idesc = service.getDescription();
    
           addDescriptions(bs.getDescription(), idesc);

            Organization o = service.getProvidingOrganization();

            /*
             * there may not always be a key...
             */
            if (o != null) {
                Key k = o.getKey();

				if (k != null && k.getId() != null) {
                    bs.setBusinessKey(k.getId());
                } 
                    
			} else {
                /*
                 * gmj - I *think* this is the right thing to do
                 */
				throw new JAXRException(
						"Service has no associated organization");
            }

			if (service.getKey() != null && service.getKey().getId() != null) {
                bs.setServiceKey(service.getKey().getId());
            } else {
                bs.setServiceKey("");
            }

            CategoryBag catBag = getCategoryBagFromClassifications(service.getClassifications());
            if (catBag!=null) {
                bs.setCategoryBag(catBag);
            }

            //Add the ServiceBinding information
            BindingTemplates bt = getBindingTemplates(service.getServiceBindings());
            if (bt != null) {
                bs.setBindingTemplates(bt);
            }
   		    
            log.debug("BusinessService=" + bs.toString());
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return bs;
    }

	public static TModel getTModelFromJAXRClassificationScheme(
			ClassificationScheme classificationScheme) throws JAXRException {
		TModel tm = objectFactory.createTModel();
		try {
            /*
             * a fresh scheme might not have a key
             */

            Key k = classificationScheme.getKey();

            if (k != null && k.getId() != null) {
                tm.setTModelKey(k.getId());
            } else {
                tm.setTModelKey("");
            }

            /*
             * There's no reason to believe these are here either
             */

            Slot s = classificationScheme.getSlot("authorizedName");
/*
			if (s != null && s.getName() != null) {
                tm.setAuthorizedName(s.getName());
            }
*/
            s = classificationScheme.getSlot("operator");
/*
			if (s != null && s.getName() != null) {
                tm.setOperator(s.getName());
            }
*/
			InternationalString iname = classificationScheme.getName();
			 
            tm.setName(getFirstName(iname));

			InternationalString idesc = classificationScheme.getDescription();
			
		    addDescriptions(tm.getDescription(), idesc);

            IdentifierBag idBag = getIdentifierBagFromExternalIdentifiers(classificationScheme.getExternalIdentifiers());
            if (idBag!=null) {
                tm.setIdentifierBag(idBag);
            }
            CategoryBag catBag = getCategoryBagFromClassifications(classificationScheme.getClassifications());
            if (catBag!=null) {
                tm.setCategoryBag(catBag);
            }
			
			// ToDO: overviewDoc
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return tm;
    }

    public static TModel getTModelFromJAXRConcept(Concept concept)
			throws JAXRException {
    	TModel tm = objectFactory.createTModel();
		if (concept == null)
			return null;
		try {
            Key key = concept.getKey();
			if (key != null && key.getId() != null)
				tm.setTModelKey(key.getId());
            Slot sl1 = concept.getSlot("authorizedName");
            /*
			if (sl1 != null && sl1.getName() != null)
				tm.setAuthorizedName(sl1.getName());

            Slot sl2 = concept.getSlot("operator");
			if (sl2 != null && sl2.getName() != null)
				tm.setOperator(sl2.getName());
			*/
			InternationalString iname = concept.getName();

            tm.setName(getFirstName(iname));

            InternationalString idesc = concept.getDescription();
			
            addDescriptions(tm.getDescription(), idesc);

//          External Links
            Collection<ExternalLink> externalLinks = concept.getExternalLinks(); 
            if(externalLinks != null && externalLinks.size() > 0)
            {
                tm.getOverviewDoc().add(getOverviewDocFromExternalLink((ExternalLink)externalLinks.iterator().next()));
            }  

            IdentifierBag idBag = getIdentifierBagFromExternalIdentifiers(concept.getExternalIdentifiers());
            if (idBag!=null) {
                tm.setIdentifierBag(idBag);
            }
            CategoryBag catBag = getCategoryBagFromClassifications(concept.getClassifications());
            if (catBag!=null) {
                tm.setCategoryBag(catBag);
            }

		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return tm;
    }

    private static void addDescriptions(List<Description> descripions, InternationalString idesc) throws JAXRException {
        if (idesc != null) {
            for (Object o : idesc.getLocalizedStrings()) {
                LocalizedString locName = (LocalizedString) o;
                Description desc = objectFactory.createDescription();
                descripions.add(desc);
                desc.setValue(locName.getValue());
                desc.setLang(locName.getLocale().getLanguage());
            }
        }
    }

    private static Name getFirstName(InternationalString iname) throws JAXRException {
        for (Object o : iname.getLocalizedStrings()) {
            LocalizedString locName = (LocalizedString) o;
            Name name = objectFactory.createName();
            name.setValue(locName.getValue());
            name.setLang(locName.getLocale().getLanguage());
            return name;
        }
        return null;
    }
    private static void addNames(List<Name> names, InternationalString iname) throws JAXRException {
        for (Object o : iname.getLocalizedStrings()) {
            LocalizedString locName = (LocalizedString) o;
            Name name = objectFactory.createName();
            name.setValue(locName.getValue());
            name.setLang(locName.getLocale().getLanguage());
            names.add(name);
        }
    }

    public static BusinessEntity getBusinessEntityFromJAXROrg(Organization organization)
			throws JAXRException {
		BusinessEntity biz = objectFactory.createBusinessEntity();
		BusinessServices bss = objectFactory.createBusinessServices();
		BusinessService[] barr = new BusinessService[0];

		try {
			// It may just be an update
            Key key = organization.getKey();
			if (key != null && key.getId() != null) {
				biz.setBusinessKey(key.getId());
            } else {
                biz.setBusinessKey("");
            }
			// Lets get the Organization attributes at the top level
			
			InternationalString iname = organization.getName();
			
			if (iname != null) {
                addNames(biz.getName(), iname);
			}
			
			InternationalString idesc = organization.getDescription();
			
            addDescriptions(biz.getDescription(), idesc);

			if (organization.getPrimaryContact() != null && 
				organization.getPrimaryContact().getPersonName()!= null &&
				organization.getPrimaryContact().getPersonName().getFullName() != null) {

				//biz.setAuthorizedName(organization.getPrimaryContact().getPersonName()
				//		.getFullName());
			}

            Collection<Service> s = organization.getServices();
            log.debug("?Org has services=" + s.isEmpty());

			barr = new BusinessService[s.size()];

            Iterator<Service> iter = s.iterator();
			int barrPos = 0;
			while (iter.hasNext()) {
				BusinessService bs = ScoutJaxrUddiV3Helper
						.getBusinessServiceFromJAXRService((Service) iter
								.next());
				barr[barrPos] = bs;
				barrPos++;
            }

            /*
             * map users : JAXR has concept of 'primary contact', which is a
             * special designation for one of the users, and D6.1 seems to say
             * that the first UDDI user is the primary contact
             */

			Contacts cts = objectFactory.createContacts();
			Contact[] carr = new Contact[0];

            User primaryContact = organization.getPrimaryContact();
            Collection<User> users = organization.getUsers();

            // Expand array to necessary size only (xmlbeans does not like
            // null items in cases like this)

            int carrSize = 0;

            if (primaryContact != null) {
                carrSize += 1;
            }

            // TODO: Clean this up and make it more efficient
            Iterator<User> it = users.iterator();
            while (it.hasNext()) {
                User u = (User) it.next();
                if (u != primaryContact) {
                    carrSize++;
                }
            }

            carr = new Contact[carrSize];

            /*
             * first do primary, and then filter that out in the loop
             */
            if (primaryContact != null) {
                Contact ct = getContactFromJAXRUser(primaryContact);
                carr[0] = ct;
            }

            it = users.iterator();
            int carrPos = 1;
            while (it.hasNext()) {
                User u = (User) it.next();

                if (u != primaryContact) {
                    Contact ct = getContactFromJAXRUser(u);
                    carr[carrPos] = ct;
                    carrPos++;
                }
            }

			bss.getBusinessService().addAll(Arrays.asList(barr));
            if (carr.length>0) {
                cts.getContact().addAll(Arrays.asList(carr));
                biz.setContacts(cts);
            }
            biz.setBusinessServices(bss);

            // External Links
            Iterator<ExternalLink> exiter = organization.getExternalLinks().iterator();
            DiscoveryURLs emptyDUs = null;
            boolean first = true;
            while (exiter.hasNext()) {
                ExternalLink link = (ExternalLink) exiter.next();
                /** Note: jUDDI adds its own discoverURL as the businessEntity* */
                if (first) {
                    emptyDUs = objectFactory.createDiscoveryURLs();
                    biz.setDiscoveryURLs(emptyDUs);
                    first = false;
                }
                DiscoveryURL emptyDU = objectFactory.createDiscoveryURL();
                emptyDUs.getDiscoveryURL().add(emptyDU);
                emptyDU.setUseType("businessEntityExt");
				
                if (link.getExternalURI() != null) {
                    emptyDU.setValue(link.getExternalURI());
                }
            }
			
          IdentifierBag idBag = getIdentifierBagFromExternalIdentifiers(organization.getExternalIdentifiers());
          if (idBag!=null) {
              biz.setIdentifierBag(idBag);
          }
          CategoryBag catBag = getCategoryBagFromClassifications(organization.getClassifications());
          if (catBag!=null) {
              biz.setCategoryBag(catBag);
          }
			
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return biz;
    }

    /**
     *
     * Convert JAXR User Object to UDDI  Contact
     */
    public static Contact getContactFromJAXRUser(User user)
			throws JAXRException {
		Contact ct = objectFactory.createContact();
        if (user == null) {
            return null;
        }

		Address[] addarr = new Address[0];
		Phone[] phonearr = new Phone[0];
		Email[] emailarr = new Email[0];
		try {
			
			if (user.getPersonName() != null && user.getPersonName().getFullName() != null) {
				org.uddi.api_v3.PersonName pn = new org.uddi.api_v3.PersonName();
				pn.setValue(user.getPersonName().getFullName());
				ct.getPersonName().add(pn);
			}
			
			if (user.getType() != null) {
            ct.setUseType(user.getType());
			}
			// Postal Address
            Collection<PostalAddress> postc = user.getPostalAddresses();

			addarr = new Address[postc.size()];

            Iterator<PostalAddress> iterator = postc.iterator();
			int addarrPos = 0;
			while (iterator.hasNext()) {
                PostalAddress post = (PostalAddress) iterator.next();
				addarr[addarrPos] = ScoutJaxrUddiV3Helper.getAddress(post);
				addarrPos++;
            }
			// Phone Numbers
            Collection ph = user.getTelephoneNumbers(null);

			phonearr = new Phone[ph.size()];

            Iterator it = ph.iterator();
			int phonearrPos = 0;
			while (it.hasNext()) {
                TelephoneNumber t = (TelephoneNumber) it.next();
				Phone phone = objectFactory.createPhone();
                String str = t.getNumber();
                log.debug("Telephone=" + str);
				
				// FIXME: If phone number is null, should the phone 
				// not be set at all, or set to empty string?
				if (str != null) {
					phone.setValue(str);
				} else {
					phone.setValue("");
				}

				phonearr[phonearrPos] = phone;
				phonearrPos++;
            }

			// Email Addresses
            Collection ec = user.getEmailAddresses();

			emailarr = new Email[ec.size()];

            Iterator iter = ec.iterator();
			int emailarrPos = 0;
			while (iter.hasNext()) {
                EmailAddress ea = (EmailAddress) iter.next();
				Email email = objectFactory.createEmail();
				
				if (ea.getAddress() != null) {
					email.setValue(ea.getAddress());
				}
				// email.setText( ea.getAddress() );
				
				if (ea.getType() != null) {
                email.setUseType(ea.getType());
            }

				emailarr[emailarrPos] = email;
				emailarrPos++;
			}
			ct.getAddress().addAll(Arrays.asList(addarr));
			ct.getPhone().addAll(Arrays.asList(phonearr));
			ct.getEmail().addAll(Arrays.asList(emailarr));
		} catch (Exception ud) {
            throw new JAXRException("Apache JAXR Impl:", ud);
        }
        return ct;
    }

	private static String getToken(String tokenstr) {
		// Token can have the value NULL which need to be converted into null
		if (tokenstr.equals("NULL"))
			tokenstr = "";
      return tokenstr;
   }

	private static String getUseType(String accessuri) {
       String acc = accessuri.toLowerCase();
		String uri = "other";
		if (acc.startsWith("http:"))
			uri = "http:";
		else if (acc.startsWith("https:"))
			uri = "https:";
		else if (acc.startsWith("ftp:"))
			uri = "ftp:";
		else if (acc.startsWith("phone:"))
			uri = "phone:";

       return uri;
   }
    
	/**
     * According to JAXR Javadoc, there are two types of classification, internal and external and they use the Classification, Concept,     
     * and ClassificationScheme objects.  It seems the only difference between internal and external (as related to UDDI) is that the
     * name/value pair of the categorization is held in the Concept for internal classifications and the Classification for external (bypassing
     * the Concept entirely).
     * 
     * The translation to UDDI is simple.  Relevant objects have a category bag which contains a bunch of KeyedReferences (name/value pairs).  
     * These KeyedReferences optionally refer to a tModel that identifies the type of category (translates to the ClassificationScheme key).  If
     * this is set and the tModel doesn't exist in the UDDI registry, then an invalid key error will occur when trying to save the object.
     * 
     * @param classifications classifications to turn into categories
     * @throws JAXRException
     */
	public static CategoryBag getCategoryBagFromClassifications(Collection classifications) throws JAXRException {
    	try {
			if (classifications == null || classifications.size()==0)
				return null;
    		
    		// Classifications
			CategoryBag cbag = objectFactory.createCategoryBag();
			Iterator classiter = classifications.iterator();
			while (classiter.hasNext()) {
				Classification classification = (Classification) classiter.next();
				if (classification != null ) {
					KeyedReference keyr = objectFactory.createKeyedReference();
					cbag.getKeyedReference().add(keyr);
	
					InternationalStringImpl iname = null;
					String value = null;
					ClassificationScheme scheme = classification.getClassificationScheme();
                    if (scheme==null || (classification.isExternal() && classification.getConcept()==null)) {
                        /*
                        * JAXR 1.0 Specification: Section D6.4.4
                        * Specification related tModels mapped from Concept may be automatically
                        * categorized by the well-known uddi-org:types taxonomy in UDDI (with
                        * tModelKey uuid:C1ACF26D-9672-4404-9D70-39B756E62AB4) as follows:
                        * The keyed reference is assigned a taxonomy value of specification.
                        */
                        keyr.setTModelKey(UDDI_ORG_TYPES);
                        keyr.setKeyValue("specification"); 
                    } else {
    					if (classification.isExternal()) {
                            iname = (InternationalStringImpl) ((RegistryObject) classification).getName();
                            value = classification.getValue();
    					} else {
    						Concept concept = classification.getConcept();
    						if (concept != null) {
    							iname = (InternationalStringImpl) ((RegistryObject) concept).getName();
    							value = concept.getValue();
    							scheme = concept.getClassificationScheme();
    						}
    					}
    	
    					String name = iname.getValue();
    					if (name != null)
    						keyr.setKeyName(name);
    	
    					if (value != null)
    						keyr.setKeyValue(value);
    					
    					if (scheme != null) {
    						Key key = scheme.getKey();
    						if (key != null && key.getId() != null)
    							keyr.setTModelKey(key.getId());
    					}
    				}
                }
			}
			return cbag;
    	} catch (Exception ud) {
			throw new JAXRException("Apache JAXR Impl:", ud);
		}
    }

	public static TModelBag getTModelBagFromSpecifications(Collection specifications) throws JAXRException {
    	try {
			if (specifications == null || specifications.size()==0)
				return null;
    		
    		// Classifications
			TModelBag tbag = objectFactory.createTModelBag();
			Iterator speciter = specifications.iterator();
			while (speciter.hasNext()) {
				RegistryObject registryobject = (RegistryObject) speciter.next();
				if (registryobject instanceof SpecificationLink) {
					SpecificationLink specificationlink = (SpecificationLink) registryobject;
					if (specificationlink.getSpecificationObject() != null) {
						RegistryObject ro = specificationlink.getSpecificationObject();
						if (ro.getKey() != null) {
							Key key = ro.getKey();
							tbag.getTModelKey().add(key.toString());
						}
					}
				} else {
					log.info("ebXML case - the RegistryObject is an ExtrinsicObject, Not implemented");
				}
			}
			return tbag;
    	} catch (Exception ud) {
			throw new JAXRException("Apache JAXR Impl:", ud);
		}
    }

	
	/**
     * Adds the objects identifiers from JAXR's external identifier collection
     * 
     * @param identifiers external identifiers to turn into identifiers
     * @throws JAXRException
     */
	public static IdentifierBag getIdentifierBagFromExternalIdentifiers(Collection identifiers) throws JAXRException {
    	try {
			if (identifiers == null || identifiers.size()==0)
				return null;
    		
    		// Identifiers
			IdentifierBag ibag = objectFactory.createIdentifierBag();
			Iterator iditer = identifiers.iterator();
			while (iditer.hasNext()) {
				ExternalIdentifier extid = (ExternalIdentifier) iditer.next();
				if (extid != null ) {
					KeyedReference keyr = objectFactory.createKeyedReference();
					ibag.getKeyedReference().add(keyr);
	
					InternationalStringImpl iname = (InternationalStringImpl) ((RegistryObject) extid).getName();
					String value = extid.getValue();
					ClassificationScheme scheme = extid.getIdentificationScheme();
	
					String name = iname.getValue();
					if (name != null)
						keyr.setKeyName(name);
	
					if (value != null)
						keyr.setKeyValue(value);
					
					if (scheme != null) {
						Key key = scheme.getKey();
						if (key != null && key.getId() != null)
							keyr.setTModelKey(key.getId());
					}
				}
			}
			return ibag;
    	} catch (Exception ud) {
			throw new JAXRException("Apache JAXR Impl:", ud);
		}
    }
    
    private static OverviewDoc getOverviewDocFromExternalLink(ExternalLink link)
       throws JAXRException
       {
           OverviewDoc od = objectFactory.createOverviewDoc();
           String url = link.getExternalURI();
           if(url != null) {
        	   org.uddi.api_v3.OverviewURL ourl = new org.uddi.api_v3.OverviewURL();
        	   ourl.setValue(url.toString());
        	   od.setOverviewURL(ourl);
           }
           InternationalString extDesc = link.getDescription();
           if(extDesc != null) {
               Description description = objectFactory.createDescription();
               od.getDescription().add(description);
               description.setValue(extDesc.getValue());
           }
           return od;
       }

    private static BindingTemplates getBindingTemplates(Collection serviceBindings)
        throws JAXRException {
        BindingTemplates bt = null;
        if(serviceBindings != null && serviceBindings.size() > 0) {
            bt = objectFactory.createBindingTemplates();
            Iterator iter = serviceBindings.iterator();
            int currLoc = 0;
            BindingTemplate[] bindingTemplateArray = new BindingTemplate[serviceBindings.size()];
            while(iter.hasNext()) {
                ServiceBinding sb = (ServiceBinding)iter.next();
                bindingTemplateArray[currLoc] = getBindingTemplateFromJAXRSB(sb);
                currLoc++;
            }
            if (bindingTemplateArray != null) {
                bt.getBindingTemplate().addAll(Arrays.asList(bindingTemplateArray));
            }
        }
        return bt; 
    }
}
