📄 propertydefinition.java
字号:
* @return <code>true</code> if implicit, <code>false</code> if not */ public boolean isImplicit() { return m_isImplicit; } /** * Switch property from "this" to "implicit". */ public void switchProperty() { m_isThis = false; m_isImplicit = true; } /** * Check if property is optional. * * @return <code>true</code> if optional, <code>false</code> if required */ public boolean isOptional() { return m_isOptional; } /** * Set flag for an optional property. * * @param opt <code>true</code> if optional property, <code>false</code> if * not */ public void setOptional(boolean opt) { m_isOptional = opt; } /** * Get property name. If a field is defined this is the same as the field; * otherwise it is either the get method name (with leading "get" stripped, * if present) or the set method (with leading "set" stripped, if present), * whichever is found. * * @return name for this property */ public String getName() { if (m_isThis) { return "this"; } else if (m_fieldItem != null) { return m_fieldItem.getName(); } else if (m_getMethod != null) { String name = m_getMethod.getName(); if (name.startsWith("get") && name.length() > 3) { name = name.substring(3); } return name; } else if (m_setMethod != null) { String name = m_setMethod.getName(); if (name.startsWith("set") && name.length() > 3) { name = name.substring(3); } return name; } else { return "item"; } } /** * Get declared type fully qualified name. * * @return fully qualified class name of declared type */ public String getTypeName() { return m_typeName; } /** * Get value type as fully qualified name for loaded property value. * * @return fully qualified class name of value type */ public String getGetValueType() { return m_getValueType; } /** * Get value type as fully qualified name for stored property value. * * @return fully qualified class name of value type */ public String getSetValueType() { return m_setValueType; } /** * Check if property has presence test. Code needs to be generated to check * for the presence of the property if it is optional and either a test * method is defined or the value is an object reference. * * @return <code>true</code> if presence test needed, <code>false</code> if * not */ public boolean hasTest() { return isOptional() && !isImplicit() && (m_testMethod != null || !ClassItem.isPrimitive(m_typeName)); } /** * Generate code to test if property is present. The generated code * assumes that the top of the stack is the reference for the containing * object, and consumes this value for the test. The target for the * returned branch instruction must be set by the caller. * * @param mb method builder * @return wrapper for branch instruction taken when property is missing */ public BranchWrapper genTest(ContextMethodBuilder mb) { // first check for supplied test method if (m_testMethod != null) { // generate call to test method to check for property present mb.addMethodExceptions(m_testMethod); if (m_testMethod.isStatic()) { mb.appendPOP(); } if (m_testMethod.getArgumentCount() > 0) { mb.loadContext(); } mb.appendCall(m_testMethod); return mb.appendIFEQ(this); } else if (!m_isThis && !m_isImplicit && !ClassItem.isPrimitive(m_typeName)) { // generated instruction either loads a field value or calls a "get" // method, as appropriate if (m_getMethod == null) { if (m_fieldItem.isStatic()) { mb.appendPOP(); } mb.appendGet(m_fieldItem); } else { if (m_getMethod.isStatic()) { mb.appendPOP(); } if (m_getMethod.getArgumentCount() > 0) { mb.loadContext(); } mb.addMethodExceptions(m_getMethod); mb.appendCall(m_getMethod); } return mb.appendIFNULL(this); } else { return null; } } /** * Generate code to load property value to stack. The generated code * assumes that the top of the stack is the reference for the containing * object. It consumes this and leaves the actual value on the stack. If * the property value is not directly accessible from the context of the * method being generated this automatically constructs an access method * and uses that method. * * @param mb method builder * @throws JiBXException if configuration error */ public void genLoad(ContextMethodBuilder mb) throws JiBXException { // nothing to be done if called on "this" or implicit reference if (!m_isThis && !m_isImplicit) { // first check direct access to property from method class ClassFile from = mb.getClassFile(); ClassItem access = m_getMethod; if (access == null) { access = m_fieldItem; } if (access != null && !from.isAccessible(access)) { access = m_objContext.getBoundClass(). getLoadMethod(access, mb.getClassFile()); } // generated instruction either loads a field value or calls a "get" // method, as appropriate if (access == null) { Integer index = (Integer)mb.getKeyValue(m_setMethod); mb.appendPOP(); if (index == null) { mb.appendACONST_NULL(); } else { mb.appendLoadLocal(index.intValue()); } } else { if (access.isStatic()) { mb.appendPOP(); } if (access.isMethod()) { if (access.getArgumentCount() > 0) { mb.loadContext(); } mb.addMethodExceptions(access); mb.appendCall(access); } else { mb.appendGet(access); } } // cast value if necessary to assure correct type mb.appendCreateCast(m_getValueType, m_typeName); } } /** * Generate code to store property value from stack. The generated code * assumes that the reference to the containing object and the value to be * stored have already been pushed on the stack. It consumes these, leaving * nothing. If the property value is not directly accessible from the * context of the method being generated this automatically constructs an * access method and uses that method. * * @param mb method builder * @throws JiBXException if configuration error */ public void genStore(MethodBuilder mb) throws JiBXException { // check for cast needed to convert to actual type if (!ClassItem.isPrimitive(m_setValueType)) { mb.appendCreateCast(m_setValueType); } // nothing to be done if called on "this" or implicit reference if (!m_isThis && !m_isImplicit) { // first check direct access to property from method class ClassFile from = mb.getClassFile(); ClassItem access = m_setMethod; if (access == null) { access = m_fieldItem; } if (!from.isAccessible(access)) { access = m_objContext.getBoundClass(). getStoreMethod(access, mb.getClassFile()); } // save to local if no way of getting value if (m_getMethod == null && m_fieldItem == null) { mb.appendDUP(); Integer index = (Integer)mb.getKeyValue(m_setMethod); if (index == null) { int slot = mb.addLocal(null, ClassItem.typeFromName(m_typeName)); index = IntegerCache.getInteger(slot); mb.setKeyValue(m_setMethod, index); } else { mb.appendStoreLocal(index.intValue()); } } // generated instruction either stores a field value or calls a // "set" method, as appropriate if (access.isMethod()) { if (access.getArgumentCount() > 1) { // this test is ugly, needed because of backfill method // calls from ValueChild if (mb instanceof ContextMethodBuilder) { ((ContextMethodBuilder)mb).loadContext(); } else { mb.appendACONST_NULL(); } } mb.addMethodExceptions(access); mb.appendCall(access); } else { mb.appendPut(access); } if (access.isStatic()) { mb.appendPOP(); } } } // DEBUG public String toString() { StringBuffer text = new StringBuffer(); if (m_isOptional) { text.append("optional "); } text.append("property "); if (m_isThis) { text.append("\"this\" "); } else if (m_isImplicit) { text.append("from collection "); } else if (m_fieldItem != null) { text.append(m_fieldItem.getName() + " "); } else { if (m_getMethod != null) { text.append("from " + m_getMethod.getName() + " "); } if (m_setMethod != null) { text.append("to " + m_setMethod.getName() + " "); } } if (m_typeName != null) { text.append( "("+ m_typeName + ")"); } return text.toString(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -