001/* 002 * Copyright 2013 Chris Pheby 003 * Licensed under the Apache License, Version 2.0 (the "License"); 004 * you may not use this file except in compliance with the License. 005 * You may obtain a copy of the License at 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * Unless required by applicable law or agreed to in writing, software 008 * distributed under the License is distributed on an "AS IS" BASIS, 009 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010 * See the License for the specific language governing permissions and 011 * limitations under the License. 012 */ 013package org.jadira.reflection.cloning.orika; 014 015import java.util.HashSet; 016import java.util.Set; 017 018import ma.glasnost.orika.CustomConverter; 019import ma.glasnost.orika.MappingContext; 020import ma.glasnost.orika.metadata.Type; 021import ma.glasnost.orika.metadata.TypeFactory; 022 023import org.jadira.reflection.cloning.BasicCloner; 024import org.jadira.reflection.cloning.api.CloneStrategy; 025import org.jadira.reflection.cloning.api.Cloner; 026 027/** 028 * This class is intended for use with Orika 029 * <br> 030 * ClonerConverter allows configuration of a number of specific types which should be copied 031 * using BasicCloner. 032 * <br> 033 * This allows you to declare your own set of types which should be copied instead of mapped. 034 * You can use this type with Orika independently of the rest of the cloning framework to perform 035 * fast deep clones within Orika. 036 */ 037public class ClonerConverter extends CustomConverter<Object, Object> { 038 039 private Cloner cloner; 040 041 private Set<Type<?>> types = new HashSet<Type<?>>(); 042 043 /** 044 * Constructs a new ClonerConverter configured to handle the provided list of types by 045 * cloning. 046 * @param types one or more types that should be copied using the ClonerConverter 047 */ 048 public ClonerConverter(java.lang.reflect.Type... types) { 049 050 this(new BasicCloner(), types); 051 } 052 053 /** 054 * Constructs a new ClonerConverter configured to handle the provided list of types by 055 * cloning. 056 * @param cloneStrategy Strategy to be used 057 * @param types one or more types that should be copied using the ClonerConverter 058 */ 059 public ClonerConverter(CloneStrategy cloneStrategy, java.lang.reflect.Type... types) { 060 061 this.cloner = new BasicCloner(cloneStrategy); 062 063 if (types.length == 0) { 064 this.types = null; 065 } 066 for (java.lang.reflect.Type type : types) { 067 this.types.add(TypeFactory.valueOf(type)); 068 } 069 } 070 071 072 /** 073 * Constructs a new ClonerConverter configured to handle the provided list of types by 074 * cloning. 075 * @param cloner Cloner implementation to be used 076 * @param types one or more types that should be copied using the ClonerConverter 077 */ 078 public ClonerConverter(Cloner cloner, java.lang.reflect.Type... types) { 079 080 this.cloner = cloner; 081 082 if (types.length == 0) { 083 this.types = null; 084 } 085 for (java.lang.reflect.Type type : types) { 086 this.types.add(TypeFactory.valueOf(type)); 087 } 088 } 089 090 private boolean shouldCopy(Type<?> type) { 091 092 if (types == null) { 093 return true; 094 } 095 096 for (Type<?> registeredType : types) { 097 if (registeredType.isAssignableFrom(type)) { 098 return true; 099 } 100 } 101 return false; 102 } 103 104 @Override 105 public boolean canConvert(Type<?> sourceType, Type<?> destinationType) { 106 return shouldCopy(sourceType) && sourceType.equals(destinationType); 107 } 108 109 @Override 110 public Object convert(Object source, Type<? extends Object> destinationType, MappingContext context) { 111 112 if (source == null) { 113 return null; 114 } 115 return cloner.clone(source); 116 } 117}