001/* 002 * RegistryMatcher.java May 2011 003 * 004 * Copyright (C) 2011, Niall Gallagher <niallg@users.sf.net> 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 015 * implied. See the License for the specific language governing 016 * permissions and limitations under the License. 017 */ 018 019package org.simpleframework.xml.transform; 020 021import org.simpleframework.xml.util.Cache; 022import org.simpleframework.xml.util.ConcurrentCache; 023 024/** 025 * The <code>RegistryMatcher</code> provides a simple matcher backed 026 * by a registry. Registration can be done to match a type to a 027 * <code>Transform</code> class or instance. If a transform class is 028 * registered an instance of it is created when requested using the 029 * default no argument constructor of the type, it is then cached so 030 * it can be reused on future requests. 031 * 032 * @author Niall Gallagher 033 * 034 * @see org.simpleframework.xml.core.Persister 035 */ 036public class RegistryMatcher implements Matcher { 037 038 /** 039 * This is used to fetch transform instances by type. 040 */ 041 private final Cache<Transform> transforms; 042 043 /** 044 * This is used to determine the transform for a type. 045 */ 046 private final Cache<Class> types; 047 048 /** 049 * Constructor for the <code>RegistryMatcher</code>. This is used 050 * to create a matcher instance that can resolve a transform by 051 * type and can also instantiate new transforms if required. It 052 * is essentially a convenience implementation. 053 */ 054 public RegistryMatcher() { 055 this.transforms = new ConcurrentCache<Transform>(); 056 this.types = new ConcurrentCache<Class>(); 057 } 058 059 /** 060 * This is used to bind a <code>Transform</code> type. The first 061 * time a transform is requested for the specified type a new 062 * instance of this <code>Transform</code> will be instantiated. 063 * 064 * @param type this is the type to resolve the transform for 065 * @param transform this is the transform type to instantiate 066 */ 067 public void bind(Class type, Class transform) { 068 types.cache(type, transform); 069 } 070 071 /** 072 * This is used to bind a <code>Transform</code> instance to the 073 * specified type. Each time a transform is requested for this 074 * type the provided instance will be returned. 075 * 076 * @param type this is the type to resolve the transform for 077 * @param transform this transform instance to be used 078 */ 079 public void bind(Class type, Transform transform) { 080 transforms.cache(type, transform); 081 } 082 083 /** 084 * This is used to match a <code>Transform</code> using the type 085 * specified. If no transform can be acquired then this returns 086 * a null value indicating that no transform could be found. 087 * 088 * @param type this is the type to acquire the transform for 089 * 090 * @return returns a transform for processing the type given 091 */ 092 public Transform match(Class type) throws Exception { 093 Transform transform = transforms.fetch(type); 094 095 if(transform == null) { 096 return create(type); 097 } 098 return transform; 099 } 100 101 /** 102 * This is used to create a <code>Transform</code> using the type 103 * specified. If no transform can be acquired then this returns 104 * a null value indicating that no transform could be found. 105 * 106 * @param type this is the type to acquire the transform for 107 * 108 * @return returns a transform for processing the type given 109 */ 110 private Transform create(Class type) throws Exception { 111 Class factory = types.fetch(type); 112 113 if(factory != null) { 114 return create(type, factory); 115 } 116 return null; 117 } 118 119 /** 120 * This is used to create a <code>Transform</code> using the type 121 * specified. If the transform can not be instantiated then this 122 * will throw an exception. If it can then it is cached. 123 * 124 * @param type this is the type to acquire the transform for 125 * @param factory the class for instantiating the transform 126 * 127 * @return returns a transform for processing the type given 128 */ 129 private Transform create(Class type, Class factory) throws Exception { 130 Object value = factory.newInstance(); 131 Transform transform = (Transform)value; 132 133 if(transform != null) { 134 transforms.cache(type, transform); 135 } 136 return transform; 137 } 138}