001 /* 002 * Copyright 2006 Stephen J. McConnell. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.metro.builder; 020 021 import java.io.IOException; 022 import java.io.OutputStream; 023 import java.io.OutputStreamWriter; 024 import java.io.Writer; 025 026 import javax.xml.XMLConstants; 027 028 import net.dpml.metro.info.Type; 029 import net.dpml.metro.info.InfoDescriptor; 030 import net.dpml.metro.info.ContextDescriptor; 031 import net.dpml.metro.info.CategoryDescriptor; 032 import net.dpml.metro.info.ServiceDescriptor; 033 import net.dpml.metro.info.EntryDescriptor; 034 import net.dpml.metro.info.Descriptor; 035 036 import net.dpml.state.State; 037 import net.dpml.state.StateEncoder; 038 039 /** 040 * Type builder. 041 * 042 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 043 * @version 1.2.0 044 */ 045 public class ComponentTypeEncoder 046 { 047 private static final String XML_HEADER = 048 "<?xml version=\"1.0\"?>"; 049 050 private static final String PART_SCHEMA_URN = "link:xsd:dpml/lang/dpml-part#1.0"; 051 private static final String TYPE_SCHEMA_URN = "link:xsd:dpml/lang/dpml-type#1.0"; 052 private static final StateEncoder STATE_GRAPH_ENCODER = new StateEncoder(); 053 054 private static final String HEADER = 055 "<type xmlns=\"" 056 + TYPE_SCHEMA_URN 057 + "\"" 058 + "\n xmlns:xsi=\"" 059 + XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI 060 + "\"\n xmlns:part=\"" 061 + PART_SCHEMA_URN 062 + "\"\n xmlns:type=\"" 063 + TYPE_SCHEMA_URN 064 + "\">"; 065 066 private static final String FOOTER = "</type>"; 067 068 /** 069 * Write the supplied type to an output stream. 070 * @param type the type descriptor 071 * @param output the output stream 072 * @exception IOException if an IO error occurs 073 */ 074 public void export( Type type, OutputStream output ) throws IOException 075 { 076 final Writer writer = new OutputStreamWriter( output ); 077 writer.write( XML_HEADER ); 078 writer.write( "\n\n" ); 079 writer.write( HEADER ); 080 writer.write( "\n" ); 081 writeBody( writer, type, " " ); 082 writer.write( "\n" ); 083 writer.write( FOOTER ); 084 writer.write( "\n" ); 085 writer.flush(); 086 output.close(); 087 } 088 089 private void writeBody( Writer writer, Type type, String pad ) throws IOException 090 { 091 writeTypeInfo( writer, type.getInfo(), pad ); 092 writeTypeServices( writer, type.getServiceDescriptors(), pad ); 093 writeTypeContext( writer, type.getContextDescriptor(), pad ); 094 writeTypeCategories( writer, type.getCategoryDescriptors(), pad ); 095 writeTypeState( writer, type.getStateGraph(), pad ); 096 } 097 098 private void writeTypeInfo( Writer writer, InfoDescriptor info, String pad ) throws IOException 099 { 100 writer.write( "\n" + pad + "<info" ); 101 writer.write( " name=\"" + info.getName() ); 102 writer.write( "\"\n" + pad + " class=\"" + info.getClassname() ); 103 writer.write( "\"\n" + pad + " version=\"" + info.getVersion() ); 104 writer.write( "\"\n" + pad + " lifestyle=\"" + info.getLifestylePolicy().getName().toLowerCase() ); 105 writer.write( "\"\n" + pad + " collection=\"" + info.getCollectionPolicy().getName().toLowerCase() ); 106 writer.write( "\"\n" + pad + " threadsafe=\"" + info.getThreadSafePolicy().getName().toLowerCase() ); 107 writer.write( "\"" ); 108 if( info.getAttributeNames().length > 0 ) 109 { 110 writer.write( ">" ); 111 writeAttributes( writer, info, pad + " " ); 112 writer.write( "\n" + pad + "</info>" ); 113 } 114 else 115 { 116 writer.write( "/>" ); 117 } 118 } 119 120 private void writeTypeServices( Writer writer, ServiceDescriptor[] services, String pad ) throws IOException 121 { 122 if( services.length == 0 ) 123 { 124 return; 125 } 126 else 127 { 128 writer.write( "\n" + pad + "<services>" ); 129 for( int i=0; i<services.length; i++ ) 130 { 131 ServiceDescriptor service = services[i]; 132 writer.write( "\n" + pad + " <service" ); 133 writer.write( " class=\"" + service.getClassname() ); 134 writer.write( "\" version=\"" + service.getVersion() ); 135 writer.write( "\"/>" ); 136 } 137 writer.write( "\n" + pad + "</services>" ); 138 } 139 } 140 141 private void writeTypeContext( Writer writer, ContextDescriptor context, String pad ) throws IOException 142 { 143 EntryDescriptor[] entries = context.getEntryDescriptors(); 144 if( entries.length > 0 ) 145 { 146 writer.write( "\n" + pad + "<context>" ); 147 for( int i=0; i<entries.length; i++ ) 148 { 149 EntryDescriptor entry = entries[i]; 150 writer.write( "\n" + pad + " <entry" ); 151 writer.write( " key=\"" + entry.getKey() ); 152 writer.write( "\" class=\"" + entry.getClassname() ); 153 if( entry.isOptional() ) 154 { 155 writer.write( "\" optional=\"true\"" ); 156 } 157 else 158 { 159 writer.write( "\" optional=\"false\"" ); 160 } 161 if( entry.isVolatile() ) 162 { 163 writer.write( "\" volatile=\"true\"" ); 164 } 165 writer.write( "/>" ); 166 } 167 writer.write( "\n" + pad + "</context>" ); 168 } 169 else 170 { 171 return; 172 } 173 } 174 175 private void writeTypeCategories( 176 Writer writer, CategoryDescriptor[] categories, String pad ) throws IOException 177 { 178 if( categories.length > 0 ) 179 { 180 writer.write( "\n" + pad + "<categories>" ); 181 for( int i=0; i<categories.length; i++ ) 182 { 183 CategoryDescriptor category = categories[i]; 184 writer.write( "\n" + pad + " <category" ); 185 writer.write( " name=\"" + category.getName() ); 186 writer.write( 187 "\" priority=\"" 188 + category.getDefaultPriority().getName().toLowerCase() ); 189 writer.write( "\"" ); 190 191 if( category.getAttributeNames().length > 0 ) 192 { 193 writer.write( ">" ); 194 writeAttributes( writer, category, pad + " " ); 195 writer.write( "\n" + pad + " </category>" ); 196 } 197 else 198 { 199 writer.write( "/>" ); 200 } 201 } 202 writer.write( "\n" + pad + "</categories>" ); 203 } 204 else 205 { 206 return; 207 } 208 } 209 210 private void writeTypeState( Writer writer, State state, String pad ) throws IOException 211 { 212 STATE_GRAPH_ENCODER.writeState( writer, state, pad ); 213 writer.write( "\n" ); 214 } 215 216 private void writeAttributes( Writer writer, Descriptor descriptor, String pad ) throws IOException 217 { 218 String[] names = descriptor.getAttributeNames(); 219 for( int i=0; i<names.length; i++ ) 220 { 221 String name = names[i]; 222 String value = descriptor.getAttribute( name, "" ); 223 writer.write( "\n" + pad + "<property" ); 224 writer.write( " name=\"" + name ); 225 writer.write( "\" value=\"" + value ); 226 writer.write( "\"/>" ); 227 } 228 } 229 } 230