if (requiredIn != null || optionalIn != null) { if (requiredIn != null) for (AttributeClass klass : requiredIn) mClassToAttrsMap.get(klass).add(name); if (optionalIn != null) for (AttributeClass klass : optionalIn) mClassToAttrsMap.get(klass).add(name); }
    private void loadAttrs(File file) throws DocumentException {        SAXReader reader = new SAXReader();        Document doc = reader.read(file);        Element root = doc.getRootElement();        if (!root.getName().equals(E_ATTRS)) {            error(null, file, "root tag is not " + E_ATTRS);            return;        }        String group = root.attributeValue(A_GROUP);        String groupIdStr = root.attributeValue(A_GROUP_ID);        if (group == null ^ groupIdStr == null) {            error(null, file, A_GROUP + " and " + A_GROUP_ID + " both have to be both specified");        }        int groupId = -1;        if (group != null) {            try {                groupId = Integer.valueOf(groupIdStr);            } catch (NumberFormatException nfe) {                error(null, file, A_GROUP_ID + " is not a number: " + groupIdStr);            }        }        if (groupId == 2) {            error(null, file, A_GROUP_ID + " is not valid (used by ZimbraObjectClass)");        } else if (groupId > 0) {            if (mGroupMap.containsKey(groupId)) {                error(null, file, "duplicate group id: " + groupId);            } else if (mGroupMap.containsValue(group)) {                error(null, file, "duplicate group: " + group);            } else {                mGroupMap.put(groupId, group);            }        }                NEXT_ATTR: for (Iterator iter = root.elementIterator(); iter.hasNext();) {            Element eattr = (Element) iter.next();            if (!eattr.getName().equals(E_ATTR)) {                error(null, file, "unknown element: " + eattr.getName());                continue;            }            AttributeCallback callback = null;            AttributeType type = null;            AttributeOrder order = null;            String value = null;            long min = Long.MIN_VALUE;            long max = Long.MAX_VALUE;            boolean immutable = false;//            boolean ignore = false;            int id = -1;            String parentOid = null;            AttributeCardinality cardinality = null;            Set<AttributeClass> requiredIn = null;            Set<AttributeClass> optionalIn = null;            Set<AttributeFlag> flags = null;            String canonicalName = null;            String name = eattr.attributeValue(A_NAME);            if (name == null) {                error(null, file, "no name specified");                continue;            }            canonicalName = name.toLowerCase();            for (Iterator attrIter = eattr.attributeIterator(); attrIter.hasNext();) {                Attribute attr = (Attribute) attrIter.next();                String aname = attr.getName();                if (aname.equals(A_NAME)) {                    // nothing to do - already processed                } else if (aname.equals(A_CALLBACK)) {                    callback = loadCallback(attr.getValue());                } else if (aname.equals(A_IMMUTABLE)) {                    immutable = "1".equals(attr.getValue());                } else if (aname.equals(A_MAX)) {                    max = AttributeInfo.parseLong(attr.getValue(), Integer.MAX_VALUE);                } else if (aname.equals(A_MIN)) {                    min = AttributeInfo.parseLong(attr.getValue(), Integer.MIN_VALUE);                } else if (aname.equals(A_TYPE)) {                    type = AttributeType.getType(attr.getValue());                    if (type == null) {                        error(name, file, "unknown <attr> type: " + attr.getValue());                        continue NEXT_ATTR;                    }                } else if (aname.equals(A_VALUE)) {                     value = attr.getValue();                } else if (aname.equals(A_PARENT_OID)) {                    parentOid = attr.getValue();                    if (!parentOid.matches("^\\d+(\\.\\d+)+"))                         error(name, file, "invalid parent OID " + parentOid + ": must be an OID");                } else if (aname.equals(A_ID)) {                    try {                        id = Integer.parseInt(attr.getValue());                        if (id < 0)  {                            error(name, file, "invalid id " + id + ": must be positive");                        }                    } catch (NumberFormatException nfe) {                        error(name, file, aname + " is not a number: " + attr.getValue());                    }                } else if (aname.equals(A_CARDINALITY)) {                    try {                        cardinality = AttributeCardinality.valueOf(attr.getValue());                    } catch (IllegalArgumentException iae) {                        error(name, file, aname + " is not valid: " + attr.getValue());                    }                } else if (aname.equals(A_REQUIRED_IN)) {                    requiredIn = parseClasses(name, file, attr.getValue());                } else if (aname.equals(A_OPTIONAL_IN)) {                    optionalIn = parseClasses(name, file, attr.getValue());                } else if (aname.equals(A_FLAGS)) {                    flags = parseFlags(name, file, attr.getValue());                } else if (aname.equals(A_ORDER)) {                	try {                		order = AttributeOrder.valueOf(attr.getValue());                	} catch (IllegalArgumentException iae) {                        error(name, file, aname + " is not valid: " + attr.getValue());                	}                } else {                    error(name, file, "unknown <attr> attr: " + aname);                }            }            List<String> globalConfigValues = new LinkedList<String>();            List<String> defaultCOSValues = new LinkedList<String>();            String description = null;            for (Iterator elemIter = eattr.elementIterator(); elemIter.hasNext();) {                Element elem = (Element)elemIter.next();                if (elem.getName().equals(E_GLOBAL_CONFIG_VALUE)) {                    globalConfigValues.add(elem.getText());                } else if (elem.getName().equals(E_DEFAULT_COS_VALUE)) {                    defaultCOSValues.add(elem.getText());                } else if (elem.getName().equals(E_DESCRIPTION)) {                    if (description != null) {                        error(name, file, "more than one description");                    }                    description = elem.getText();                } else {                    error(name, file, "unknown element: " + elem.getName());                }            }            // Check that if id is specified, then cardinality is specified.            if (id > 0  && cardinality == null) {                error(name, file, "cardinality not specified");            }                        // Check that if id is specified, then atleast one object class is            // defined            if (id > 0 && (optionalIn != null && optionalIn.isEmpty()) && (requiredIn != null && requiredIn.isEmpty())) {                error(name, file, "atleast one of " + A_REQUIRED_IN + " or " + A_OPTIONAL_IN + " must be specified");            }            // Check that if it is COS inheritable it is in account and COS            // classes            checkFlag(name, file, flags, AttributeFlag.accountInherited, AttributeClass.account, AttributeClass.cos, requiredIn, optionalIn);            // Check that if it is domain inheritable it is in domain and            // account            checkFlag(name, file, flags, AttributeFlag.domainInherited, AttributeClass.account, AttributeClass.domain, requiredIn, optionalIn);            // Check that if it is domain inheritable it is in domain and            // account            checkFlag(name, file, flags, AttributeFlag.serverInherited, AttributeClass.server, AttributeClass.globalConfig, requiredIn, optionalIn);            // Check that is cardinality is single, then not more than one            // default value is specified            if (cardinality == AttributeCardinality.single) {                if (globalConfigValues.size() > 1) {                    error(name, file, "more than one global config value specified for cardinality " + AttributeCardinality.single);                }                if (defaultCOSValues.size() > 1) {                    error(name, file, "more than one default COS value specified for cardinality " + AttributeCardinality.single);                }            }            AttributeInfo info = new AttributeInfo(name, id, parentOid, groupId, callback, type, order, value, immutable, min, max, cardinality, requiredIn, optionalIn, flags, globalConfigValues, defaultCOSValues, description);            if (mAttrs.get(canonicalName) != null) {                error(name, file, "duplicate definiton");            }            mAttrs.put(canonicalName, info);            if (flags != null) {            	for (AttributeFlag flag : flags) {            		mFlagToAttrsMap.get(flag).add(name);            	}            }        }    }