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

import info.dragonlady.sso.SSOConfig;

import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.opensaml.SAMLAction;
import org.opensaml.SAMLAssertion;
import org.opensaml.SAMLAttribute;
import org.opensaml.SAMLAttributeStatement;
import org.opensaml.SAMLAuthenticationStatement;
import org.opensaml.SAMLAuthorizationDecisionStatement;
import org.opensaml.SAMLException;
import org.opensaml.SAMLNameIdentifier;
import org.opensaml.SAMLSubject;
import org.opensaml.artifact.Artifact;
import org.opensaml.artifact.SAMLArtifactType0001;
import org.opensaml.artifact.Util;

/**
 * アサーション生成ユーティリティクラス。
 * 
 * @author Hiroshi.Ebata(INFOCITY)
 * @version $Revision: 1.0 $ $Date: 2007/04/20 18:42:25 $
 */
public class AssertionGenerator {

	/**
	 * アーティファクトを生成する。
	 * 
	 * @param handle ハンドル
	 * @return Artifact アーティファクト
	 * @throws NoSuchAlgorithmException
	 * @throws ResourceParseException
	 */
	public static final Artifact generateArtifact(byte[] handle) throws NoSuchAlgorithmException, ResourceParseException {
		Artifact artifact = null;
	    byte[] srcId = Util.generateSourceId(SSOConfig.getProvider());
	    artifact = new SAMLArtifactType0001(srcId, handle);

	    return artifact;
	}

	/**
	 * 認証アサーションを生成する。
	 * 
	 * @param authId 認証ID
	 * @param attributes 属性
	 * @param authMethod 認証方法
	 * @return SAMLAssertion アサーション
	 * @throws ResourceParseException
	 * @throws SAMLException
	 */
	public static final SAMLAssertion	generateAuthenticationAssertion(String authId, String confirmationMethod, String authMethod) throws ResourceParseException, SAMLException {
		SAMLNameIdentifier identifier = new SAMLNameIdentifier(authId, null, null);
		SAMLSubject subject = new SAMLSubject(identifier, null, null, null);
		subject.addConfirmationMethod(confirmationMethod);

		// 認証ステートメント作成
		SAMLAuthenticationStatement statement = new SAMLAuthenticationStatement(subject, authMethod, new Date(), null, null, null);

		SAMLAssertion assertion = createAssertion();
		assertion.addStatement(statement);

	    return assertion;
	}

	/**
	 * 属性アサーションを生成する。
	 * 
	 * @param authId 認証ID
	 * @param attributes 属性
	 * @return SAMLAssertion アサーション
	 * @throws ResourceParseException
	 * @throws SAMLException
	 */
	public static final SAMLAssertion generateAttributeAssertion(String authId, Map<String, List<String>> attributes) throws ResourceParseException, SAMLException {
		SAMLNameIdentifier identifier = new SAMLNameIdentifier(authId, null, null);
		SAMLSubject subject = new SAMLSubject(identifier, null, null, null);

		List<SAMLAttribute> addAttr = new ArrayList<SAMLAttribute>();
		Iterator<String> itr = attributes.keySet().iterator();
		while(itr.hasNext()) {
			String key = itr.next();
			SAMLAttribute attribute = new SAMLAttribute(key, SSOConfig.getProvider(), null, 0, null);
			List<String> values = attributes.get(key);
			for(int i = 0; i < values.size(); i++) {
				attribute.addValue(values.get(i));
			}
			addAttr.add(attribute);
		}
		SAMLAttributeStatement statement = new SAMLAttributeStatement(subject, addAttr);

		SAMLAssertion assertion = createAssertion();
		assertion.addStatement(statement);

	    return assertion;
	}

	/**
	 * 認可決定アサーションを生成する。
	 * 
	 * @param authId 認証ID
	 * @param resource リソースURL
	 * @param decision 認可決定文字列
	 * @return SAMLAssertion アサーション
	 * @throws ResourceParseException
	 * @throws SAMLException
	 */
	public static final SAMLAssertion generateAuthorizationDecisionAssertion(String authId, String resource, String decision, List<SAMLAction> actions) throws ResourceParseException, SAMLException {
		SAMLNameIdentifier identifier = new SAMLNameIdentifier(authId, null, null);
		SAMLSubject subject = new SAMLSubject();
		subject.setNameIdentifier(identifier);
		SAMLAuthorizationDecisionStatement statement = new SAMLAuthorizationDecisionStatement(subject, resource, decision, actions, null);

		SAMLAssertion assertion = createAssertion();
		assertion.addStatement(statement);

	    return assertion;
	}

	private static final SAMLAssertion createAssertion() throws ResourceParseException, SAMLException {
		Calendar calendar = Calendar.getInstance();
		Date notBefore = calendar.getTime();
		calendar.add(Calendar.SECOND, SSOConfig.getAssertionLife().intValue());
		Date notOnOrAfter = calendar.getTime();

		SAMLAssertion assertion = new SAMLAssertion(SSOConfig.getIssuer(), notBefore, notOnOrAfter, null, null, null);
	    return assertion;
	}

}
