public List<String> write() {
   List<String> lines = new ArrayList<String>();
   StringBuilder out = new StringBuilder();
   for (Entry<String, Attribute> attribute : attributes.entrySet()) {
     out.append(attribute.getKey()).append(": ");
     Attribute attributeValue = attribute.getValue();
     if (attributeValue.size() > 1) {
       lines.add(out.toString());
       out.setLength(0);
       for (int i = 0; i < attributeValue.size(); i++) {
         Value value = attributeValue.get(i);
         out.append(" ");
         value.toString(out);
         if (i + 1 < attributeValue.size()) {
           out.append(",");
         }
         lines.add(out.toString());
         out.setLength(0);
       }
     } else {
       attributeValue.toString("", out);
       lines.add(out.toString());
       out.setLength(0);
     }
   }
   return lines;
 }
  private void encodeV2Attributes(
      ByteStringBuilder buffer,
      Map<AttributeType, List<Attribute>> attributes,
      EntryEncodeConfig config)
      throws DirectoryException {
    int numAttributes = 0;

    // First count how many attributes are there to encode.
    for (List<Attribute> attrList : attributes.values()) {
      for (Attribute a : attrList) {
        if (a.isVirtual() || a.isEmpty()) {
          continue;
        }

        numAttributes++;
      }
    }

    // Encoded one-to-five byte number of attributes
    buffer.appendBERLength(numAttributes);

    if (config.compressAttributeDescriptions()) {
      for (List<Attribute> attrList : attributes.values()) {
        for (Attribute a : attrList) {
          if (a.isVirtual() || a.isEmpty()) {
            continue;
          }

          ByteStringBuilder bsb = new ByteStringBuilder();
          config.getCompressedSchema().encodeAttribute(bsb, a);
          buffer.appendBERLength(bsb.length());
          buffer.append(bsb);
        }
      }
    } else {
      // The attributes will be encoded as a sequence of:
      // - A UTF-8 byte representation of the attribute name.
      // - A zero delimiter
      // - A one-to-five byte number of values for the attribute
      // - A sequence of:
      //   - A one-to-five byte length for the value
      //   - A UTF-8 byte representation for the value
      for (List<Attribute> attrList : attributes.values()) {
        for (Attribute a : attrList) {
          byte[] nameBytes = getBytes(a.getNameWithOptions());
          buffer.append(nameBytes);
          buffer.append((byte) 0x00);

          buffer.appendBERLength(a.size());
          for (AttributeValue v : a) {
            buffer.appendBERLength(v.getValue().length());
            buffer.append(v.getValue());
          }
        }
      }
    }
  }
 private Integer getIntegerUserAttribute(
     Entry userEntry,
     String attributeTypeName,
     Arg1<Object> nonUniqueAttributeMessage,
     Arg2<Object, Object> cannotProcessAttributeMessage) {
   AttributeType attrType = DirectoryServer.getAttributeTypeOrDefault(attributeTypeName);
   List<Attribute> attrList = userEntry.getAttribute(attrType);
   if (attrList != null && attrList.size() == 1) {
     Attribute a = attrList.get(0);
     if (a.size() == 1) {
       ByteString v = a.iterator().next();
       try {
         return Integer.valueOf(v.toString());
       } catch (Exception e) {
         logger.traceException(e);
         logger.error(cannotProcessAttributeMessage.get(v, userEntry.getName()));
       }
     } else if (a.size() > 1) {
       logger.error(nonUniqueAttributeMessage.get(userEntry.getName()));
     }
   }
   return null;
 }
  /**
   * The attributes will be encoded as a sequence of: - A UTF-8 byte representation of the attribute
   * name. - A zero delimiter - A one-to-five byte number of values for the attribute - A sequence
   * of: - A one-to-five byte length for the value - A UTF-8 byte representation for the value
   */
  private void append(ByteStringBuilder buffer, Map<AttributeType, List<Attribute>> attributes) {
    for (List<Attribute> attrList : attributes.values()) {
      for (Attribute a : attrList) {
        byte[] nameBytes = getBytes(a.getNameWithOptions());
        buffer.appendBytes(nameBytes);
        buffer.appendByte(0x00);

        buffer.appendBERLength(a.size());
        for (ByteString v : a) {
          buffer.appendBERLength(v.length());
          buffer.appendBytes(v);
        }
      }
    }
  }
  /**
   * Returns a pair consisting of a MarshalledObject and attributes to be bound with the stub.
   *
   * @param obj The non-null object to store.
   * @param inAttrs The possible null attributes to store with object.
   * @return A non-null Result consisting of the MarshalledObject and attributes.
   */
  private static DirStateFactory.Result jrmpObject(Object obj, Attributes inAttrs)
      throws NamingException {
    try {
      Object mobj = new MarshalledObject(obj);

      Attributes outAttrs = null;
      Attribute cname = null;
      Attribute tnames = null;
      Attribute objectClass = null;

      if (inAttrs != null) {
        // Get existing objectclass attribute
        objectClass = (Attribute) inAttrs.get("objectClass");
        if (objectClass == null && !inAttrs.isCaseIgnored()) {
          // %%% workaround
          objectClass = (Attribute) inAttrs.get("objectclass");
        }

        // No objectclasses supplied, use "top" to start
        if (objectClass == null) {
          objectClass = new BasicAttribute("objectClass", "top");
        } else {
          objectClass = (Attribute) objectClass.clone();
        }

        cname = inAttrs.get(CLASSNAME_ATTRID);
        tnames = inAttrs.get(CLASSNAMES_ATTRID);

        outAttrs = (Attributes) inAttrs.clone();
      } else {
        outAttrs = new BasicAttributes(true);
        objectClass = new BasicAttribute("objectClass", "top");
      }

      if (cname == null) {
        outAttrs.put(CLASSNAME_ATTRID, obj.getClass().getName());
      }
      if (tnames == null) {
        Attribute tAttr = LdapCtxFactory.createTypeNameAttr(obj.getClass());
        if (tAttr != null) {
          outAttrs.put(tAttr);
        }
      }

      boolean structural =
          (objectClass.size() == 0 || (objectClass.size() == 1 && objectClass.contains("top")));

      if (structural) {
        objectClass.add(STRUCTURAL_OCID);
      }
      objectClass.add(MARSHALLED_OCID);
      outAttrs.put(objectClass);

      return new DirStateFactory.Result(mobj, outAttrs);

    } catch (java.io.IOException e) {
      NamingException ne = new NamingException("Cannot create MarshallObject for " + obj);
      ne.setRootCause(e);
      throw ne;
    }
  }