1 4 5 9 10 package org.openlaszlo.compiler; 11 import java.util.*; 12 import org.jdom.Element; 13 14 class ClassModel { 15 protected final ViewSchema schema; 16 protected final String className; 17 protected final ClassModel superclass; 19 protected final Element definition; 21 protected NodeModel nodeModel; 22 23 24 protected String superclassName = null; 25 protected boolean hasInputText = false; 26 protected boolean isInputText = false; 27 28 29 protected boolean supportsTextAttribute = false; 30 31 protected final Map attributeSpecs = new HashMap(); 32 33 protected final Map methods = new HashMap(); 34 protected boolean inline = false; 35 36 public String toString() { 37 return "ClassModel: className="+className + ", " + 38 "superclass=" + superclass + ", " + 39 "superclassName=" + superclassName + ", " + 40 "hasInputText=" + hasInputText + ", " + 41 "isInputText=" + isInputText + ", " + 42 "definition=" + definition; 43 } 44 45 ClassModel(String className, ClassModel superclass, 47 ViewSchema schema, Element definition) { 48 this.className = className; 49 this.superclass = superclass; 50 this.definition = definition; 51 this.schema = schema; 52 } 53 54 ClassModel(String className, ViewSchema schema) { 56 this(className, null, schema, null); 57 } 58 59 61 boolean isSubclassOf(ClassModel superclass) { 62 if (this == superclass) return true; 63 if (this.superclass == null) return false; 64 return this.superclass.isSubclassOf(superclass); 65 } 66 67 boolean isBuiltin() { 68 return superclass == null; 69 } 70 71 ClassModel getSuperclassModel() { 72 return superclass; 73 } 74 75 String getSuperclassName() { 76 if (superclassName != null) { 77 return superclassName; 78 } else if (superclass == null) { 79 return null; 80 } else { 81 return superclass.className; 82 } 83 } 84 85 89 AttributeSpec getAttribute(String attrName) { 90 AttributeSpec attr = (AttributeSpec) attributeSpecs.get(attrName); 91 if (attr != null) { 92 return attr; 93 } else if (superclass != null) { 94 return(superclass.getAttribute(attrName)); 95 } else { 96 return null; 97 } 98 } 99 100 102 AttributeSpec findSimilarAttribute(String attrName) { 103 for (Iterator iter = attributeSpecs.values().iterator(); iter.hasNext();) { 104 AttributeSpec attr = (AttributeSpec) iter.next(); 105 if ((attrName.toLowerCase().equals(attr.name.toLowerCase())) || 106 (attrName.toLowerCase().startsWith(attr.name.toLowerCase())) || 107 (attrName.toLowerCase().endsWith(attr.name.toLowerCase())) || 108 (attr.name.toLowerCase().startsWith(attrName.toLowerCase())) || 109 (attr.name.toLowerCase().endsWith(attrName.toLowerCase()))) { 110 return attr; 111 } 112 } 113 if (superclass == null) { 115 return null; 116 } else { 117 return superclass.findSimilarAttribute(attrName); 118 } 119 } 120 121 ViewSchema.Type getAttributeTypeOrException(String attrName) 122 throws UnknownAttributeException 123 { 124 AttributeSpec attr = getAttribute(attrName); 125 if (attr != null) { 126 return attr.type; 127 } 128 ViewSchema.Type type = ViewSchema.getAttributeType(attrName); 131 if (type == null) { 133 throw new UnknownAttributeException(); 134 } 135 return type; 136 } 137 138 ViewSchema.Type getAttributeType(String attrName) { 139 AttributeSpec attr = getAttribute(attrName); 140 if (attr != null) { 141 return attr.type; 142 } 143 ViewSchema.Type type = ViewSchema.getAttributeType(attrName); 146 if (type == null) { 148 type = ViewSchema.EXPRESSION_TYPE; 149 } 150 return type; 151 } 152 153 void setNodeModel(NodeModel model) { 154 this.nodeModel = model; 155 } 156 157 boolean getInline() { 158 return inline && nodeModel != null; 159 } 160 161 void setInline(boolean inline) { 162 this.inline = inline; 163 } 164 165 public static class InlineClassError extends CompilationError { 166 public InlineClassError(ClassModel cm, NodeModel im, String message) { 167 super( 168 "The class " + cm.className + " has been declared " + 169 "inline-only but cannot be inlined. " + message + ". " + 170 "Remove " + cm.className + " from the <?lzc class=\"" + 171 cm.className + "\"> or " + "<?lzc classes=\"" + cm.className 172 + "\"> processing instruction to remove this error.", 173 im.element); 174 } 175 } 176 177 protected boolean descendantDefinesAttribute(NodeModel model, String name) { 178 for (Iterator iter = model.getChildren().iterator(); iter.hasNext(); ) { 179 NodeModel child = (NodeModel) iter.next(); 180 if (child.hasAttribute(name) || descendantDefinesAttribute(child, name)) 181 return true; 182 } 183 return false; 184 } 185 186 NodeModel applyClass(NodeModel instance) { 187 final String DEFAULTPLACEMENT_ATTR_NAME = "defaultPlacement"; 188 final String PLACEMENT_ATTR_NAME = "placement"; 189 if (nodeModel == null) throw new RuntimeException ("no nodeModel for " + className); 190 if (nodeModel.hasAttribute(DEFAULTPLACEMENT_ATTR_NAME)) 191 throw new InlineClassError(this, instance, "The class has a " + DEFAULTPLACEMENT_ATTR_NAME + " attribute"); 192 if (instance.hasAttribute(DEFAULTPLACEMENT_ATTR_NAME)) 193 throw new InlineClassError(this, instance, "The instance has a " + DEFAULTPLACEMENT_ATTR_NAME + " attribute"); 194 if (descendantDefinesAttribute(instance, PLACEMENT_ATTR_NAME)) 195 throw new InlineClassError(this, instance, "An element within the instance has a " + PLACEMENT_ATTR_NAME + " attribute"); 196 197 try { 198 NodeModel model = (NodeModel) nodeModel.clone(); 200 setChildrenClassRootDepth(model, 1); 203 model.updateMembers(instance); 204 model.setClassName(getSuperclassName()); 205 return model; 206 } catch (CompilationError e) { 207 throw new InlineClassError(this, instance, e.getMessage()); 208 } 209 } 210 211 protected void setChildrenClassRootDepth(NodeModel model, int depth) { 212 final String CLASSROOTDEPTH_ATTRIBUTE_NAME = "$classrootdepth"; 213 for (Iterator iter = model.getChildren().iterator(); iter.hasNext(); ) { 214 NodeModel child = (NodeModel) iter.next(); 215 if (child.hasAttribute(CLASSROOTDEPTH_ATTRIBUTE_NAME)) 219 continue; 220 child.setAttribute(CLASSROOTDEPTH_ATTRIBUTE_NAME, 221 new Integer (depth)); 222 int childDepth = depth; 223 ClassModel childModel = child.getClassModel(); 224 if (childModel != null && childModel.isSubclassOf(schema.getClassModel("state"))) 229 childDepth++; 230 setChildrenClassRootDepth(child, childDepth); 231 } 232 } 233 } 234 | Popular Tags |