001 /* 002 * Copyright 2004 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.info; 020 021 import java.io.Serializable; 022 import java.util.ArrayList; 023 import java.util.Arrays; 024 import java.util.List; 025 026 /** 027 * A descriptor describing the context that a component 028 * declares. The context descriptor contains information about 029 * context entries accessable via keys (typically mapped to 030 * get[Name] operations on a Context inner interface). 031 * 032 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 033 * @version 1.0.4 034 */ 035 public class ContextDescriptor implements Serializable 036 { 037 //--------------------------------------------------------- 038 // static 039 //--------------------------------------------------------- 040 041 /** 042 * Serial version identifier. 043 */ 044 static final long serialVersionUID = 1L; 045 046 //--------------------------------------------------------- 047 // immutable state 048 //--------------------------------------------------------- 049 050 private final EntryDescriptor[] m_entries; 051 052 //--------------------------------------------------------- 053 // constructors 054 //--------------------------------------------------------- 055 056 /** 057 * Creation of a new context descriptor. 058 * @param entries the set of context entries 059 */ 060 public ContextDescriptor( final EntryDescriptor[] entries ) 061 { 062 if( null == entries ) 063 { 064 m_entries = new EntryDescriptor[0]; 065 } 066 else 067 { 068 m_entries = entries; 069 } 070 } 071 072 //--------------------------------------------------------- 073 // implementation 074 //--------------------------------------------------------- 075 076 /** 077 * Return the entries contained in the context. 078 * 079 * @return the array of entries contained in the context. 080 */ 081 public EntryDescriptor[] getEntryDescriptors() 082 { 083 return m_entries; 084 } 085 086 /** 087 * Return the entry with specified key. 088 * 089 * @param key the context entry key 090 * @return the entry matching the key of null if no matching entry 091 * @exception NullPointerException if the key argument is null. 092 */ 093 public EntryDescriptor getEntryDescriptor( final String key ) 094 throws NullPointerException 095 { 096 if ( null == key ) 097 { 098 throw new NullPointerException( "key" ); 099 } 100 101 for ( int i = 0; i < m_entries.length; i++ ) 102 { 103 final EntryDescriptor entry = m_entries[i]; 104 if( entry.getKey().equals( key ) ) 105 { 106 return entry; 107 } 108 } 109 110 return null; 111 } 112 113 /** 114 * Returns a set of entry descriptors resulting from a merge of the descriptors 115 * contained in this descriptor with the supplied descriptors. 116 * 117 * @param entries the entries to merge 118 * @return the mergerged set of entries 119 * @exception IllegalArgumentException if a entry conflict occurs 120 */ 121 public EntryDescriptor[] merge( EntryDescriptor[] entries ) 122 throws IllegalArgumentException 123 { 124 for ( int i = 0; i < entries.length; i++ ) 125 { 126 EntryDescriptor entry = entries[i]; 127 final String key = entry.getKey(); 128 EntryDescriptor local = getEntryDescriptor( entry.getKey() ); 129 if ( local != null ) 130 { 131 if ( !entry.getClassname().equals( local.getClassname() ) ) 132 { 133 final String error = 134 "Conflicting entry type for key: " + key; 135 throw new IllegalArgumentException( error ); 136 } 137 } 138 } 139 140 return join( entries, getEntryDescriptors() ); 141 } 142 143 private EntryDescriptor[] join( EntryDescriptor[] primary, EntryDescriptor[] secondary ) 144 { 145 List list = new ArrayList( primary.length + secondary.length ); 146 list.addAll( Arrays.asList( primary ) ); 147 list.addAll( Arrays.asList( secondary ) ); 148 return (EntryDescriptor[]) list.toArray( new EntryDescriptor[0] ); 149 } 150 151 /** 152 * Test is the supplied object is equal to this object. 153 * @param other the other object 154 * @return true if the object are equivalent 155 */ 156 public boolean equals( Object other ) 157 { 158 if( null == other ) 159 { 160 return false; 161 } 162 boolean isEqual = true; 163 if( isEqual ) 164 { 165 isEqual = other instanceof ContextDescriptor; 166 } 167 if( isEqual ) 168 { 169 ContextDescriptor entity = (ContextDescriptor) other; 170 for( int i = 0; i < m_entries.length; i++ ) 171 { 172 isEqual = isEqual && m_entries[i].equals( entity.m_entries[i] ); 173 } 174 } 175 return isEqual; 176 } 177 178 /** 179 * Return the hashcode for the object. 180 * @return the hashcode value 181 */ 182 public int hashCode() 183 { 184 int hash = getClass().hashCode(); 185 for( int i = 0; i < m_entries.length; i++ ) 186 { 187 hash = hash + 65152197; 188 hash ^= m_entries[i].hashCode(); 189 } 190 return hash; 191 } 192 }