001/* 002 * VisitorStrategy.java January 2010 003 * 004 * Copyright (C) 2010, 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.strategy; 020 021import java.util.Map; 022 023import org.simpleframework.xml.stream.InputNode; 024import org.simpleframework.xml.stream.NodeMap; 025import org.simpleframework.xml.stream.OutputNode; 026 027/** 028 * The <code>VisitorStrategy</code> object is a simplification of a 029 * strategy, which allows manipulation of the serialization process. 030 * Typically implementing a <code>Strategy</code> is impractical as 031 * it requires the implementation to determine the type a node 032 * represents. Instead it is often easier to visit each node that 033 * is being serialized or deserialized and manipulate it so that 034 * the resulting XML can be customized. 035 * <p> 036 * To perform customization in this way a <code>Visitor</code> can 037 * be implemented. This can be passed to this strategy which will 038 * ensure the visitor is given each XML element as it is either 039 * being serialized or deserialized. Such an inversion of control 040 * allows the nodes to be manipulated with little effort. By 041 * default this used <code>TreeStrategy</code> object as a default 042 * strategy to delegate to. However, any strategy can be used. 043 * 044 * @author Niall Gallagher 045 * 046 * @see org.simpleframework.xml.strategy.Visitor 047 */ 048public class VisitorStrategy implements Strategy { 049 050 /** 051 * This is the strategy that is delegated to by this strategy. 052 */ 053 private final Strategy strategy; 054 055 /** 056 * This is the visitor that is used to intercept serialization. 057 */ 058 private final Visitor visitor; 059 060 /** 061 * Constructor for the <code>VisitorStrategy</code> object. This 062 * strategy requires a visitor implementation that can be used 063 * to intercept the serialization and deserialization process. 064 * 065 * @param visitor this is the visitor used for interception 066 */ 067 public VisitorStrategy(Visitor visitor) { 068 this(visitor, new TreeStrategy()); 069 } 070 071 /** 072 * Constructor for the <code>VisitorStrategy</code> object. This 073 * strategy requires a visitor implementation that can be used 074 * to intercept the serialization and deserialization process. 075 * 076 * @param visitor this is the visitor used for interception 077 * @param strategy this is the strategy to be delegated to 078 */ 079 public VisitorStrategy(Visitor visitor, Strategy strategy) { 080 this.strategy = strategy; 081 this.visitor = visitor; 082 } 083 084 /** 085 * This method will read with an internal strategy after it has 086 * been intercepted by the visitor. Interception of the XML node 087 * before it is delegated to the internal strategy allows the 088 * visitor to change some attributes or details before the node 089 * is interpreted by the strategy. 090 * 091 * @param type this is the type of the root element expected 092 * @param node this is the node map used to resolve an override 093 * @param map this is used to maintain contextual information 094 * 095 * @return the value that should be used to describe the instance 096 */ 097 public Value read(Type type, NodeMap<InputNode> node, Map map) throws Exception { 098 if(visitor != null) { 099 visitor.read(type, node); 100 } 101 return strategy.read(type, node, map); 102 } 103 104 /** 105 * This method will write with an internal strategy before it has 106 * been intercepted by the visitor. Interception of the XML node 107 * before it is delegated to the internal strategy allows the 108 * visitor to change some attributes or details before the node 109 * is interpreted by the strategy. 110 * 111 * @param type this is the type of the root element expected 112 * @param node this is the node map used to resolve an override 113 * @param map this is used to maintain contextual information 114 * 115 * @return the value that should be used to describe the instance 116 */ 117 public boolean write(Type type, Object value, NodeMap<OutputNode> node, Map map) throws Exception { 118 boolean result = strategy.write(type, value, node, map); 119 120 if(visitor != null) { 121 visitor.write(type, node); 122 } 123 return result; 124 } 125}