001: /*
002: * $RCSfile: Proto.java,v $
003: *
004: * @(#)Proto.java 1.15 99/03/24 15:33:26
005: *
006: * Copyright (c) 1996-1998 Sun Microsystems, Inc. All Rights Reserved.
007: *
008: * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
009: * modify and redistribute this software in source and binary code form,
010: * provided that i) this copyright notice and license appear on all copies of
011: * the software; and ii) Licensee does not utilize the software in a manner
012: * which is disparaging to Sun.
013: *
014: * This software is provided "AS IS," without a warranty of any kind. ALL
015: * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
016: * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
017: * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
018: * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
019: * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
020: * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
021: * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
022: * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
023: * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
024: * POSSIBILITY OF SUCH DAMAGES.
025: *
026: * This software is not designed or intended for use in on-line control of
027: * aircraft, air traffic, aircraft navigation or aircraft communications; or in
028: * the design, construction, operation or maintenance of any nuclear
029: * facility. Licensee represents and warrants that it will not use or
030: * redistribute the Software for such purposes.
031: *
032: * $Revision: 1.2 $
033: * $Date: 2005/02/03 23:07:00 $
034: * $State: Exp $
035: */
036: /*
037: * @Author: Rick Goldberg
038: * @Author: Doug Gehringer
039: *
040: */
041: package org.jdesktop.j3d.loaders.vrml97.impl;
042:
043: import java.util.Enumeration;
044: import java.util.Hashtable;
045: import java.util.Observer;
046: import java.util.Vector;
047:
048: /** Description of the Class */
049: public class Proto implements Namespace {
050:
051: String name;
052: Loader loader;
053: Vector nodes = new Vector();
054: /** Description of the Field */
055: public Hashtable FieldSpec = new Hashtable(4);
056: Hashtable defTable = new Hashtable();
057: Vector routes = new Vector();
058: ProtoInstance newInstance;
059:
060: /**
061: *Constructor for the Proto object
062: *
063: *@param loader Description of the Parameter
064: *@param initName Description of the Parameter
065: */
066: Proto(Loader loader, String initName) {
067: this .loader = loader;
068: name = initName;
069: if (loader.debug) {
070: System.out.println("PROTO " + initName);
071: }
072: }
073:
074: /**
075: * Gets the name attribute of the Proto object
076: *
077: *@return The name value
078: */
079: String getName() {
080: return name;
081: }
082:
083: /**
084: * Description of the Method
085: *
086: *@param defName Description of the Parameter
087: *@param node Description of the Parameter
088: */
089: public void define(String defName, BaseNode node) {
090: defTable.put(defName, node);
091: }
092:
093: /**
094: * Description of the Method
095: *
096: *@param defName Description of the Parameter
097: *@return Description of the Return Value
098: */
099: public BaseNode use(String defName) {
100: BaseNode orgNode = (BaseNode) defTable.get(defName);
101: return new ProtoUseNode(loader, this , orgNode);
102: }
103:
104: /**
105: * Adds a feature to the Route attribute of the Proto object
106: *
107: *@param fromNode The feature to be added to the Route attribute
108: *@param fromEventOut The feature to be added to the Route attribute
109: *@param toNode The feature to be added to the Route attribute
110: *@param toEventIn The feature to be added to the Route attribute
111: */
112: public void addRoute(BaseNode fromNode, String fromEventOut,
113: BaseNode toNode, String toEventIn) {
114: if (fromNode instanceof ProtoUseNode) {
115: fromNode = ((ProtoUseNode) fromNode).orgNode;
116: }
117: // TODO: test field name and type
118: if (toNode instanceof ProtoUseNode) {
119: toNode = ((ProtoUseNode) toNode).orgNode;
120: }
121: // TODO: test field name and type
122: routes.addElement(new Route(fromNode, fromEventOut, toNode,
123: toEventIn));
124: }
125:
126: /**
127: * Description of the Method
128: *
129: *@param nodeField Description of the Parameter
130: *@param protoFieldName Description of the Parameter
131: *@return Description of the Return Value
132: */
133: synchronized boolean setupIsMap(Field nodeField,
134: String protoFieldName) {
135: protoFieldName = Field.baseName(protoFieldName);
136: Field protoField = (Field) FieldSpec.get(protoFieldName);
137: if (protoField == null) {
138: System.err
139: .println("Proto.setupIsMap(): Can't find proto field \""
140: + protoFieldName + "\"");
141: return false;
142: }
143: nodeField.update(protoField);// set the initial value
144:
145: // Add routes for each way the proto field implies (timestamps will
146: // avoid loops)
147: if (protoField.isEventIn()) {
148: if (nodeField.isEventIn()) {
149: routes.addElement(new Route(null, protoFieldName,
150: nodeField.ownerNode, nodeField.fieldName));
151: } else {
152: return false;
153: }
154: }
155: if (protoField.isEventOut()) {
156: if (nodeField.isEventOut()) {
157: routes.addElement(new Route(nodeField.ownerNode,
158: nodeField.fieldName, null, protoFieldName));
159: } else {
160: return false;
161: }
162: }
163: // If the proto field is a plain field, build the EventIn route
164: // to map the initial value from the parse. There won't
165: // be any further updates since you can't route to the field
166: if (!protoField.isEventIn() && !protoField.isEventOut()) {
167: routes.addElement(new Route(null, protoFieldName,
168: nodeField.ownerNode, nodeField.fieldName));
169: }
170: return true;
171: }
172:
173: /**
174: * Description of the Method
175: *
176: *@param node Description of the Parameter
177: *@param nodeEventName Description of the Parameter
178: *@param protoFieldName Description of the Parameter
179: *@return Description of the Return Value
180: */
181: public boolean setupEventIsMap(Node node, String nodeEventName,
182: String protoFieldName) {
183: protoFieldName = Field.baseName(protoFieldName);
184: Field protoField = (Field) FieldSpec.get(protoFieldName);
185: if (protoField == null) {
186: System.err
187: .println("Proto.setupEventIsMap: Can't find protoField "
188: + protoFieldName);
189: return false;
190: }
191: nodeEventName = Field.baseName(nodeEventName);
192: Field nodeField = (Field) node.FieldSpec.get(nodeEventName);
193: if (nodeField == null) {
194: System.err.println("Proto.setupEventIsMap: Can't find "
195: + "nodeEventName " + nodeEventName);
196: return false;
197: }
198: // Add routes for each way the proto field implies (timestamps will
199: // avoid loops) (( but cause proto bugs if too fast ))
200: if (protoField.isEventIn()) {
201: if (nodeField.isEventIn()) {
202: routes.addElement(new Route(null, protoFieldName,
203: nodeField.ownerNode, nodeEventName));
204: } else {
205: return false;
206: }
207: }
208: if (protoField.isEventOut()) {
209: if (nodeField.isEventOut()) {
210: routes.addElement(new Route(nodeField.ownerNode,
211: nodeEventName, null, protoFieldName));
212: } else {
213: return false;
214: }
215: }
216: return true;
217: }
218:
219: /**
220: * Adds a feature to the Object attribute of the Proto object
221: *
222: *@param node The feature to be added to the Object attribute
223: */
224: public void addObject(BaseNode node) {
225: nodes.addElement(node);
226: }
227:
228: // generate a copy of the proto, resolving linkages to the new instance
229: /**
230: * Description of the Method
231: *
232: *@return Description of the Return Value
233: */
234: public ProtoInstance instance() {
235:
236: // create a new Proto and register it with the loader
237: newInstance = new ProtoInstance(loader, name, this );
238: if (loader.debug) {
239: System.out
240: .println("Proto.instance() begins newInstance is "
241: + newInstance.toStringId());
242: }
243: loader.beginProtoInstance(newInstance);
244:
245: // set up the new fields
246: newInstance.initFields();
247:
248: // clone the trees attached to the Proto. Def'd nodes will
249: // register with the the new instance (see also SFNode.clone() and
250: // MFNode.clone()). Use'd nodes will lookup in the new instance (see
251: // ProtoUseNode.clone()
252:
253: Group protoInstanceHandleabra = new Group(loader);
254: protoInstanceHandleabra.initImpl();
255:
256: BaseNode[] children = new BaseNode[nodes.size()];
257: for (int i = 0; i < nodes.size(); i++) {
258: BaseNode baseNode = (BaseNode) nodes.elementAt(i);
259: //System.out.println(baseNode.getType());
260: if ((baseNode instanceof Script) && (!baseNode.implReady)) {
261: baseNode.initImpl();
262: }
263:
264: // since the sensor will be in an artificial group,
265: // the group above may want the pickability information
266: if (baseNode instanceof VrmlSensor) {
267: newInstance.containsSensor = true;
268: if (newInstance.sensors == null) {
269: newInstance.sensors = new java.util.Vector();
270: }
271: newInstance.sensors.addElement(baseNode);
272: }
273:
274: BaseNode clone = (BaseNode) baseNode.clone();
275: loader.cleanUp();
276:
277: //
278: //if (i == 0) {
279: //newInstance.instanceNode = clone;
280: //}
281:
282: children[i] = clone;
283: loader.registerClone(baseNode, clone);
284: }
285:
286: // TBD
287: // bug, now the protoInstanceHandleabra if it contains
288: // a VrmlSensor must enable pick reporting on the parent
289: // of the protoInstance, which can be discovered(?)
290: // by Proto when it is asked for instance.
291:
292: protoInstanceHandleabra.addChildren.setValue(children);
293: newInstance.instanceNode = protoInstanceHandleabra;
294: if (newInstance.containsSensor) {
295: protoInstanceHandleabra.implGroup.setPickable(true);
296: }
297:
298: loader.cleanUp();
299: newInstance.applyRoutes();
300: if (loader.debug) {
301: System.out
302: .println("Proto.instance() returns instance with "
303: + "VRML tree:\n" + newInstance.instanceNode);
304: }
305: loader.endProtoInstance();
306: return newInstance;
307: }
308:
309: /**
310: * Description of the Method
311: *
312: *@param org Description of the Parameter
313: *@param clone Description of the Parameter
314: */
315: void registerClone(BaseNode org, BaseNode clone) {
316: //System.out.println("registerClone org = " + org.toStringId() +
317: // " clone = " + clone.toStringId());
318: newInstance.nodeMapping.put(org, clone);
319: }
320:
321: /**
322: * Sets the eventIn attribute of the Proto object
323: *
324: *@param eventInName The new eventIn value
325: *@param f The new eventIn value
326: */
327: public void setEventIn(String eventInName, Field f) {
328: String fieldName = Field.baseName(eventInName);
329: f.init(null, FieldSpec, Field.EVENT_IN, fieldName);
330: }
331:
332: /**
333: * Sets the eventOut attribute of the Proto object
334: *
335: *@param eventOutName The new eventOut value
336: *@param f The new eventOut value
337: */
338: public void setEventOut(String eventOutName, Field f) {
339: String fieldName = Field.baseName(eventOutName);
340: f.init(null, FieldSpec, Field.EVENT_OUT, fieldName);
341: }
342:
343: /**
344: * Sets the field attribute of the Proto object
345: *
346: *@param fieldName The new field value
347: *@param f The new field value
348: */
349: public void setField(String fieldName, Field f) {
350: if (loader.debug) {
351: System.out.println("Proto.setField(): adding field named "
352: + fieldName);
353: }
354: fieldName = Field.baseName(fieldName);
355: f.init(null, FieldSpec, Field.FIELD, fieldName);
356: }
357:
358: /**
359: * Sets the exposedField attribute of the Proto object
360: *
361: *@param fieldName The new exposedField value
362: *@param f The new exposedField value
363: */
364: public void setExposedField(String fieldName, Field f) {
365: fieldName = Field.baseName(fieldName);
366: if (loader.debug) {
367: System.out
368: .println("Proto.setExposedField(): adding field named \""
369: + fieldName + "\"");
370: }
371: f.init(null, FieldSpec, Field.EXPOSED_FIELD, fieldName);
372: }
373:
374: /**
375: * Description of the Method
376: *
377: *@return Description of the Return Value
378: */
379: public String toString() {
380: String retval = "Proto " + name + " [\n";
381: for (Enumeration e = FieldSpec.keys(); e.hasMoreElements();) {
382: String fieldName = (String) e.nextElement();
383: Field field = (Field) FieldSpec.get(fieldName);
384: retval += "field ";
385: String fieldType = field.getClass().getName() + " ";
386: int start = fieldType.lastIndexOf(".") + 1;
387: int end = fieldType.length();
388: fieldType = fieldType.substring(start, end);
389: retval += fieldType + " " + fieldName + " " + field;
390: }
391: retval += "]\n{\n";
392: for (int i = 0; i < nodes.size(); i++) {
393: BaseNode baseNode = (BaseNode) nodes.elementAt(i);
394: retval += baseNode + "\n";
395: }
396: retval += "}\n";
397: return retval;
398: }
399: }
|