/*
 * Copyright  2003-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.security.message.token;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import junit.framework.TestCase;

import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 * TimestampTest according to org.apache.ws.security.message.token.Timestamp
 *
 * @author Christian Mueller (christian.mueller@gmail.com, christian.mueller@arcor.net)
 */
public class TimestampTest extends TestCase {
	
	private DateFormat dateFormat;
	
	private Document doc;

	private Calendar created, expires;

	public TimestampTest(String name) throws ParserConfigurationException {
		super(name);
		
		this.dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
		this.dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
		
		this.created = Calendar.getInstance();
		this.created.set(2006, Calendar.JANUARY, 7, 18, 00, 0);
		this.created.set(Calendar.MILLISECOND, 0);
		
		this.expires = Calendar.getInstance();
		this.expires.set(2006, Calendar.JANUARY, 7, 18, 05, 0); // 5 min later
		this.expires.set(Calendar.MILLISECOND, 0);
		
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		dbf.setNamespaceAware(true);
		DocumentBuilder docBuilder = dbf.newDocumentBuilder();
		this.doc = docBuilder.newDocument();
	}

	protected void setUp() throws Exception {
		super.setUp();
	}

	protected void tearDown() throws Exception {
		super.tearDown();
	}

	/**
	 * Test method for 'org.apache.ws.security.message.token.Timestamp.Timestamp(WSSConfig, Element)'
	 * 
	 * @throws WSSecurityException 
	 */
	public void testTimestampElement() throws WSSecurityException {
		// with wsu:Created and wsu:Expires
		Element timestampElement = getTimestampElement();
		timestampElement.appendChild(getCreatedElement());
		timestampElement.appendChild(getExpiresElement());
		Timestamp timestamp = new MyTimestamp(timestampElement);
		
		assertEquals(this.created, timestamp.getCreated());
		assertEquals(this.expires, timestamp.getExpires());
		assertEquals(timestampElement, timestamp.getElement());
		
		// with wsu:Created and without wsu:Expires
		
		timestampElement = getTimestampElement();
		timestampElement.appendChild(getCreatedElement());
		timestamp = new Timestamp(timestampElement);
		
		assertEquals(this.created, timestamp.getCreated());
		assertNull(timestamp.getExpires());
		assertEquals(timestampElement, timestamp.getElement());
		
		// without wsu:Created and with wsu:Expires
		
		timestampElement = getTimestampElement();
		timestampElement.appendChild(getExpiresElement());
		timestamp = new Timestamp(timestampElement);
		
		assertNull(timestamp.getCreated());
		assertEquals(this.expires, timestamp.getExpires());
		assertEquals(timestampElement, timestamp.getElement());
		
		// without wsu:Created and wsu:Expires
		
		timestampElement = getTimestampElement();
		timestamp = new Timestamp(timestampElement);
		
		assertNull(timestamp.getCreated());
		assertNull(timestamp.getExpires());
		assertEquals(timestampElement, timestamp.getElement());
	}

	/**
	 * Test method for 'org.apache.ws.security.message.token.Timestamp.Timestamp(WSSConfig, Document, int)'
	 */
	public void testTimestampBooleanDocumentInt() {
		Timestamp timestamp = new MyTimestamp(false, this.doc, 300); // 5 min

		assertEquals(this.created, timestamp.getCreated());
		assertEquals(this.expires, timestamp.getExpires());
		
		Element timestampElement = timestamp.getElement();
		assertEquals(WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN, timestampElement.getTagName());
		assertEquals(WSConstants.WSU_NS, timestampElement.getNamespaceURI());
		
		Element createdElement = (Element) timestampElement.getFirstChild();
		assertEquals(WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN, createdElement.getTagName());
		assertEquals(WSConstants.WSU_NS, createdElement.getNamespaceURI());
		assertEquals("2006-01-07T17:00:00Z", ((Text) createdElement.getFirstChild()).getData()); 
		
		Element expiredElement = (Element) createdElement.getNextSibling();
		assertEquals(WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN, expiredElement.getTagName());
		assertEquals(WSConstants.WSU_NS, expiredElement.getNamespaceURI());
		assertEquals("2006-01-07T17:05:00Z", ((Text) expiredElement.getFirstChild()).getData());
	}
	
	/**
	 * Test method for 'org.apache.ws.security.message.token.Timestamp.setId(String)'
	 */
	public void testSetId() {
		Timestamp timestamp = new MyTimestamp(false, this.doc, 300); // 5 min
		timestamp.setID("id-0815");

		assertEquals("id-0815", timestamp.getID());
		assertEquals("id-0815", timestamp.getElement().getAttributeNS(WSConstants.WSU_NS, "Id"));
	}
	
	private Element getTimestampElement() {
		return this.doc.createElementNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN);
	}
	
	private Element getCreatedElement() {
		Element createdElement = this.doc.createElementNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN);
        createdElement.appendChild(this.doc.createTextNode(this.dateFormat.format(this.created.getTime())));
        return createdElement;
	}
	
	private Element getExpiresElement() {
        Element expiresElement = this.doc.createElementNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN);
        expiresElement.appendChild(this.doc.createTextNode(this.dateFormat.format(this.expires.getTime())));
        return expiresElement;
	}
	
	public class MyTimestamp extends Timestamp {

		public MyTimestamp(boolean milliseconds, Document doc, int ttl) {
			super(milliseconds, doc, ttl);
		}
		
		public MyTimestamp(Element element) throws WSSecurityException {
			super(element);
		}
		
		protected Calendar getCurrentTime() {
			Calendar currentTime = Calendar.getInstance();
			currentTime.set(2006, Calendar.JANUARY, 7, 18, 00, 0);
			currentTime.set(Calendar.MILLISECOND, 0);
			
			return currentTime;
		}
	}
}

