/*
 *  Copyright (C) 2006  Takashi Kasuya <kasuya@sfc.keio.ac.jp>
 *
 * This library is free software; you can redistribute it and/or
 *　modify it under the terms of the GNU Lesser General Public
 *　License as published by the Free Software Foundation; either
 *　version 2.1 of the License, or (at your option) any later version.
 *　This library is distributed in the hope that it will be useful,
 *　but WITHOUT ANY WARRANTY; without even the implied warranty of
 *　MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *　Lesser General Public License for more details.
 *
 *　You should have received a copy of the GNU Lesser General Public
 *　License along with this library; if not, write to the Free Software
 *　Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */


package jp.ac.naka.ec.sip;

import gov.nist.javax.sip.address.SipUri;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TooManyListenersException;

import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.InvalidArgumentException;
import javax.sip.ListeningPoint;
import javax.sip.RequestEvent;
import javax.sip.ServerTransaction;
import javax.sip.SipException;
import javax.sip.SipFactory;
import javax.sip.SipListener;
import javax.sip.SipProvider;
import javax.sip.SipStack;
import javax.sip.address.Address;
import javax.sip.address.AddressFactory;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.header.ContactHeader;
import javax.sip.header.ContentTypeHeader;
import javax.sip.header.EventHeader;
import javax.sip.header.ExpiresHeader;
import javax.sip.header.FromHeader;
import javax.sip.header.HeaderFactory;
import javax.sip.header.MaxForwardsHeader;
import javax.sip.header.SubscriptionStateHeader;
import javax.sip.header.ToHeader;
import javax.sip.header.ViaHeader;
import javax.sip.message.MessageFactory;
import javax.sip.message.Request;
import javax.sip.message.Response;

import jp.ac.naka.ec.EventDispatcher;
import jp.ac.naka.ec.EventSource;
import jp.ac.naka.ec.TreeNode;
import jp.ac.naka.ec.entity.Entity;
import jp.ac.naka.ec.entity.EntityContainer;
import jp.ac.naka.ec.entity.EntityEvent;
import jp.ac.naka.ec.entity.EntityEventDispatcher;
import jp.ac.naka.ec.entity.EntityListener;
import jp.ac.naka.ec.sip.pidf.PIDFData;
import jp.ac.naka.ec.sip.pidf.PIDFFactory;
import jp.ac.naka.ec.sip.pidf.PIDFFactoryImpl;
import net.sourceforge.jsdp.SessionDescription;

import org.apache.log4j.Logger;

/**
 * SIPリクエスト、レスポンスの送信を行うクラス。NOTIFYリクエストのの自動送信もになう。
 * 
 * @author Takashi Kasuya
 * 
 */
public class SipCore extends EventSource{

	private static SipProvider provider;
	private static SipListener listener;

	private static MessageFactory messageFactory;
	private static AddressFactory addressFactory;
	private static HeaderFactory headerFactory;

	private SipURI uri;
	private static boolean initialized = false;

	private static EntityContainer con;
	private static SipCore instance = new SipCore();

	public static int DEFAULT_EXPIRES = 3600;
	public static String event_package = "presence";

	private static Map<String, Dialog> dialogTable = new HashMap<String, Dialog>();
	private static final String pathname = "gov.nist";

	private static final String TRANSPORT = "udp";

	private static Logger logger = Logger.getLogger(SipCore.class);
	private PIDFFactory pidfFactory;
	
	/**
	 * 
	 * @param user_name Name of EntityContainer
	 * @param hostname 
	 * @param sip_port
	 * @param sip_config
	 * @throws SipException
	 * @throws IOException
	 * @throws ParseException
	 * @throws InvalidArgumentException
	 * @throws TooManyListenersException
	 */
	public static void initialize(String user_name, String hostname, int sip_port,
			String sip_config) throws SipException, IOException, ParseException, InvalidArgumentException, TooManyListenersException {
		SipFactory sipFactory = SipFactory.getInstance();
		sipFactory.setPathName(pathname);
		
		Properties prop = new Properties();
		prop.load(new FileInputStream(sip_config));
		// v1.2で非推奨
		// prop.setProperty("javax.sip.IP_ADDRESS", hostname);
		SipStack sipStack = null;
		sipStack = sipFactory.createSipStack(prop);
		addressFactory = sipFactory.createAddressFactory();

		URI uri = addressFactory.createSipURI(user_name, hostname + ":"
				+ sip_port);
		logger.info("getHostAddress:\t" + uri.toString());

		ListeningPoint lp = sipStack.createListeningPoint(hostname,
				sip_port, TRANSPORT);
		// ListeningPoint lp1 =
		// sipStack.createListeningPoint(getPort(),"tcp");

		SipProvider sipProvider = sipStack.createSipProvider(lp);
		// sipProvider.addSipListener();
		// sipProvider = sipStack.createSipProvider(lp1);
		listener = new DefaultListener();
		sipProvider.addSipListener(listener);

		provider = sipProvider;
		
		messageFactory = sipFactory.createMessageFactory();
		headerFactory = sipFactory.createHeaderFactory();
		
		EventDispatcher dispatcher = instance.getEventDispatcher();

		dispatcher.addEntityListener(new EntityListener() {
			public void receiveMessage(EntityEvent e) {
				Entity target = (Entity) e.getTarget();
				switch (e.getEventType()) {
				case INIT:
					// REGISTER送信
					try {
						instance.sendRequest((Entity) e.getTarget(),
								Request.REGISTER);
					} catch (SipException se) {
						logger.error("Error while sending REGISTER to "
								+ target.getURI());
					}
					break;
				case ACK:
					Dialog dialog = dialogTable.get(target.getURI().toString());
					Request ack;
					try {
						ack = dialog.createAck(dialog.getLocalSeqNumber());
						logger.info("Send ACK to " + dialog.getRemoteTarget());
						dialog.sendAck(ack);
					} catch (Exception e1) {
						logger.warn("Error while sending ACK", e1);
					}
					break;
				case MESSAGE:
					if (e.isBroadcast()) {
						Set<Entity> entities = con.getEntities();
						for (Iterator<Entity> iter = entities.iterator(); iter
								.hasNext();) {
							target = iter.next();
							if (!target.isLocal()
									&& target instanceof EntityContainer) {
								try {
									Request req = instance.createRequest(
											target, con, Request.MESSAGE);
									req.setContent(e.getMessage(),
											headerFactory
													.createContentTypeHeader(
															"text", "plain"));
									provider.sendRequest(req);
								} catch (Exception e1) {
									logger.warn(
											"Error while sending MESSAGE to "
													+ target, e1);
								}
								logger.info("Send MESSAGE to "
										+ target.getURI());
							}
						}
					} else {
						Entity source = (Entity) e.getSource();
						Set<TreeNode> set = con.getChildNodes();

						if (!source.isLocal() || target.isLocal()) {
							return;
						}
						if (!set.contains(target) && con.include(target)
								&& !target.equals(con)) {
							try {
								Request req = instance.createRequest(target,
										con, Request.MESSAGE);
								req.setContent(e.getMessage(), headerFactory
										.createContentTypeHeader("text",
												"plain"));
								provider.sendRequest(req);
							} catch (Exception e1) {
								logger.warn("Error while sending MESSAGE to "
										+ target, e1);
							}
						} else {
							logger
									.info("No External Entry :"
											+ target.getURI());
						}
					}
				}
			}

			public SessionDescription receiveOffer(EntityEvent evt) {
				Entity target = (Entity) evt.getTarget();
				if (target.isLocal()) {
					return null;
				}
				Entity source = (Entity) evt.getSource();
				try {
					instance.sendRequest(
							evt.getSessionDescription().toString(), target,
							source, Request.INVITE);
				} catch (Exception e) {
					logger.warn("Error while sending INVITE to " + target, e);
				}
				return null;
			}

			public void receiveBye(EntityEvent evt) {
				Entity target = (Entity) evt.getTarget();
				if (target.isLocal()) {
					return;
				}
				Entity source = (Entity) evt.getSource();
				try {
					instance.sendRequest("", target, source, Request.BYE);
				} catch (Exception e) {
					logger.warn("Error while sending BYE to " + target, e);
				}

			}

			public void receiveAnswer(EntityEvent e) {
				Entity source = (Entity) e.getSource();
				Request req = e.getRequest();
				Response res = null;
				if (req == null) {
					return;
				}
				try {
					res = messageFactory.createResponse(Response.OK, req);

					if (e.getSessionDescription() != null) {
						ContentTypeHeader type = headerFactory
								.createContentTypeHeader("application", "sdp");
						res.setContent(e.getSessionDescription().toString(),
								type);
					}

					// ContactHeader
					Address contact_addr = addressFactory.createAddress(source
							.getURI());
					contact_addr.setDisplayName(source.getName());
					ContactHeader contact = headerFactory
							.createContactHeader(contact_addr);
					res.setHeader(contact);

					Entity target = (Entity) e.getTarget();
					String uri = target.getURI().toString();
					Dialog dialog = dialogTable.get(uri);
					ServerTransaction st = (ServerTransaction) dialog
							.getApplicationData();
					st.sendResponse(res);

					logger.info("Sending Response 200(OK) to " + uri);

				} catch (Exception e1) {
					logger.warn("Error while creating Response", e1);
					return;
				}
			}

			public void addedNewEntity(EntityEvent e) {
				// REGISTER
				switch (e.getEventType()) {
				case REGISTER:
					// SUBSCRIBE送信
					Entity target = (Entity) e.getSource();
					try {
						instance.sendRequest(target, Request.SUBSCRIBE);
					} catch (SipException e1) {
						logger.warn("Error while sending SUBSCRIBE to "
								+ target.getURI(), e1);
					}
					break;
				case SUBSCRIBE:
					// NOTIFY送信
					Entity[] entities = (Entity[]) e.getSource();
					String target_uri = entities[0].getURI().toString();
					Dialog dialog = dialogTable.get(target_uri);
					try {
						instance.startNotify(target_uri, dialog);
					} catch (ParseException e2) {
						logger.warn("Error while sending NOTIFY to "
								+ target_uri, e2);
					}
					break;
				case NOTIFY:
					// 親がいる場合は伝播
					if (instance.task != null) {
						instance.task.refresh();
						try {
							instance.task.sendNotify();
						} catch (Exception e1) {
							logger.warn(
									"Error while sending NOTIFY message to "
											+ con.getParent(), e1);
						}
					}
					entities = (Entity[]) e.getSource();
					target_uri = entities[0].getURI().toString();
					Set<String> set = dialogTable.keySet();
					// 本当は差分だけが良い
					String pidf = instance.pidfFactory.createPIDF().toString();
					for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
						String uri = iter.next();
						if (uri.equals(target_uri)) {
							continue;
						}
						dialog = dialogTable.get(uri);
						try {
							Request req = dialog.createRequest(Request.MESSAGE);
							ClientTransaction ct = provider.getNewClientTransaction(req);
							req.setContent(pidf, headerFactory.createContentTypeHeader(
									PIDFData.CONTENT_TYPE, PIDFData.CONTENT_SUBTYPE));
							dialog.sendRequest(ct);
							logger.info("Forwarding PIDF to :" + uri);
						} catch (Exception e1) {
							logger.error(
									"Error while sending MESSAGE message to "
											+ uri, e1);
						}
						
					}
					break;
				case ADD:
					if (e.getSource() instanceof Entity[]) {
						entities = (Entity[]) e.getSource();
						target_uri = entities[0].getURI().toString();
						set = dialogTable.keySet();
						pidf = instance.pidfFactory.createPIDF().toString();
						
						for (Iterator<String> iter = set.iterator(); iter.hasNext();) {
							String uri = iter.next();
							if (uri.equals(target_uri)) {
								continue;
							}
							dialog = dialogTable.get(uri);
							try {
								Request req = dialog.createRequest(Request.MESSAGE);
								ClientTransaction ct = provider.getNewClientTransaction(req);
								req.setContent(pidf, headerFactory.createContentTypeHeader(
										PIDFData.CONTENT_TYPE, PIDFData.CONTENT_SUBTYPE));
								dialog.sendRequest(ct);
								logger.info("Forwarding PIDF to :" + uri);
							} catch (Exception e1) {
								logger.error(
										"Error while sending MESSAGE message to "
												+ uri, e1);
							}
							
						}
					}
					break;
				default:
					logger.warn("Invalid Operation");
				}
			}
		});
		initialized = true;
	}

	/**
	 * It retrieve an Instance of SipCore.
	 * @return
	 */
	public static SipCore getInstance() {
		return instance;
	}

	/**
	 * 
	 * @param container
	 */
	public void setEntityContainer(EntityContainer container) {
		con = container;
		uri = (SipURI)con.getURI();
		pidfFactory = new PIDFFactoryImpl(con);
	}

	/**
	 * Send a SIP response by stateless.
	 * 
	 * @param num
	 * @param req
	 * @throws ParseException
	 * @throws InvalidArgumentException
	 * @throws SipException
	 */
	public void sendResponse(int num, Request req) throws ParseException,
			InvalidArgumentException, SipException {
		Response res = messageFactory.createResponse(num, req);
		ToHeader to = (ToHeader) res.getHeader(ToHeader.NAME);
		logger.info("Sending Response (" + num + ") to " + to.getAddress());
		provider.sendResponse(res);
	}

	/**
	 * Send a SIP response. It holds a Dialog.
	 * 
	 * @param num
	 * @param evt
	 * @param sender_uri
	 * @throws ParseException
	 * @throws SipException
	 * @throws InvalidArgumentException
	 */
	public void sendResponse(int num, RequestEvent evt, String sender_uri)
			throws ParseException, SipException, InvalidArgumentException {
		if (!initialized) {
			return;
		}
		Request req = evt.getRequest();
		Response res = messageFactory.createResponse(num, req);
		// Expires header is mandatory in 2xx response of SUBSCRIBE
		if (req.getMethod().equals(Request.SUBSCRIBE)) {
			prepareResponse(res);
			ExpiresHeader expiresHeader = req.getExpires();
			int expires = expiresHeader.getExpires() - 1;
			res.setHeader(headerFactory.createExpiresHeader(expires));
		}

		ServerTransaction st = evt.getServerTransaction();
		if (st == null) {
			st = provider.getNewServerTransaction(req);
		}
		logger.info("Sending " + req.getMethod() + " Response to "
				+ sender_uri);
		st.sendResponse(res);

		// Dialogの保持
		if (req.getMethod().equals(Request.SUBSCRIBE)
				|| req.getMethod().equals(Request.NOTIFY)) {
			Dialog dialog = st.getDialog();
			dialogTable.put(sender_uri, dialog);
		} else if (num == Response.TRYING) {
			Dialog dialog = st.getDialog();
			dialogTable.put(sender_uri, dialog);
			dialog.setApplicationData(st);
		}
	}

	/**
	 * 
	 * @param res
	 * @throws ParseException
	 * @throws InvalidArgumentException
	 */
	private void prepareResponse(Response res) throws ParseException,
			InvalidArgumentException {
		ToHeader to = (ToHeader) res.getHeader(ToHeader.NAME);
		// TODO
		Random rand = new Random();
		to.setTag(rand.nextInt(999999) + "");
		// ContactHeader
		Address addr = addressFactory.createAddress(uri);
		ContactHeader contact = headerFactory.createContactHeader(addr);
		res.setHeader(contact);
	}

	/**
	 * Send a SIP Message by a specified method. It sends by stateless.
	 * @param target
	 * @param method
	 * @throws SipException
	 */
	void sendRequest(Entity target, String method) throws SipException {
		Request req = createRequest(target, con, method);
		if (method.equals(Request.REGISTER)) {
			try {
				// REGISTERに必要なヘッダ： Expires, Contact
				ExpiresHeader expires = headerFactory
						.createExpiresHeader(DEFAULT_EXPIRES);
				req.setExpires(expires);
				Address contact_addr = addressFactory.createAddress(con
						.getURI());
				contact_addr.setDisplayName(con.getName());
				ContactHeader contact = headerFactory
						.createContactHeader(contact_addr);
				req.setHeader(contact);
			} catch (Exception e) {
				throw new SipException(e.getMessage());
			}
		} else if (method.equals(Request.SUBSCRIBE)) {
			// PIDF
			PIDFFactory pidf_fac = new PIDFFactoryImpl(con);
			PIDFData data = pidf_fac.createPIDF();
			try {
				req.setContent(data.toString(), headerFactory
						.createContentTypeHeader(PIDFData.CONTENT_TYPE,
								PIDFData.CONTENT_SUBTYPE));
				// Expires
				ExpiresHeader expires = headerFactory
						.createExpiresHeader(DEFAULT_EXPIRES);
				req.setExpires(expires);
				// EventHeader
				EventHeader event = headerFactory
						.createEventHeader(event_package);
				req.setHeader(event);
				Address contact_addr = addressFactory.createAddress(con
						.getURI());
				contact_addr.setDisplayName(con.getName());
				ContactHeader contact = headerFactory
						.createContactHeader(contact_addr);
				req.setHeader(contact);
			} catch (Exception e) {
				throw new SipException(e.getMessage());
			}
		}
		ClientTransaction ct = provider.getNewClientTransaction(req);
		ct.sendRequest();
		logger.info("Sending " + method + " to " + target.getURI());
		Dialog dialog = ct.getDialog();
		if (dialog != null)
			dialogTable.put(target.getURI().toString(), dialog);
	}

	/**
	 * 
	 * @param message
	 * @param target
	 * @param source
	 * @param method
	 * @throws SipException
	 * @throws ParseException
	 */
	void sendRequest(String message, Entity target, Entity source,
			String method) throws SipException, ParseException {

		String name = target.getURI().toString();

		if (method.equals(Request.INVITE)) {
			Request req = createRequest(target, source, method);

			Address contact_addr = addressFactory
					.createAddress(source.getURI());
			ContactHeader contact = headerFactory
					.createContactHeader(contact_addr);
			req.setHeader(contact);
			// SDP body
			req.setContent(message, headerFactory.createContentTypeHeader(
					"application", "sdp"));
			ClientTransaction ct = provider.getNewClientTransaction(req);
			ct.sendRequest();
			dialogTable.put(name, ct.getDialog());
		} else if (method.equals(Request.MESSAGE)) {
			Request req;
			/*
			if (target == con.getParent()) {
				Dialog dialog = dialogTable.get(name);
				req = dialog.createRequest(Request.MESSAGE);
				ClientTransaction ct = provider.getNewClientTransaction(req);
				req.setContent(message, headerFactory.createContentTypeHeader(
						PIDFData.CONTENT_TYPE, PIDFData.CONTENT_SUBTYPE));
				dialog.sendRequest(ct);
				logger.info(" :" + target.getURI());
				return;
			}*/
			req = createRequest(target, source, method);
			FromHeader from = (FromHeader) req.getHeader(FromHeader.NAME);
			Address addr = addressFactory.createAddress(source.getURI());
			addr.setDisplayName(source.getFullyQualifiedName());
			from.setAddress(addr);
			req.setContent(message, headerFactory.createContentTypeHeader(
					"text", "plain"));
			provider.sendRequest(req);
		} else {
			// BYE, NOTIFYの場合
			Dialog dialog = dialogTable.get(name);
			Request req = dialog.createRequest(method);
			ClientTransaction ct = provider.getNewClientTransaction(req);
			dialog.sendRequest(ct);
		}

	}

	Random rand = new Random();

	/**
	 * 
	 * @param target
	 * @param source
	 * @param method
	 * @return
	 * @throws SipException
	 */
	private Request createRequest(Entity target, Entity source, String method)
			throws SipException {
		Address toAddress = addressFactory.createAddress(target.getURI());

		Request req;
		String transport = "udp", branch = null;
		String tag = "" + rand.nextInt(100000000);
		try {
			ToHeader to = headerFactory.createToHeader(toAddress, null);
			Address fromAddress = addressFactory.createAddress(source.getURI());
			fromAddress.setDisplayName(source.getName());
			FromHeader from = headerFactory.createFromHeader(fromAddress, tag);

			// ToHeader to = headerFactory.createToHeader(toAddress, null);
			CSeqHeader cSeq = headerFactory.createCSeqHeader(1L, method);
			CallIdHeader callId = provider.getNewCallId();
			MaxForwardsHeader maxForwards = headerFactory
					.createMaxForwardsHeader(70);
			ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>();
			String ipAddr = provider.getListeningPoint(transport)
					.getIPAddress();
			int port = provider.getListeningPoint(transport).getPort();
			ViaHeader viaHeader = headerFactory.createViaHeader(ipAddr, port,
					transport, branch);
			viaHeaders.add(viaHeader);

			req = messageFactory.createRequest(to.getAddress().getURI(),
					method, callId, cSeq, from, to, viaHeaders, maxForwards);

		} catch (Exception e) {
			throw new SipException(e.getMessage());
		}

		return req;
	}

	NotifyTask task;

	/**
	 * 
	 * @param sender_name
	 * @param dialog
	 * @throws ParseException
	 */
	void startNotify(String sender_name, Dialog dialog)
			throws ParseException {

		logger.info("Start NotifyTask to:" + sender_name);
		task = new NotifyTask(dialog);
		task.start();

	}

	/**
	 * Expiresの更新
	 *
	 */
	public void refresh() {
		task.refresh();
	}

	private class NotifyTask extends TimerTask {

		private EntityContainer target = null;

		private final static String eventPackage = "presence";

		private PIDFData temp = null;

		private Dialog dialog;

		private boolean alive = false;

		private Timer timer;

		Address fromAddress;

		public NotifyTask(Dialog dialog) throws ParseException {
			this.dialog = dialog;
			this.alive = true;
			fromAddress = addressFactory.createAddress(con.getURI());
			fromAddress.setDisplayName(con.getName());
		}

		public void start() {
			timer = new Timer(true);
			timer.schedule(this, 1000, DEFAULT_EXPIRES * 1000);
		}

		@Override
		public void run() {
			try {
				sendNotify();
			} catch (Exception e) {
				logger.warn("Error occure, remove Entity :" + target, e);
				con.removeChild(target);
			}
		}

		public void sendNotify() throws SipException, ParseException {

			Request notify = dialog.createRequest(Request.NOTIFY);

			// expires
			SubscriptionStateHeader state = headerFactory
					.createSubscriptionStateHeader(SubscriptionStateHeader.ACTIVE);
			EventHeader event = headerFactory.createEventHeader(eventPackage);

			// Fromの書き換え
			// FromHeader from = (FromHeader) notify.getHeader(FromHeader.NAME);
			// from.setAddress(fromAddress);
			PIDFData pidf = pidfFactory.createPIDF();
			if (temp == null || !temp.equals(pidf)) {
				ContentTypeHeader contentType = headerFactory
						.createContentTypeHeader(PIDFData.CONTENT_TYPE,
								PIDFData.CONTENT_SUBTYPE);

				notify.addHeader(state);
				notify.addHeader(event);
				notify.setContent(pidf.toString(), contentType);
			} else {
				// nop
			}

			ClientTransaction ct = provider.getNewClientTransaction(notify);

			if (alive) {
				logger.info("Sending NOTIFY to " + dialog.getRemoteTarget());
				dialog.sendRequest(ct);
				alive = false;
			} else {
				logger.info("Expires out, remove Entity" + target);
				con.removeChild(target);
			}
		}

		public void refresh() {
			this.alive = true;
		}
	}

	/**
	 * SIP URIの作成
	 * @param temp
	 * @return
	 */
	public URI createURI(String temp) {
		URI uri;
		try {
			if (addressFactory != null)
				uri = addressFactory.createURI(temp);
			else {
				SipUri s_uri = new SipUri();
				java.util.StringTokenizer stToken = new java.util.StringTokenizer(
						temp, "@:");
				String scheme = stToken.nextToken();
				if (!scheme.equals("sip") && !scheme.equals("pres")) {
					throw new IllegalArgumentException("Bad uri scheme :"
							+ scheme);
				}
				String user = stToken.nextToken();
				String host = stToken.nextToken();
				int port = Integer.parseInt(stToken.nextToken());
				s_uri.setUser(user);
				s_uri.setHost(host);
				s_uri.setPort(port);
				uri = s_uri;
			}
		} catch (ParseException e) {
			return null;
		}
		return uri;
	}

	@Override
	public void init(EntityContainer source, Properties prop) throws Exception {
		// TODO Auto-generated method stub
		
	}

}
