package net.etalia.client.json;

import java.util.HashMap;
import java.util.Map;

import net.etalia.client.domain.Article;
import net.etalia.client.domain.Entity;
import net.etalia.client.domain.Journalia;
import net.etalia.client.domain.JournaliaStampAggregation;
import net.etalia.client.domain.JournaliaSuggestedAggregation;
import net.etalia.client.domain.JournaliaSystemAggregation;
import net.etalia.client.domain.Media;
import net.etalia.client.domain.PageQuery;
import net.etalia.client.domain.PublicationOwner;
import net.etalia.client.domain.PublicationStamps;
import net.etalia.client.domain.PublicationStandard;
import net.etalia.client.domain.SearchCriteria;
import net.etalia.client.domain.User;
import net.etalia.client.domain.UserProfile;
import net.etalia.jalia.EntityFactory;
import net.etalia.jalia.EntityNameProvider;
import net.etalia.jalia.JsonClassData;
import net.etalia.jalia.JsonClassDataFactory;
import net.etalia.jalia.JsonClassDataFactoryImpl;
import net.etalia.jalia.JsonContext;

/**
 * Implements Etalia names, entity factory and class data factory.
 * 
 * 
 * @author Simone Gianni <simoneg@apache.org>
 */
public class JaliaDomainFactory implements EntityNameProvider, EntityFactory, JsonClassDataFactory {

	private JsonClassDataFactoryImpl classDataFactory = new JsonClassDataFactoryImpl();
	private Map<Class<?>, String> nameMappingsByClass = new HashMap<Class<?>, String>();
	private Map<String, Class<?>> nameMappingsByName = new HashMap<String, Class<?>>();
	
	{
		map(Article.class, "Article");
		map(Journalia.class, "Journalia");
		map(JournaliaSystemAggregation.class, "SystemAggregation");
		map(JournaliaStampAggregation.class, "StampAggregation");
		map(JournaliaSuggestedAggregation.class, "SuggestedAggregation");
		map(Media.class, "Media");
		map(PageQuery.class, "PageQuery");
		map(PublicationOwner.class, "PublicationOwner");
		map(PublicationStamps.class, "PublicationStamps");
		map(PublicationStandard.class, "PublicationStandard");
		map(SearchCriteria.class, "SearchCriteria");
		map(User.class, "User");
		map(UserProfile.class, "UserProfile");
	}
	
	private void map(Class<?> clazz, String name) {
		nameMappingsByClass.put(clazz, name);
		nameMappingsByName.put(name, clazz);
	}

	/**
	 * Uses default domain mappings for Etalia
	 */
	public String getEntityName(Class<?> clazz) {
		String ret = nameMappingsByClass.get(clazz);
		if (ret == null) {
			// TODO parse an annotation?
		}
		return ret;
	}

	/**
	 * Uses default domain mappings for Etalia
	 */
	public Class<?> getEntityClass(String name) {
		return nameMappingsByName.get(name);
	}

	
	public JsonClassData getClassData(Class<?> clazz, JsonContext context) {
		JsonClassData ret = classDataFactory.getClassData(clazz, context);
		if (!ret.isNew()) return ret;
		ret.ignoreGetter("id");
		ret.ignoreSetter("id");
		classDataFactory.cache(clazz, ret);
		return ret;
	}
	
	/**
	 * Uses {@link Persistent#getId()} to fetch the id.
	 */
	public String getId(Object entity, JsonContext context) {
		if (entity instanceof Entity) {
			return ((Entity) entity).getId();
		} else if (entity instanceof Media) {
			return ((Media) entity).getId();
		}
		return null;
	}

	public Object buildEntity(Class<?> clazz, String id, JsonContext context) {
		try {
			return clazz.newInstance();
		} catch (Exception e) {
			throw new IllegalStateException(e);
		}
	}

	public Object prepare(Object obj, boolean serializing, JsonContext context) {
		return obj;
	}

	public Object finish(Object obj, boolean serializing, JsonContext context) {
		return obj;
	}

}

@@ -460,63 +460,250 @@
 Page
-Query;%0Aimport net.etalia.client.domain.PublicationOwner
+Example;%0Aimport net.etalia.client.domain.PageLink;%0Aimport net.etalia.client.domain.PageQuery;%0Aimport net.etalia.client.domain.PaginationList;%0Aimport net.etalia.client.domain.PublicationOwner;%0Aimport net.etalia.client.domain.PublicationSection
 ;%0Aim
@@ -1986,82 +1986,260 @@
 Page
-Query.class, %22PageQuery%22);%0A%09%09map(PublicationOwner.class, %22PublicationOwner
+Example.class, %22PageExample%22);%0A%09%09map(PageLink.class, %22PageLink%22);%0A%09%09map(PageQuery.class, %22PageQuery%22);%0A%09%09map(PaginationList.class, %22PaginationList%22);%0A%09%09map(PublicationOwner.class, %22PublicationOwner%22);%0A%09%09map(PublicationSection.class, %22PublicationSection
 %22);%0A

Add missing json mapping