Source code: com/trapezium/vrml/node/PROTOInstance.java
1 /*
2 * @(#)PROTOInstance.java
3 *
4 * Copyright (c) 1998 by Trapezium Development LLC. All Rights Reserved.
5 *
6 * The information in this file is the property of Trapezium Development LLC
7 * and may be used only in accordance with the terms of the license granted
8 * by Trapezium.
9 *
10 */
11 package com.trapezium.vrml.node;
12
13 import com.trapezium.parse.TokenEnumerator;
14 import com.trapezium.vrml.fields.Field;
15 import com.trapezium.vrml.fields.FieldValue;
16 import com.trapezium.vrml.fields.ISField;
17 import com.trapezium.vrml.fields.SFNodeValue;
18 import com.trapezium.vrml.fields.MFNodeValue;
19 import com.trapezium.vrml.Scene;
20 import com.trapezium.vrml.VrmlElement;
21 import com.trapezium.vrml.grammar.VRML97;
22 import com.trapezium.vrml.grammar.FieldDescriptor;
23 import com.trapezium.vrml.visitor.ISLocator;
24 import com.trapezium.vrml.visitor.DEFVisitor;
25 import java.util.Vector;
26
27 /**
28 * Scene graph component for a PROTO instance.
29 *
30 * The PROTOInstance has field values which are explicitly declared,
31 * and are part of the PROTO interface. It has node values which are
32 * copied from the PROTO declaration, with actual values from the
33 * instance substituted where indicated by IS fields.
34 *
35 * Note: The above level of PROTOInstance construction is not complete.
36 *
37 * USE nodeNameId
38 *
39 * @author Johannes N. Johannsen
40 * @version 1.21, 16 July 1998, self ref PROTO USE bug
41 * @version 1.12, 7 April 1998, added "getFieldNames" method
42 * @version 1.1, 6 Jan 1998
43 *
44 * @since 1.0
45 */
46 public class PROTOInstance extends Node {
47 PROTObase protoBase;
48
49 /** Class constructor */
50 public PROTOInstance( PROTObase pb ) {
51 super();
52 protoBase = pb;
53 }
54
55 /** template method, overrides Node.isPROTOnode() which returns false. */
56 public boolean isPROTOnode() {
57 return( true );
58 }
59
60 /** Get the first node in the PROTO declaration, this node defines the
61 * type of the PROTO.
62 */
63 public Node getPROTONodeType() {
64 return( protoBase.getPROTONodeType() );
65 }
66
67 /** Get a reference to the declaration of the PROTO */
68 public PROTObase getPROTObase() {
69 return( protoBase );
70 }
71
72 /** Get the FieldDescriptor, defined by IS usage for a field */
73 public FieldDescriptor getFieldDescriptor( String fieldId ) {
74 if ( protoBase != null ) {
75 return( protoBase.getFieldDescriptor( fieldId ));
76 } else {
77 return( null );
78 }
79 }
80
81 /** Get the name of the PROTO this instance is based on */
82 public String getPROTOname() {
83 if ( protoBase != null ) {
84 return( protoBase.getId() );
85 } else {
86 return( null );
87 }
88 }
89
90 /** Get the name of the Node type compatible with this PROTO */
91 public String getNodeName() {
92 Node n = getPROTONodeType();
93 if ( n != null ) {
94 return( n.getNodeName() );
95 } else {
96 return( null );
97 }
98 }
99
100 /** get the field id with the closest spelling */
101 public String getClosestFieldId( String fieldName ) {
102 if ( protoBase != null ) {
103 return( protoBase.getClosestFieldId( fieldName ));
104 } else {
105 return( null );
106 }
107 }
108
109 /** get the VRML97 field type SF<type> or MF<type> for the field.
110 *
111 * @return type is returned as a String, "UnknownType" returned
112 * if field is unknown.
113 */
114 public String getFieldType( String fieldName ) {
115 if ( protoBase != null ) {
116 Field f = protoBase.getInterfaceDeclaration( fieldName );
117 if ( f != null ) {
118 return( VRML97.getFieldTypeString( f.getFieldType() ));
119 }
120 }
121 return( "UnknownType" );
122 }
123
124 /** get the interface declaration of the field
125 *
126 * @return Field declaring the interface, null if field unknown
127 */
128 public Field getInterfaceDeclaration( String fieldName ) {
129 if ( protoBase != null ) {
130 return( protoBase.getInterfaceDeclaration( fieldName ));
131 } else {
132 return( null );
133 }
134 }
135
136 /** Check if field is part of the PROTO interface declaration.
137 *
138 * @return true if the <B>fieldName</B> is part of the PROTO
139 * interface declaration, otherwise false.
140 */
141 public boolean isValidFieldId( String fieldName ) {
142 if ( protoBase != null ) {
143 return( protoBase.isValidFieldId( fieldName ));
144 } else {
145 return( false );
146 }
147 }
148
149 /** Copy all nodes containing IS references from PROTO declaration body.
150 *
151 * IS references are resolved as the copy takes place.
152 */
153 public void copyBaseNodeInfo() {
154 if ( protoBase != null ) {
155 Scene s = protoBase.getPROTObody();
156 if ( s != null ) {
157 int nChildren = s.numberChildren();
158 // ISLocator il = new ISLocator();
159 for ( int i = 0; i < nChildren; i++ ) {
160 VrmlElement vle = s.getChildAt( i );
161 if ( vle instanceof Node ) {
162 // il.reset();
163 // vle.traverse( il );
164
165 // create copies of nodes that have IS field references
166 // if ( il.foundISField() ) {
167 Node n = (Node)vle;
168 Node newNode = (Node)n.vrmlClone( this );
169 addChild( newNode );
170 // }
171 }
172 }
173 }
174 }
175 }
176
177 /**
178 * Validate the nodes contained in a PROTO instance.
179 */
180 public void verify( TokenEnumerator v ) {
181 Scene scene = (Scene)getScene();
182 if ( scene != null ) {
183 int nChildren = numberChildren();
184 int vstate = v.getState();
185 for ( int i = 0; i < nChildren; i++ ) {
186 VrmlElement ve = getChildAt( i );
187 if ( ve instanceof Node ) {
188 Node node = (Node)ve;
189 NodeType.verify( node, node.getNodeName(), scene );
190 }
191 }
192 v.setState( vstate );
193 }
194 }
195
196 /** Get the interface type of a particular field.
197 *
198 * @param fieldId the name of the field to check
199 * @return VRML97.UnknownInterfaceType if the field doesn't exist in
200 * the PROTO, otherwise one of VRML97.exposedField, VRML97.field,
201 * VRML97.eventIn, VRML97.eventOut.
202 */
203 public int getInterfaceType( String fieldId ) {
204 Field f = getInterfaceDeclaration( fieldId );
205 if ( f != null ) {
206 return( f.getInterfaceType() );
207 } else {
208 return( VRML97.UnknownInterfaceType );
209 }
210 }
211
212 /** Get a list of field names defined for the PROTO.
213 */
214 public String[] getFieldNames() {
215 return( protoBase.getFieldNames() );
216 }
217
218 /** Check if the instance fields are in use, handles case
219 * where the field is not referenced by IS in the PROTO declaration,
220 * but the field is DEFed in an instance, and USEd somewhere else.
221 * Note, at the time this is called (during parsing, we don't know if
222 * the DEF is USEd, so we just assume it is).
223 * In this case, the "not referenced" IS warning has to be removed.
224 */
225 public void checkInUse() {
226 if ( protoBase != null ) {
227 if ( protoBase.hasUnusedInterfaces() ) {
228 int nChildren = numberChildren();
229 for ( int i = 0; i < nChildren; i++ ) {
230 VrmlElement ve = getChildAt( i );
231 if ( ve instanceof Field ) {
232 Field f = (Field)ve;
233 FieldValue fv = f.getFieldValue();
234 if (( fv instanceof SFNodeValue) || ( fv instanceof MFNodeValue )) {
235 DEFVisitor dv = new DEFVisitor();
236 fv.traverse( dv );
237 if ( dv.getNumberDEFs() > 0 ) {
238 Field interfaceDeclaration = protoBase.getInterfaceDeclaration( f.getFieldId() );
239 if ( interfaceDeclaration != null ) {
240 String err = interfaceDeclaration.getError();
241 if ( err != null ) {
242 if ( err.indexOf( "not referenced" ) > 0 ) {
243 interfaceDeclaration.setError( null );
244 }
245 }
246 }
247 }
248 }
249 }
250 }
251 }
252 }
253 }
254 }
255