1/*
2 * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package com.sun.beans.decoder;
26
27import java.beans.XMLDecoder;
28
29/**
30 * This class is intended to handle <java> element.
31 * Each element that appears in the body of this element
32 * is evaluated in the context of the decoder itself.
33 * Typically this outer context is used to retrieve the owner of the decoder,
34 * which can be set before reading the archive.
35 * <p>The following attributes are supported:
36 * <dl>
37 * <dt>version
38 * <dd>the Java version (not supported)
39 * <dt>class
40 * <dd>the type of preferable parser (not supported)
41 * <dt>id
42 * <dd>the identifier of the variable that is intended to store the result
43 * </dl>
44 *
45 * @see DocumentHandler#getOwner
46 * @see DocumentHandler#setOwner
47 * @since 1.7
48 *
49 * @author Sergey A. Malenkov
50 */
51final class JavaElementHandler extends ElementHandler {
52    private Class<?> type;
53    private ValueObject value;
54
55    /**
56     * Parses attributes of the element.
57     * The following attributes are supported:
58     * <dl>
59     * <dt>version
60     * <dd>the Java version (not supported)
61     * <dt>class
62     * <dd>the type of preferable parser (not supported)
63     * <dt>id
64     * <dd>the identifier of the variable that is intended to store the result
65     * </dl>
66     *
67     * @param name   the attribute name
68     * @param value  the attribute value
69     */
70    @Override
71    public void addAttribute(String name, String value) {
72        if (name.equals("version")) { // NON-NLS: the attribute name
73            // unsupported attribute
74        } else if (name.equals("class")) { // NON-NLS: the attribute name
75            // check class for owner
76            this.type = getOwner().findClass(value);
77        } else {
78            super.addAttribute(name, value);
79        }
80    }
81
82    /**
83     * Adds the argument to the list of readed objects.
84     *
85     * @param argument  the value of the element that contained in this one
86     */
87    @Override
88    protected void addArgument(Object argument) {
89        getOwner().addObject(argument);
90    }
91
92    /**
93     * Tests whether the value of this element can be used
94     * as an argument of the element that contained in this one.
95     *
96     * @return {@code true} if the value of this element should be used
97     *         as an argument of the element that contained in this one,
98     *         {@code false} otherwise
99     */
100    @Override
101    protected boolean isArgument() {
102        return false; // do not use owner as object
103    }
104
105    /**
106     * Returns the value of this element.
107     *
108     * @return the value of this element
109     */
110    @Override
111    protected ValueObject getValueObject() {
112        if (this.value == null) {
113            this.value = ValueObjectImpl.create(getValue());
114        }
115        return this.value;
116    }
117
118    /**
119     * Returns the owner of the owner document handler
120     * as a value of &lt;java&gt; element.
121     *
122     * @return the owner of the owner document handler
123     */
124    private Object getValue() {
125        Object owner = getOwner().getOwner();
126        if ((this.type == null) || isValid(owner)) {
127            return owner;
128        }
129        if (owner instanceof XMLDecoder) {
130            XMLDecoder decoder = (XMLDecoder) owner;
131            owner = decoder.getOwner();
132            if (isValid(owner)) {
133                return owner;
134            }
135        }
136        throw new IllegalStateException("Unexpected owner class: " + owner.getClass().getName());
137    }
138
139    /**
140     * Validates the owner of the &lt;java&gt; element.
141     * The owner is valid if it is {@code null} or an instance
142     * of the class specified by the {@code class} attribute.
143     *
144     * @param owner  the owner of the &lt;java&gt; element
145     * @return {@code true} if the {@code owner} is valid;
146     *         {@code false} otherwise
147     */
148    private boolean isValid(Object owner) {
149        return (owner == null) || this.type.isInstance(owner);
150    }
151}
152