# EntitiesResource.java

    /*
     * Copyright (c) 2008, Niclas Hedhman. All Rights Reserved.
     *
     * 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.qi4j.library.rest.admin;

    import java.io.IOException;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.io.Writer;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    import org.qi4j.api.entity.EntityComposite;
    import org.qi4j.api.entity.EntityReference;
    import org.qi4j.api.injection.scope.Service;
    import org.qi4j.api.value.ValueSerialization;
    import org.qi4j.spi.query.EntityFinder;
    import org.qi4j.spi.query.EntityFinderException;
    import org.restlet.data.CharacterSet;
    import org.restlet.data.MediaType;
    import org.restlet.data.Status;
    import org.restlet.ext.atom.Entry;
    import org.restlet.ext.atom.Feed;
    import org.restlet.ext.atom.Link;
    import org.restlet.ext.atom.Text;
    import org.restlet.representation.EmptyRepresentation;
    import org.restlet.representation.OutputRepresentation;
    import org.restlet.representation.Representation;
    import org.restlet.representation.Variant;
    import org.restlet.representation.WriterRepresentation;
    import org.restlet.resource.ResourceException;
    import org.restlet.resource.ServerResource;

    /**
     * Listing of all Entities.
     * <p>
     * Mapped to /entity
     * </p>
     */
    public class EntitiesResource
        extends ServerResource
    {

        @Service
        private EntityFinder entityFinder;
        @Service
        private ValueSerialization valueSerialization;

        public EntitiesResource()
        {
            super();

            // Define the supported variants.
            getVariants().addAll(
                Arrays.asList( new Variant( MediaType.TEXT_HTML ), new Variant( MediaType.APPLICATION_RDF_XML ),
                               new Variant( MediaType.APPLICATION_JSON ), new Variant( MediaType.APPLICATION_ATOM ) ) );

            setNegotiated( true );
        }

        @Override
        protected Representation get( Variant variant )
            throws ResourceException
        {
            System.out.println( "VARIANT: " + variant.getMediaType() );
            // Generate the right representation according to its media type.
            if( MediaType.APPLICATION_JSON.equals( variant.getMediaType() ) )
            {
                return representJson();
            }
            else if( MediaType.APPLICATION_RDF_XML.equals( variant.getMediaType() ) )
            {
                return representRdf();
            }
            else if( MediaType.TEXT_HTML.equals( variant.getMediaType() ) )
            {
                return representHtml();
            }
            else if( MediaType.APPLICATION_ATOM.equals( variant.getMediaType() ) )
            {
                return representAtom();
            }

            throw new ResourceException( Status.CLIENT_ERROR_NOT_FOUND );
        }

        private Representation representJson()
            throws ResourceException
        {
            try
            {
                final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
                return new OutputRepresentation( MediaType.APPLICATION_JSON )
                {
                    @Override
                    public void write( OutputStream outputStream )
                        throws IOException
                    {
                        valueSerialization.serialize( query, outputStream );
                    }
                };
            }
            catch( Exception e )
            {
                throw new ResourceException( e );
            }
        }

        private Representation representRdf()
            throws ResourceException
        {
            try
            {
                final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );

                WriterRepresentation representation = new WriterRepresentation( MediaType.APPLICATION_RDF_XML )
                {
                    @Override
                    public void write( Writer writer )
                        throws IOException
                    {
                        PrintWriter out = new PrintWriter( writer );
                        out.println( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<rdf:RDF\n"
                                     + "\txmlns=\"urn:qi4j:\"\n" + "\txmlns:qi4j=\"http://www.qi4j.org/rdf/model/1.0/\"\n"
                                     + "\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
                                     + "\txmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\">" );
                        for( EntityReference qualifiedIdentity : query )
                        {
                            out.println( "<qi4j:entity rdf:about=\"" + getRequest().getResourceRef().getPath() + "/"
                                         + qualifiedIdentity.identity() + ".rdf\"/>" );
                        }

                        out.println( "</rdf:RDF>" );
                    }
                };
                representation.setCharacterSet( CharacterSet.UTF_8 );

                return representation;
            }
            catch( EntityFinderException e )
            {
                throw new ResourceException( Status.SERVER_ERROR_INTERNAL, e );
            }
        }

        private Representation representHtml()
            throws ResourceException
        {
            try
            {
                final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
                Representation representation = new WriterRepresentation( MediaType.TEXT_HTML )
                {
                    @Override
                    public void write( Writer buf )
                        throws IOException
                    {
                        PrintWriter out = new PrintWriter( buf );
                        out.println( "<html><head><title>All entities</title></head><body><h1>All entities</h1><ul>" );

                        for( EntityReference entity : query )
                        {
                            out.println( "<li><a href=\""
                                         + getRequest().getResourceRef().clone().addSegment( entity.identity() + ".html" )
                                         + "\">" + entity.identity() + "</a></li>" );
                        }
                        out.println( "</ul></body></html>" );
                    }
                };
                representation.setCharacterSet( CharacterSet.UTF_8 );
                return representation;
            }
            catch( EntityFinderException e )
            {
                throw new ResourceException( e );
            }
        }

        private Representation representAtom()
            throws ResourceException
        {
            try
            {
                Feed feed = new Feed();
                feed.setTitle( new Text( MediaType.TEXT_PLAIN, "All entities" ) );
                List<Entry> entries = feed.getEntries();
                final Iterable<EntityReference> query = entityFinder.findEntities( EntityComposite.class, null, null, null, null, Collections.<String, Object>emptyMap() );
                for( EntityReference entityReference : query )
                {
                    Entry entry = new Entry();
                    entry.setTitle( new Text( MediaType.TEXT_PLAIN, entityReference.toString() ) );
                    Link link = new Link();
                    link.setHref( getRequest().getResourceRef().clone().addSegment( entityReference.identity() ) );
                    entry.getLinks().add( link );
                    entries.add( entry );
                }

                return feed;
            }
            catch( Exception e )
            {
                throw new ResourceException( e );
            }
        }

        @Override
        protected Representation post( Representation entity, Variant variant )
            throws ResourceException
        {
            try
            {
                /*
                 * InputStream in = entity.getStream(); ObjectInputStream oin = new ObjectInputStream( in ); String identity
                 * = oin.readUTF(); Usecase usecase = (Usecase) oin.readUnshared(); MetaInfo unitofwork = (MetaInfo)
                 * oin.readUnshared(); Iterable<UnitOfWorkEvent> events = (Iterable<UnitOfWorkEvent>) oin.readUnshared();
                 *
                 * // Store state try { entityStore.apply( identity, events, usecase, unitofwork ).commit(); } catch(
                 * ConcurrentEntityStateModificationException e ) { throw new ResourceException(
                 * Status.CLIENT_ERROR_CONFLICT ); }
                 */
            }
            catch( Exception e )
            {
                throw new ResourceException( e );
            }

            return new EmptyRepresentation();
        }
    }