Source code: javax/ide/editor/spi/EditorHook.java
1 package javax.ide.editor.spi;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.logging.Level;
9
10 import javax.ide.extension.ElementContext;
11 import javax.ide.extension.ElementName;
12 import javax.ide.extension.ElementStartContext;
13 import javax.ide.extension.ElementVisitor;
14 import javax.ide.extension.ExtensionHook;
15 import javax.ide.extension.I18NStringVisitor;
16 import javax.ide.extension.spi.ExtensionVisitor;
17 import javax.ide.util.MetaClass;
18
19 /**
20 * Editor information gathered from processing the <b>editor-hook</b>
21 * section of an extension manifest. The information recorded
22 * here describes a new editor.
23 */
24 public final class EditorHook extends ExtensionHook
25 {
26 public static final ElementName ELEMENT = new ElementName(
27 MANIFEST_XMLNS, "editor-hook" );
28
29 private static final ElementName EDITORS = new ElementName(
30 MANIFEST_XMLNS, "editors" );
31 private static final ElementName EDITOR = new ElementName(
32 MANIFEST_XMLNS, "editor" );
33 private static final ElementName NAME = new ElementName(
34 MANIFEST_XMLNS, "name" );
35
36
37 private static final ElementName MAPPINGS = new ElementName(
38 MANIFEST_XMLNS, "mappings" );
39 private static final ElementName MAPPING = new ElementName(
40 MANIFEST_XMLNS, "mapping" );
41 private static final ElementName OPEN_WITH = new ElementName(
42 MANIFEST_XMLNS, "open-with" );
43
44 private static final ElementName LISTENERS = new ElementName(
45 MANIFEST_XMLNS, "editor-listeners" );
46 private static final ElementName EDITOR_LISTENER = new ElementName(
47 MANIFEST_XMLNS, "editor-listener" );
48
49 private ElementVisitor _editorsVisitor = new EditorsVisitor();
50 private ElementVisitor _editorVisitor = new EditorVisitor();
51 private ElementVisitor _mappingsVisitor = new MappingsVisitor();
52 private ElementVisitor _mappingVisitor = new MappingVisitor();
53 private ElementVisitor _openWithVisitor = new OpenWithVisitor();
54 private ElementVisitor _listenersVisitor = new ListenersVisitor();
55 private ElementVisitor _listenerVisitor = new ListenerVisitor();
56
57 private static final String KEY_DOCUMENT_CLASS = "documentClass";
58 private static final String KEY_OPEN_WITH_COLL = "openWithColl";
59
60 public static final String ANY_EDITOR_CLASS = "_anyListener";
61
62 private Map /*<String,MetaClass>*/ _editorsByClassName = new HashMap();
63 private Map /*<String,MappingInfo>*/ _mappings = new HashMap();
64 private Map /*<String,MetaClass>*/ _listeners = new HashMap();
65 private Map /*<MetaClass,DisplayInfo>*/ _editorDisplayInfo = new HashMap();
66
67 /**
68 * Get the display information for the specified editor class.
69 *
70 * @param editorClass the editor class.
71 * @return display information for this class of editor.
72 */
73 public DisplayInfo getDisplayInfo( MetaClass editorClass )
74 {
75 return (DisplayInfo) _editorDisplayInfo.get( editorClass );
76 }
77
78 /**
79 * Get all registered editors.
80 *
81 * @return MetaClass instances for all editor classes registered in extension
82 * manifests.
83 */
84 public Collection /*<MetaClass>*/ getEditors()
85 {
86 return _editorsByClassName.values();
87 }
88
89 /**
90 * Get the editor meta class for the specified unique editor class name.
91 *
92 * @param className the editor class name.
93 * @return the editor meta class.
94 */
95 public MetaClass getEditorClass( String className )
96 {
97 return (MetaClass)_editorsByClassName.get( className );
98 }
99
100 /**
101 * Get the class names of all mapped document classes.
102 *
103 * @return a collection of document class names that are mapped.
104 */
105 public Collection /*<String>*/ getMappedDocumentClasses()
106 {
107 return _mappings.keySet();
108 }
109
110 /**
111 * Get the list of mapping infos for the specified document class. Each
112 * mapping info is an editor class and a value indicating whether
113 *
114 * @param documentClass the class of a document.
115 *
116 * @return the document-editor {@link MappingInfo}s. If none available,
117 * return an empty collection.
118 */
119 public Collection /*<MappingInfo>*/ getEditorsForDocClass( Class documentClass )
120 {
121 return (Collection)_mappings.get( documentClass.getName() );
122 }
123
124 /**
125 * Get the list of editor listeners declared in an extension
126 * manifest. This information records the editor listener
127 * classes interested in receiving events from specific editor types.
128 *
129 * @return a map of all listeners. The keys are class names of editors, the
130 * values are Collections of MetaClass instances for each
131 * listener for the corresponding editor class.
132 *
133 */
134 public Map /*<String,Collection<MetaClass>>*/ getListeners()
135 {
136 return _listeners;
137 }
138
139 public void start( ElementStartContext context )
140 {
141 context.registerChildVisitor( EDITORS, _editorsVisitor );
142 context.registerChildVisitor( MAPPINGS, _mappingsVisitor );
143 context.registerChildVisitor( LISTENERS, _listenersVisitor );
144 }
145
146 private class EditorsVisitor extends ElementVisitor
147 {
148 public void start( ElementStartContext context )
149 {
150 context.registerChildVisitor( EDITOR, _editorVisitor );
151 }
152 }
153
154 private class EditorVisitor extends ElementVisitor
155 {
156 public void start( ElementStartContext context )
157 {
158 String editorClass = context.getAttributeValue( "editor-class" );
159 if ( editorClass == null || (editorClass=editorClass.trim()).length() == 0 )
160 {
161 log( context, Level.SEVERE, "Missing required 'editor-class' attribute." );
162 return;
163 }
164
165 ClassLoader cl = (ClassLoader) context.getScopeData().get(
166 ExtensionVisitor.KEY_CLASSLOADER
167 );
168 final MetaClass editorMetaClass = new MetaClass( cl, editorClass );
169 _editorsByClassName.put( editorClass, editorMetaClass );
170
171 context.registerChildVisitor( NAME, new I18NStringVisitor() {
172 protected void string( ElementContext context, String text )
173 {
174 _editorDisplayInfo.put( editorMetaClass, new DisplayInfo( text ) );
175 }
176 });
177 }
178 }
179
180 private class MappingsVisitor extends ElementVisitor
181 {
182 public void start( ElementStartContext context )
183 {
184 context.registerChildVisitor( MAPPING, _mappingVisitor );
185 }
186 }
187
188 private class MappingVisitor extends ElementVisitor
189 {
190 public void start( ElementStartContext context )
191 {
192 String docClass = context.getAttributeValue( "document-class" );
193 if ( docClass == null || (docClass=docClass.trim()).length() == 0 )
194 {
195 log( context, Level.SEVERE, "Missing required 'document-class' attribute." );
196 }
197 else
198 {
199 context.getScopeData().put( KEY_DOCUMENT_CLASS, docClass );
200
201 List mappings = (List) _mappings.get( docClass );
202 if ( mappings == null )
203 {
204 mappings = new ArrayList();
205 _mappings.put( docClass, mappings );
206 }
207
208 context.getScopeData().put( KEY_OPEN_WITH_COLL, mappings );
209 context.registerChildVisitor( OPEN_WITH, _openWithVisitor );
210 }
211 }
212
213 }
214
215 private class OpenWithVisitor extends ElementVisitor
216 {
217 public void start( ElementStartContext context )
218 {
219 String editorClass = context.getAttributeValue( "editor-class" );
220 if ( editorClass == null || (editorClass=editorClass.trim()).length() == 0)
221 {
222 log( context, Level.SEVERE, "Missing required attribute 'editor-class'" );
223 return;
224 }
225
226 String isPreferred = context.getAttributeValue( "preferred" );
227 boolean preferred = isPreferred == null ? false : Boolean.valueOf( isPreferred ).booleanValue();
228
229 MappingInfo mi = new MappingInfo( editorClass, preferred );
230
231 List mappings = (List) context.getScopeData().get( KEY_OPEN_WITH_COLL );
232 mappings.add( mi );
233 }
234
235 }
236
237 private class ListenersVisitor extends ElementVisitor
238 {
239 public void start( ElementStartContext context )
240 {
241 context.registerChildVisitor( EDITOR_LISTENER, _listenerVisitor );
242 }
243 }
244
245 private class ListenerVisitor extends ElementVisitor
246 {
247 public void start( ElementStartContext context )
248 {
249 String sourceClass = context.getAttributeValue( "source-class" );
250 final String listenerClass = context.getAttributeValue( "listener-class" );
251
252 if ( listenerClass == null )
253 {
254 log( context, Level.SEVERE, "Required attribute 'listener-class' missing.");
255 return;
256 }
257
258 ClassLoader cl =
259 (ClassLoader) context.getScopeData().get( ExtensionVisitor.KEY_CLASSLOADER );
260 MetaClass mc = new MetaClass( cl, listenerClass );
261
262 if ( sourceClass == null )
263 {
264 sourceClass = ANY_EDITOR_CLASS;
265 }
266 List listeners = (List) _listeners.get( sourceClass );
267 if ( listeners == null )
268 {
269 listeners = new ArrayList();
270 _listeners.put( sourceClass, listeners );
271 }
272 listeners.add( mc );
273 }
274 }
275
276
277 }