Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 0f62b02c2ce09d7542f27def20a00d2fa10fb053 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
/*******************************************************************************
 * Copyright (c) 2004, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.internal.intro.impl.model;

import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.ui.internal.intro.impl.model.util.BundleUtil;
import org.eclipse.ui.internal.intro.impl.util.StringUtil;
import org.osgi.framework.Bundle;
import org.w3c.dom.Element;

/**
 * An intro config component. All config components can get to their defining
 * config element or bundle depending from where the element was loaded.
 * <p>
 * Class Rules:
 * <ul>
 * <li>If an element does not appear as a child under any node, then that
 * element does not need a type to be defined.</li>
 * <li>Each subclass must ensure that it properly supports cloning. This means
 * that if a deep copy is needed, the subclass must override the base behavior
 * here.</li>
 * <li>if cloning is not needed, override clone method and throw an unsupported
 * cloning exception. For now, only pages and targets of includes are cloneable.
 * </li>
 * </ul>
 * <p>
 * Note: This is an abstract base class for all classes in the Intro Model. <br>
 * Clients are not expected to implement or subclass this class, or any of its
 * subclasses.
 */
public abstract class AbstractIntroElement implements Cloneable {

    /**
     * Type constant which identifies an IntroModelRoot element.
     */
    public static final int MODEL_ROOT = 1;

    /**
     * Type constant which identifies an IntroPartPresentation element.
     */
    public static final int PRESENTATION = 1 << 1;

    /**
     * Type constant which identifies an IntroHomePage element.
     */
    public static final int HOME_PAGE = 1 << 2;

    /**
     * Type constant which identifies the IntroPage element.
     */
    public static final int PAGE = 1 << 3;

    /**
     * Type constant which identifies the AbstractIntroPage element.
     */
    public static final int ABSTRACT_PAGE = HOME_PAGE | PAGE;

    /**
     * Type constant which identifies an IntroDiv element.
     */
    public static final int GROUP = 1 << 4;

    /**
     * Type constant which identifies the AbstractIntroContainer element.
     */
    public static final int ABSTRACT_CONTAINER = ABSTRACT_PAGE | GROUP
            | MODEL_ROOT;

    /**
     * Type constant which identifies the IntroHtml element.
     */
    public static final int HTML = 1 << 5;

    /**
     * Type constant which identifies the IntroLink element.
     */
    public static final int LINK = 1 << 6;

    /**
     * Type constant which identifies the IntroImage element.
     */
    public static final int IMAGE = 1 << 7;

    /**
     * Type constant which identifies the IntroInclude element.
     */
    public static final int INCLUDE = 1 << 8;

    /**
     * Type constant which identifies the IntroText element.
     */
    public static final int TEXT = 1 << 9;

    /**
     * Type constant which identifies the IntroContainerExtension element.
     */
    public static final int CONTAINER_EXTENSION = 1 << 10;

    /**
     * Type constant which identifies the IntroHead element.
     */
    public static final int HEAD = 1 << 11;

    /**
     * Type constant which identifies the IntroHead element.
     */
    public static final int PAGE_TITLE = 1 << 12;

    /**
     * Type constant which identifies the IntroAnchor element.
     */
    public static final int ANCHOR = 1 << 13;

    /**
     * Type constant which identifies the IntroContentProvider element.
     */
    public static final int CONTENT_PROVIDER = 1 << 14;

    /**
     * Type constant which identifies the LaunchBarElement.
     */
    public static final int LAUNCH_BAR = 1 << 15;

    /**
     * Type constant which identifies the launch bar shortcut.
     */
    public static final int LAUNCH_BAR_SHORTCUT = 1 << 16;

    /**
     * Type constant which identifies am injected IFrame model element.
     */
    public static final int INJECTED_IFRAME = 1 << 17;
    
    /**
     * Type constant for the theme element.
     */
    public static final int THEME = 1 << 18;
    
    /**
     * Type constant for the hr element.
     */
    public static final int HR = 1 << 19;


    /**
     * Type constant which identifies the AbstractText element.
     */
    public static final int ABSTRACT_TEXT = HTML | LINK | CONTENT_PROVIDER;

    /**
     * Type constant which identifies the AbstractCommonIntroElement element.
     */
    public static final int BASE_ELEMENT = ABSTRACT_CONTAINER | ABSTRACT_TEXT
            | IMAGE | TEXT | PAGE_TITLE;

    /**
     * Type constant which identifies any element in the Intro Model which can
     * have an id. Note: eventhough IntroStandbyContentPart has an id, it does
     * not appear as a child in the model, and so it does not have a type.
     */
    public static final int ID_ELEMENT = BASE_ELEMENT | ANCHOR;

    /**
     * Type constant which identifies any element in the Intro Model.
     */
    public static final int ELEMENT = ID_ELEMENT | CONTAINER_EXTENSION | HEAD
            | INCLUDE | PRESENTATION | LAUNCH_BAR | LAUNCH_BAR_SHORTCUT;



    private AbstractIntroElement parent;
    private Object cfgElement;
    private Bundle bundle;
    private String mixinStyle;


    /**
     * Constructor used when model elements are being loaded from plugin.xml.
     */
    AbstractIntroElement(IConfigurationElement element) {
        cfgElement = element;
        bundle = BundleUtil.getBundleFromConfigurationElement(element);
    }


    /**
     * Constructor used when model elements are being loaded from an xml content
     * file. Bundle is propagated down the model to enable resolving resources
     * relative to the base of the bundle.
     * 
     * @param element
     * @param pd
     */
    AbstractIntroElement(Element element, Bundle bundle) {
    	this.cfgElement = element;
        this.bundle = bundle;
    }


    /**
     * Constructor used when model elements are being loaded from an xml content
     * file. Bundle AND base is propagated down the model to enable resolving
     * resources relative to the xml content file. The base is set to point to
     * the relative location of the parent folder that holds the content file.
     * In the case of a configExtension, it is set to point to the relative
     * position of the parent folder that holds the extension. Only when needed,
     * the base field is stored in a model element. This saves memory.
     * 
     * @param element
     * @param pd
     */
    AbstractIntroElement(Element element, Bundle bundle, String base) {
        this(element, bundle);
    }




    /**
     * Returns the configuration element from which this intro element was
     * loaded. In the case of extension, returns the configuration element of
     * the defining extension.
     * 
     * @return
     */
    public IConfigurationElement getCfgElement() {
        return cfgElement instanceof IConfigurationElement?(IConfigurationElement)cfgElement:null;
    }
    
    public Element getElement() {
    	return cfgElement instanceof Element?(Element)cfgElement:null;
    }

    /**
     * DOM getAttribute retruns an empty string (not null) if attribute is not
     * defined. Override this behavior to be consistent with Intro Model, and
     * IConfiguration element.
     * 
     * @param element
     * @param att
     * @return
     */
    protected String getAttribute(Element element, String att) {
        if (element.hasAttribute(att)) {
            String value = element.getAttribute(att);
            if (value!=null) {
            	IntroModelRoot root = getModelRoot();
            	if (root!=null)
            		return root.resolveVariables(value);
            	return value;
            }
        }
        return null;
    }

    /**
     * Util method to parse a comma separated list of values
     * 
     * @param element
     * @param att
     * @return
     */
    protected String[] getAttributeList(Element element, String att) {
        if (element.hasAttribute(att)) {
            String value = element.getAttribute(att);
            if (value!=null) {
            	IntroModelRoot root = getModelRoot();
            	if (root!=null)
            		value = root.resolveVariables(value);
            	return StringUtil.split(value, ","); //$NON-NLS-1$
            }
        }
        /*
        if (element.hasAttribute(att))
            return element.getAttribute(att).split(","); //$NON-NLS-1$
            */
        return null;
    }
    
    protected void loadFromParent() {
    }


    /**
     * Returns the plugin descriptor of the plugin from which this intro element
     * was loaded. In the case of extension, returns the plugin descriptor of
     * the plugin defining the extension.
     * 
     * @return
     */
    public Bundle getBundle() {
        return bundle;
    }



    /**
     * Returns the specific model type of this intro element. To be implemented
     * by all subclasses.
     * 
     * @return returns one of the model class types defined in this class.
     */
    public abstract int getType();


    /**
     * Returns the parent of this intro element.
     * <p>
     * Rules:
     * <ul>
     * <li>For the model root, it retruns null.</li>
     * <li>For the introPart presentation it returns a model root.</li>
     * <li>For Pages, it returns an intro model root.</li>
     * <li>For all other elements, it retruns a subclass of abstract container.
     * </li>
     * <li>for divs that are children of configs (shared divs), it returns the
     * holding model root.</li>
     * <li>for Head elements that are children of Implementation elements
     * (shared Heads), it returns the holding presentation element.</li>
     * </ul>
     * 
     * @return returns the parent of this intro element. Null only for model
     *         root.
     */
    public AbstractIntroElement getParent() {
        return parent;
    }

    /**
     * @param parent
     *            The parent to set.
     */
    public void setParent(AbstractIntroElement parent) {
        this.parent = parent;
        if (parent!=null)
        	loadFromParent();
    }

    public void setBundle(Bundle bundle) {
        this.bundle = bundle;
    }

    /**
     * Returns the parent page holding this intro element. For the model root
     * and the introPart presentation it returns null. For Pages, it returns the
     * page itself. For all other element, returns the holding page.
     * <p>
     * Exceptions:
     * <ul>
     * <li>for divs that are children of configs (shared divs), it returns
     * null.</li>
     * <li>for Head elements that are children of Implementation elements
     * (shared Heads), it returns null.</li>
     * </ul>
     */
    public AbstractIntroPage getParentPage() {
        // return yourself if you are a page.
        if (isOfType(AbstractIntroElement.ABSTRACT_PAGE))
            return (AbstractIntroPage) this;

        AbstractIntroElement parent = getParent();
        if (parent == null)
            return null;

        while (parent != null && parent.getParent() != null
                && !parent.isOfType(AbstractIntroElement.ABSTRACT_PAGE))
            parent = parent.getParent();
        if (parent.isOfType(ABSTRACT_PAGE))
            return (AbstractIntroPage) parent;
        return null;
    }
    
    public IntroModelRoot getModelRoot() {
        // return yourself if you are a model root.
        if (isOfType(AbstractIntroElement.MODEL_ROOT))
            return (IntroModelRoot) this;

        AbstractIntroElement parent = getParent();
        if (parent == null)
            return null;

        while (parent != null && parent.getParent() != null
                && !parent.isOfType(AbstractIntroElement.MODEL_ROOT))
            parent = parent.getParent();
        if (parent.isOfType(MODEL_ROOT))
            return (IntroModelRoot) parent;
        return null;    	
    }


    /**
     * Returns whether the element is among the specified element types. An
     * example of an element mask is as follows:
     * <p>
     * <code>
     *  	int elementMask = IntroElement.ABSTRACT_CONTAINER;
     * 		int elementMask = IntroElement.DIV | IntroElement.DEFAULT_LINK;
     * </code>
     * 
     * @param elementMask
     *            element mask formed by bitwise OR of element type constants
     *            defined in this class.
     * @return <code>true</code> if this element has a matching type, and
     *         <code>false</code> otherwise.
     */
    public boolean isOfType(int elementMask) {
        return (getType() & elementMask) != 0;
    }

    /**
     * Returns whether the types of all the elements in the given array are
     * among the specified element types. <br>
     * An example of an element mask is as follows:
     * <p>
     * <code>
     * int elementMask = IntroElement.DIV | IntroElement.DEFAULT_LINK;
     * </code>
     * 
     * @return <code>true</code> if all elements are of the right type, and
     *         <code>false</code> if the list is empty, or at least one
     *         element is not of the specified types.
     */
    public static final boolean allElementsAreOfType(
            AbstractIntroElement[] elements, int elementMask) {
        // if we have an empty list, no point going on.
        if (elements.length == 0)
            return false;

        for (int i = 0; i < elements.length; i++) {
            AbstractIntroElement element = elements[i];
            if (!element.isOfType(elementMask))
                return false;
        }
        return true;
    }

    /**
     * Shallow copy. The design of cloning this model assumes that when a
     * container is cloned, all its children must be cloned and reparented to
     * it, hence one clone of this container object. This is why we have a
     * shallow copy here.
     */
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }


	
	public String getMixinStyle() {
		return mixinStyle;
	}


	
	public void setMixinStyle(String mixinStyle) {
		this.mixinStyle = mixinStyle;
	}



}

Back to the top