/*
 * @(#)AttributeAuthority.java
 *
 * Copyright (C) 2007 Infocity Inc. All Rights Reserved.
 */
package info.dragonlady.sso.authority;

import info.dragonlady.sso.util.AssertionGenerator;
import info.dragonlady.sso.util.AssertionParser;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAttributeDesignator;
import org.opensaml.SAMLAttributeQuery;
import org.opensaml.SAMLException;
import org.opensaml.SAMLRequest;
import org.opensaml.SAMLResponse;
import org.opensaml.SAMLSubject;
import org.w3c.dom.Element;

/**
 * 属性オーソリティ抽象クラス。
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2007/04/25 16:59:45 $
 */
public abstract class AttributeAuthority implements SAMLAuthority {

	/* (non-Javadoc)
	 * @see info.dragonlady.sso.authority.SAMLAuthority#query(org.opensaml.SAMLRequest)
	 */
	public final SAMLResponse query(SAMLRequest request) throws AuthorityException {
		try {
			SAMLResponse response = new SAMLResponse(request.getId(), null, null, null);
			SAMLException samlException = null;
			String authId = null;
			List<String> attributeNames = new ArrayList<String>();
			try {
				SAMLAttributeQuery query = (SAMLAttributeQuery)request.getQuery();
				SAMLSubject subject = query.getSubject();
				SAMLAssertion authAssertion = new SAMLAssertion();
				authAssertion.fromDOM((Element)subject.getConfirmationData().getFirstChild());
				authId = new AssertionParser(authAssertion).getName();
				Iterator<SAMLAttributeDesignator> itr = query.getDesignators();
				while(itr.hasNext()) {
					attributeNames.add(itr.next().getName());
				}
			} catch(Exception e) {
				// TODO
				samlException = new SAMLException(SAMLException.REQUESTER, "", e);
			}

			if(samlException == null) {
				try {
					Map<String, List<String>> attributes = getAttributes(authId, attributeNames);
					SAMLAssertion assertion = AssertionGenerator.generateAttributeAssertion(authId, attributes);
					response.addAssertion(assertion);
					// TODO
					samlException = new SAMLException(SAMLException.SUCCESS, "");
				} catch(Exception e) {
					// TODO
					samlException = new SAMLException(SAMLException.RESPONDER, "", e);
				}
			}
			response.setStatus(samlException);
			return response;
		} catch(Exception e) {
			// TODO
			throw new AuthorityException(e);
		}
	}

	/**
	 * 属性情報取得処理。
	 * 
	 * @param authId 認証ID
	 * @param attributeNames 取得属性名
	 * @return Map<String, List<String>> 属性情報
	 * @throws AuthorityException
	 */
	protected abstract Map<String, List<String>> getAttributes(
			String authId,
			List<String> attributeNames) throws AuthorityException;

}
