001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.j2ee.sun.share.config;
043:
044: import javax.enterprise.deploy.model.*;
045: import javax.enterprise.deploy.spi.exceptions.ConfigurationException;
046: import org.netbeans.modules.j2ee.dd.api.common.RootInterface;
047: import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
048: import org.netbeans.modules.j2ee.deployment.plugins.api.*;
049: import org.netbeans.modules.schema2beans.*;
050: import org.openide.ErrorManager;
051: import java.io.Writer;
052: import java.io.StringWriter;
053: import java.util.*;
054:
055: abstract public class DDCommon implements DDBean {
056:
057: StandardDDImpl container;
058: DDCommon parent = null;
059: //final BaseBean bean;
060: final String xpath;
061: final String dtdname;
062: final ModuleDDSupport support;
063: final Set configBeans = new HashSet();
064: final Set childBeans = new HashSet();
065: RootInterface rooti;
066:
067: // must know about its STandardDDImpl to pass to ConfigBeanStorage
068: DDCommon(DDCommon copy) {
069: this (copy.parent, copy.rooti, copy.support, copy.xpath);
070: configBeans.addAll(copy.configBeans);
071: }
072:
073: DDCommon(DDCommon parent, BaseBean bean, ModuleDDSupport support,
074: String dtdname) {
075: this .parent = parent;
076: //this.bean = bean;
077: this .dtdname = dtdname;
078: this .xpath = ((parent == null) ? "" : parent.xpath) + "/"
079: + dtdname; // NOI18N
080: this .support = support;
081: if (parent != null) {
082: parent.addChild(this );
083: }
084: }
085:
086: DDCommon(DDCommon parent, RootInterface rooti,
087: ModuleDDSupport support, String dtdname) {
088: this .parent = parent;
089: this .rooti = rooti;
090: //this.bean = null;
091: this .dtdname = dtdname;
092: this .xpath = ((parent == null) ? "" : parent.xpath) + "/"
093: + dtdname; // NOI18N
094: this .support = support;
095: if (parent != null) {
096: parent.addChild(this );
097: }
098: }
099:
100: void addChild(DDCommon bean) {
101: childBeans.add(bean);
102: }
103:
104: void removeChild(DDCommon bean) {
105: childBeans.remove(bean);
106: }
107:
108: // find the DDBean which is a child of this DDBean that has the
109: // given corresponding BaseBean. If there is no such DDBean, return
110: // null
111: DDCommon findChild(BaseBean bean) {
112: for (Iterator i = childBeans.iterator(); i.hasNext();) {
113: DDCommon child = (DDCommon) i.next();
114: if (child.rooti == rooti) {
115: return child;
116: }
117: }
118: return null;
119: }
120:
121: final public String getXpath() {
122: return xpath;
123: }
124:
125: final public DDBeanRoot getRoot() {
126: DDCommon root = this ;
127: while (root.parent != null) {
128: root = root.parent;
129: }
130: return (DDRoot) support.getBean(root.rooti);
131: }
132:
133: final public DDBean[] getChildBean(String xpath) {
134: return getChildrenImpl(xpath);
135: }
136:
137: public String getText() {
138: Writer w = new StringWriter();
139: try {
140: w.write("FIXME");
141: //bean.writeNode(w);
142: //rooti.write(new java.io.)
143: } catch (Exception e) {
144: }
145: return w.toString();
146: }
147:
148: final public String[] getText(String xpath) {
149: StandardDDImpl[] dds = getChildrenImpl(xpath);
150: if (dds == null) {
151: return null;
152: }
153: String[] ret = new String[dds.length];
154: for (int i = 0; i < dds.length; i++) {
155: ret[i] = dds[i].proxy.getText();
156: }
157: return ret;
158: }
159:
160: final private StandardDDImpl[] getChildrenImpl(String xpath) {
161: // System.out.println("Starting search with " + xpath);
162: xpath = ModuleDDSupport.normalizePath(xpath);
163: // System.out.println("Now " + xpath);
164: DDCommon searchRoot = this ;
165: if (xpath == null || xpath.equals("") || xpath.equals(".")) { // NOI18N
166: return new StandardDDImpl[] { container };
167: }
168:
169: if (xpath.startsWith("/")) { // NOI18N
170: searchRoot = ((DDRoot) getRoot()).proxy;
171: xpath = xpath.substring(xpath.indexOf("/") + 1); // NOI18N
172: } else if (xpath.equals("..")) {
173: if (parent == null) {
174: return null;
175: } else {
176: return new StandardDDImpl[] { parent.container };
177: }
178: } else {
179: while (xpath.startsWith("../") && searchRoot != null) {
180: searchRoot = searchRoot.parent;
181: xpath = xpath.substring(3);
182: }
183: }
184:
185: Collection ret = searchRoot != null ? searchRoot.search(xpath,
186: true) : Collections.EMPTY_LIST;
187:
188: StandardDDImpl[] arr = new StandardDDImpl[ret.size()];
189: ret.toArray(arr);
190: return arr;
191: }
192:
193: Collection search(String xpath, boolean addCurrent) {
194:
195: Collection ret = new LinkedList();
196:
197: int index = xpath.indexOf("/"); // NOI18N
198: String fragment = index < 0 ? xpath : xpath.substring(0, index);
199:
200: if (isProxy()) {
201: // find all children manually
202: // FIXME
203: BeanProp prop = null; //bean.beanProp(fragment);
204: if (prop != null) {
205: String remainder = index < 0 ? "" : xpath
206: .substring(index); // NOI18N
207: if (prop.isIndexed()) {
208: Object[] values = prop.getValues();
209: for (int i = 0; i < values.length; i++) {
210: DDCommon ddc = prop.isBean() ? support
211: .getBean((BaseBean) values[i]).proxy
212: : support.getBean(prop, i).proxy;
213: ret.addAll(ddc.search(remainder, true));
214: }
215: } else {
216: DDCommon ddc = prop.isBean() ? support.getBean(prop
217: .getBean()).proxy : support.getBean(prop,
218: -1).proxy;
219: ret.addAll(ddc.search(remainder, true));
220: }
221: }
222: } else if (addCurrent) {
223: // DDParser parser = new DDParser(bean,xpath);
224: // DDParser parser = new DDParser(rooti,xpath);
225: //
226: // while(parser.hasNext()) {
227: // Object current = parser.next();
228: // DDParser.DDLocation location = parser.getLocation();
229: // if(location.isNode()) {
230: // BaseBean currentBean = (BaseBean) current;
231: // ret.add(support.getBean(currentBean));
232: // }
233: // else {
234: // ret.add(support.getBean(
235: // location.getRoot().getProperty(location.getName()),
236: // location.getIndex()));
237: // }
238: // }
239: }
240:
241: if (index < 0)
242: return ret;
243:
244: // PENDING optimization - keep a semaphore recording whether
245: // or not there are any children proxies, if not you can
246: // skip this loop
247: for (Iterator i = childBeans.iterator(); i.hasNext();) {
248: DDCommon ddc = (DDCommon) i.next();
249: if (ddc.dtdname.equals(fragment))
250: ret.addAll(ddc.search(xpath.substring(index), false));
251: }
252:
253: return ret;
254:
255: }
256:
257: boolean isProxy() {
258: return false;
259: }
260:
261: public void addXpathListener(String xpath, XpathListener listener) {
262: support.addXpathListener(this , xpath, listener);
263: }
264:
265: public void removeXpathListener(String xpath, XpathListener listener) {
266: support.removeXpathListener(this , xpath, listener);
267: }
268:
269: public int hashCode() {
270: return rooti.hashCode();
271: }
272:
273: /* Must be overridden in subclasses, and super.equals(o) must be
274: part of the computation. */
275: public boolean equals(Object o) {
276: if (o instanceof DDCommon)
277: return ((DDCommon) o).rooti == rooti;
278: return false;
279: }
280:
281: void fireEvent(XpathEvent xe) {
282: // System.out.println("Got event " + xe + " at " + this);
283: if (xe.isChangeEvent()) {
284: notifyChange(xe);
285: } else {
286: // xpath is a prefix of eventXpath
287: // System.out.println("Xpath is " + xpath);
288: String eventXpath = xe.getBean().getXpath();
289: // System.out.println("eventXpath is " + eventXpath);
290: // take away xpath
291: String relPath = getRelativePath(eventXpath, xpath);
292: ConfigBeanStorage[] confBeans = getConfigBeans();
293: for (int i = 0; i < confBeans.length; i++) {
294: try {
295: confBeans[i].fireEvent(relPath, xe);
296: } catch (ConfigurationException e) {
297: // PENDING need to do something better here with the CE?
298: ErrorManager.getDefault().log(ErrorManager.WARNING,
299: e.getMessage());
300: }
301: }
302: }
303: if (parent != null) {
304: parent.fireEvent(xe);
305: }
306: }
307:
308: public static String getRelativePath(String child, String parent) {
309: String relPath = child.substring(parent.length());
310: if (relPath.startsWith("/"))
311: relPath = relPath.substring(1); // NOI18N
312: return relPath;
313: }
314:
315: void notifyChange(XpathEvent event) {
316: ConfigBeanStorage[] confBeans = getConfigBeans();
317: for (int i = 0; i < confBeans.length; i++) {
318: confBeans[i].bean.notifyDDChange(event);
319: }
320: }
321:
322: // PENDING move the fireCustomizerListeners to this class as well.
323: public void addConfigBean(ConfigBeanStorage cbs) {
324: configBeans.add(cbs);
325: }
326:
327: public void removeConfigBean(ConfigBeanStorage cbs) {
328: configBeans.remove(cbs);
329: }
330:
331: public ConfigBeanStorage[] getConfigBeans() {
332: ConfigBeanStorage[] ret = new ConfigBeanStorage[configBeans
333: .size()];
334: configBeans.toArray(ret);
335: return ret;
336: }
337:
338: public String[] getAttributeNames() {
339: return null;
340: }
341:
342: public String getAttributeValue(String name) {
343: return null;
344: }
345:
346: public String getId() {
347: return null;
348: }
349:
350: public J2eeModuleProvider getModuleProvider() {
351: return support.getProvider();
352: }
353: }
|