/** * Copyright (C) cedarsoft GmbH. * * Licensed under the GNU General Public License version 3 (the "License") * with Classpath Exception; you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.cedarsoft.org/gpl3ce * (GPL 3 with Classpath Exception) * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as * published by the Free Software Foundation. cedarsoft GmbH designates this * particular file as subject to the "Classpath" exception as provided * by cedarsoft GmbH in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 3 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 3 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact cedarsoft GmbH, 72810 Gomaringen, Germany, * or visit www.cedarsoft.com if you need additional information or * have any questions. */ package com.cedarsoft.rest.server; import com.cedarsoft.rest.model.JaxbObject; import com.cedarsoft.rest.model.JaxbStub; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.ws.rs.core.UriBuilder; import java.util.ArrayList; import java.util.List; /** * @param <T> the type * @param <J> the Jaxb type * @param <S> the Jaxb stub type */ public abstract class JaxbMapping<T, J extends JaxbObject, S extends JaxbStub<J>> { @Nonnull private final DelegateJaxbMappings delegateJaxbMappings = new DelegateJaxbMappings(); @Nonnull public DelegateJaxbMappings getDelegatesMapping() { return delegateJaxbMappings; } @Nonnull public S getJaxbObjectStub( @Nonnull T object, @Nonnull UriContext context ) { return createJaxbObjectStub( object, context ); } @Nonnull public J getJaxbObject( @Nonnull T object, @Nonnull UriContext context ) { return createJaxbObject( object, context ); } @Nullable protected <T, J extends JaxbObject> J get( @Nonnull Class<J> jaxbType, @Nullable T object, @Nonnull UriContext context ) { if ( object == null ) { return null; } // return getDelegatesMapping().getMapping( jaxbType ).getJaxbObject( object, context.getUriBuilder() ); return getDelegatesMapping().getMapping( jaxbType ).getJaxbObject( object, context ); } @Nullable protected <T, J extends JaxbObject> List<J> get( @Nonnull Class<J> jaxbType, @Nonnull Iterable<? extends T> objects, @Nonnull UriContext context ) { JaxbMapping<Object, J, ? extends JaxbStub<J>> mapping = getDelegatesMapping().getMapping( jaxbType ); List<J> converted = new ArrayList<J>(); for ( T object : objects ) { // converted.add( mapping.getJaxbObject( object, context.getUriBuilder() ) ); converted.add( mapping.getJaxbObject( object, context ) ); } return converted; } @Nullable protected <T, J extends JaxbObject, S extends JaxbStub<J>> S getStub( @Nonnull Class<S> jaxbStubType, @Nullable T object, @Nonnull UriContext context ) { if ( object == null ) { return null; } return getDelegatesMapping().getMappingForStub( jaxbStubType ).getJaxbObjectStub( object, context ); } @Nullable protected <T, J extends JaxbObject, S extends JaxbStub<J>> List<S> getStub( @Nonnull Class<S> jaxbSubType, @Nonnull Iterable<? extends T> objects, @Nonnull UriContext context ) { JaxbMapping<Object, ?, S> mapping = getDelegatesMapping().getMappingForStub( jaxbSubType ); List<S> converted = new ArrayList<S>(); for ( T object : objects ) { // converted.add( mapping.getJaxbObject( object, context.getUriBuilder() ) ); converted.add( mapping.getJaxbObjectStub( object, context ) ); } return converted; } @Nonnull public List<J> getJaxbObjects( @Nonnull Iterable<? extends T> objects, @Nonnull UriContext context ) { List<J> currentJaxbObjects = new ArrayList<J>(); for ( T object : objects ) { currentJaxbObjects.add( getJaxbObject( object, context ) ); } return currentJaxbObjects; } @Nonnull public List<S> getJaxbStubs( @Nonnull Iterable<? extends T> objects, @Nonnull UriContext context ) { List<S> currentJaxbObjects = new ArrayList<S>(); for ( T object : objects ) { currentJaxbObjects.add( getJaxbObjectStub( object, context ) ); } return currentJaxbObjects; } /** * Creates the local context. * The local context has an updated URI context. * * @param context the base context (not local!) * @param jaxbObject the jaxb object * @return the local context (with updated URI builder) - or null if no local context is available */ @Nullable protected UriContext createLocalContext( @Nonnull UriContext context, @Nonnull JaxbObject jaxbObject ) { UriBuilder localUri = getUri( jaxbObject, context ); if ( localUri == null ) { return null; } return context.create( localUri ); } /** * Creates the jaxb object * * @param object the object * @param context the context * @return the jaxb object */ @Nonnull protected final J createJaxbObject( @Nonnull T object, @Nonnull UriContext context ) { J jaxbObject = createJaxbObject( object ); UriContext localContext = createLocalContext( context, jaxbObject ); if ( localContext != null ) { setHref( jaxbObject, localContext ); } copyFieldsToJaxbObject( object, jaxbObject, localContext != null ? localContext : context ); return jaxbObject; } /** * Creates the JaxbObjectStub. * <p/> * A stub only contains the very basic informations off the object. It is used in collections and when referenced * from other objects. * <p/> * It has to contain a href to fetch the missing details later. * * @param object the object * @param context the context * @return the stub */ protected final S createJaxbObjectStub( @Nonnull T object, @Nonnull UriContext context ) { S jaxbStub = createJaxbStub( object ); UriContext localContext = createLocalContext( context, jaxbStub ); if ( localContext != null ) { setHref( jaxbStub, localContext ); } copyFieldsToStub( object, jaxbStub, localContext != null ? localContext : context ); return jaxbStub; } /** * Sets the URI to the jaxb object. * Override this method for custom behaviour (e.g. no href set) * * @param jaxbObject the jaxb object * @param context the context */ protected void setHref( @Nonnull JaxbObject jaxbObject, @Nonnull UriContext context ) { jaxbObject.setHref( context.getUri() ); } /** * Returns the local URI for the object * * @param object the object (may be used to fetch the ID) * @param context the context * @return the updated uri builder or null of no URI is available */ @Nullable protected abstract UriBuilder getUri( @Nonnull JaxbObject object, @Nonnull UriContext context ); /** * Creates the basic JaxbObject. * This method also *must* set the ID * * @param object the object * @return the jaxb object (with the ID set) */ @Nonnull protected abstract J createJaxbObject( @Nonnull T object ); /** * Creates the basic stub. * This method also *must* set the ID * * @param object the object * @return the stub object (with the ID set) */ @Nonnull protected abstract S createJaxbStub( @Nonnull T object ); /** * Copies the fields from the source to the target. * <p/> * Context: This is the local context that has been created using the URI returned by {@link #getUri(JaxbObject, UriContext)}. * If that method returns null, there is no local context available and the given parameter is the context of the parent. * * @param source the source object * @param target the target jaxb object * @param context the (local) context. */ protected abstract void copyFieldsToJaxbObject( @Nonnull T source, @Nonnull J target, @Nonnull UriContext context ); protected abstract void copyFieldsToStub( @Nonnull T source, @Nonnull S target, @Nonnull UriContext context ); }