PtsPrimitiveSerializer.java
上传用户:szyujian
上传日期:2016-09-20
资源大小:320k
文件大小:21k
源码类别:
android开发
开发平台:
C/C++
- /*
- * Copyright (C) 2007-2008 Esmertec AG.
- * Copyright (C) 2007-2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.android.im.imps;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.io.OutputStreamWriter;
- import java.io.Writer;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import com.android.im.imps.ImpsConstants.ImpsVersion;
- public class PtsPrimitiveSerializer implements PrimitiveSerializer {
- private final String mPreampleHead;
- // The ccc is the Transaction-ID in range 0-999 without preceding zero.
- private static final Pattern sTxIdPattern = Pattern.compile("(0|[1-9]\d{0,2})");
- // If the value of the parameter contains spaces ( ), quotes ("),
- // commas (,),parentheses (()),equal (=) or ampersand (&) characters,
- // it SHALL be wrapped with quotes (").
- private static final Pattern sCharsToBeQuoted = Pattern.compile("[ ",\(\)=&]");
- public PtsPrimitiveSerializer(ImpsVersion impsVersion) throws SerializerException {
- if (impsVersion == ImpsVersion.IMPS_VERSION_12) {
- mPreampleHead = "WV12";
- } else if (impsVersion == ImpsVersion.IMPS_VERSION_13) {
- mPreampleHead = "WV13";
- } else {
- throw new SerializerException("Unsupported IMPS version");
- }
- }
- public void serialize(Primitive p, OutputStream out)
- throws IOException, SerializerException {
- String txId = p.getTransactionID();
- if (txId == null) {
- if (!ImpsTags.Polling_Request.equals(p.getType())) {
- throw new SerializerException("null Transaction-ID for non polling request");
- }
- // FIXME: what should this be? Temporarily use 0
- txId = "0";
- } else {
- Matcher m = sTxIdPattern.matcher(txId);
- if (!m.matches()) {
- throw new SerializerException(
- "Transaction-ID must be in range 0-999 without preceding zero");
- }
- }
- // TODO: use buffered writer?
- Writer writer = new OutputStreamWriter(out, "UTF-8");
- writer.write(mPreampleHead);
- String code = PtsCodes.getTxCode(p.getType());
- if (code == null) {
- throw new SerializerException("Unsupported transaction type "
- + p.getType());
- }
- writer.write(code);
- writer.write(txId);
- if (p.getSessionId() != null) {
- writer.write(" SI=");
- writer.write(p.getSessionId());
- }
- PrimitiveElement content = p.getContentElement();
- if (content != null && content.getChildCount() > 0) {
- ArrayList<PrimitiveElement> infoElems = content.getChildren();
- ArrayList<String> users = new ArrayList<String>();
- ArrayList<String> lists = new ArrayList<String>();
- int len = infoElems.size();
- for (int i = 0; i < len; i++) {
- PrimitiveElement elem = infoElems.get(i);
- String elemName = elem.getTagName();
- // workaround for multiple elements
- if (ImpsTags.User.equals(elemName)) {
- users.add(elem.getChildContents(ImpsTags.UserID));
- continue;
- } else if (ImpsTags.UserID.equals(elemName)) {
- users.add(elem.getContents());
- continue;
- } else if (ImpsTags.ContactList.equals(elemName)) {
- lists.add(elem.getContents());
- continue;
- }
- String elemCode = PtsCodes.getElementCode(elemName, p.getType());
- if (elemCode == null) {
- throw new SerializerException("Don't know how to encode element "
- + elemName);
- }
- writer.write(' ');
- writer.write(elemCode);
- // so far all top level information elements have values.
- writer.write('=');
- String value;
- ElemValueEncoder encoder = ElemValueEncoder.getEncoder(elemName);
- if (encoder == null) {
- // default simple value
- value = escapeValueString(elem.getContents());
- } else {
- value = encoder.encodeValue(p, elem);
- }
- if (value == null) {
- throw new SerializerException("Empty value for element "
- + elemName);
- }
- writer.write(value);
- }
- writeMultiValue(writer, PtsCodes.getElementCode(ImpsTags.UserID, p.getType()), users);
- writeMultiValue(writer, PtsCodes.getElementCode(ImpsTags.ContactList, p.getType()), lists);
- }
- writer.close();
- }
- private void writeMultiValue(Writer writer, String code, ArrayList<String> values)
- throws IOException {
- if (values.size() == 0) {
- return;
- }
- writer.write(' ');
- writer.write(code);
- writer.write('=');
- if (values.size() == 1) {
- writer.write(escapeValueString(values.get(0)));
- } else {
- writer.write('(');
- int valueCount = values.size();
- for (int i = 0; i < valueCount; i++) {
- if (i > 0) {
- writer.write(',');
- }
- writer.write(escapeValueString(values.get(i)));
- }
- writer.write(')');
- }
- }
- static String escapeValueString(String contents) {
- Matcher m = sCharsToBeQuoted.matcher(contents);
- if (m.find()) {
- if (contents.indexOf('"') != -1) {
- contents = contents.replace(""", """");
- }
- return """ + contents + """;
- }
- return contents;
- }
- static void appendPairValue(StringBuilder buf, String first, String second) {
- buf.append('(');
- if (first != null) {
- buf.append(first);
- }
- buf.append(',');
- buf.append(second);
- buf.append(')');
- }
- /**
- * Appends a name and value pair like "(<name>,<value>)".
- */
- static boolean appendNameAndValue(StringBuilder buf, String name, String value,
- HashMap<String, String> nameCodes, HashMap<String, String> valueCodes,
- boolean ignoreUnsupportedValue) {
- String nameCode = nameCodes.get(name);
- if (nameCode == null) {
- ImpsLog.log("PTS: Ignoring value " + name);
- return false;
- }
- String valueCode = null;
- if (valueCodes != null) {
- valueCode = valueCodes.get(value);
- }
- if (valueCode != null) {
- value = valueCode;
- } else {
- if (ignoreUnsupportedValue) {
- return false;
- }
- value = escapeValueString(value);
- }
- appendPairValue(buf, nameCode, value);
- return true;
- }
- static abstract class ElemValueEncoder {
- public abstract String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException;
- public static ElemValueEncoder getEncoder(String elemName) {
- return sEncoders.get(elemName);
- }
- private static HashMap<String, ElemValueEncoder> sEncoders;
- static {
- sEncoders = new HashMap<String, ElemValueEncoder>();
- sEncoders.put(ImpsTags.ClientID, new ClientIdEncoder());
- sEncoders.put(ImpsTags.CapabilityList, new CapabilityEncoder());
- sEncoders.put(ImpsTags.Functions, new ServiceTreeEncoder());
- sEncoders.put(ImpsTags.Result, new ResultEncoder());
- sEncoders.put(ImpsTags.ContactListProperties, new ProperitiesEncoder(
- PtsCodes.sContactListPropsToCode));
- sEncoders.put(ImpsTags.PresenceSubList, new PresenceSubListEncoder());
- ElemValueEncoder nickListEncoder = new NickListEncoder();
- sEncoders.put(ImpsTags.NickList, nickListEncoder);
- sEncoders.put(ImpsTags.AddNickList, nickListEncoder);
- sEncoders.put(ImpsTags.RemoveNickList, nickListEncoder);
- }
- }
- static class PresenceSubListEncoder extends ElemValueEncoder {
- private boolean mEncodePresenceValue;
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- if (elem.getChildCount() == 0) {
- throw new SerializerException("No presence in the PresenceSubList");
- }
- StringBuilder buf = new StringBuilder();
- mEncodePresenceValue = ImpsTags.UpdatePresence_Request.equals(p.getType());
- ArrayList<PrimitiveElement> presences = elem.getChildren();
- int presenceCount = presences.size();
- if (presenceCount == 1) {
- if (mEncodePresenceValue) {
- // Append an extra pair of braces according to the Spec
- buf.append('(');
- encodePresence(buf, presences.get(0));
- buf.append(')');
- } else {
- encodePresence(buf, presences.get(0));
- }
- } else {
- buf.append('(');
- for (int i = 0; i < presenceCount; i++) {
- if (i > 0) {
- buf.append(',');
- }
- encodePresence(buf, presences.get(i));
- }
- buf.append(')');
- }
- return buf.toString();
- }
- private void encodePresence(StringBuilder buf, PrimitiveElement p)
- throws SerializerException {
- boolean hasQualifier = p.getChild(ImpsTags.Qualifier) != null;
- String presenceName = p.getTagName();
- String presenceNameCode = getPresenceCode(presenceName);
- if (!mEncodePresenceValue) {
- encodeNoValuePresence(buf, p);
- } else {
- buf.append('(');
- buf.append(presenceNameCode);
- buf.append(',');
- if (hasQualifier) {
- buf.append(p.getChildContents(ImpsTags.Qualifier));
- buf.append(',');
- }
- // All the presences with value have this kind of structure:
- // <name, qualifier, value>
- // And for the values, there are three different hierarchies:
- // 1. Simply use PresenceValue to indicate the value, most of the
- // presences has adapted this way. -> SingleValue
- // 2. Use special tags for multiple values of this presence, eg. ClientInfo
- // has adapted this way. -> MultiValue
- // 3. Has one or more children for the presence, and each child have
- // multiple values. eg. CommCap has adapted this way. -> ExtMultiValue
- if (isMultiValuePresence(presenceName)) {
- // condition 2: multiple value
- int emptyValueSize = hasQualifier ? 1 : 0;
- ArrayList<PrimitiveElement> children = p.getChildren();
- if (children.size() > emptyValueSize) {
- buf.append('(');
- int childCount = children.size();
- int j = 0; // used for first value check
- for (int i = 0; i < childCount; i++, j++) {
- PrimitiveElement value = children.get(i);
- if (ImpsTags.Qualifier.equals(value.getTagName())) {
- j--;
- continue;
- }
- if (j > 0) {
- buf.append(',');
- }
- buf.append('(');
- buf.append(getPresenceCode(value.getTagName()));
- buf.append(',');
- buf.append(PtsCodes.getPAValueCode(value.getContents()));
- buf.append(')');
- }
- buf.append(')');
- }
- } else if (isExtMultiValuePresence(presenceName)) {
- // condition 3: extended multiple value
- // TODO: Implementation
- } else {
- // Condition 1: single value
- if (p.getChild(ImpsTags.PresenceValue) == null) {
- throw new SerializerException("Can't find presence value for " + presenceName);
- }
- buf.append(PtsCodes.getPAValueCode(p.getChildContents(ImpsTags.PresenceValue)));
- }
- buf.append(')');
- }
- }
- private void encodeNoValuePresence(StringBuilder buf, PrimitiveElement p)
- throws SerializerException {
- if (p.getChildCount() == 0) {
- buf.append(getPresenceCode(p.getTagName()));
- } else {
- ArrayList<PrimitiveElement> children = p.getChildren();
- int childCount = children.size();
- buf.append('(');
- buf.append(getPresenceCode(p.getTagName()));
- buf.append(",(");
- for (int i = 0; i < childCount; i++) {
- if (i > 0) {
- buf.append(',');
- }
- encodeNoValuePresence(buf, children.get(i));
- }
- buf.append("))");
- }
- }
- private String getPresenceCode(String tagname) throws SerializerException {
- String code = PtsCodes.getPresenceAttributeCode(tagname);
- if (code == null) {
- throw new SerializerException("Unsupport presence attribute: " + tagname);
- }
- return code;
- }
- private boolean isMultiValuePresence(String presenceName) {
- if (ImpsTags.ClientInfo.equals(presenceName)) {
- return true;
- }
- // TODO: Add more supported extended multiple presence here
- return false;
- }
- private boolean isExtMultiValuePresence(String presenceName) {
- // TODO: Add supported extended multiple presence here
- return false;
- }
- }
- static class ClientIdEncoder extends ElemValueEncoder {
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- String value = elem.getChildContents(ImpsTags.URL);
- if (value == null) {
- value = elem.getChildContents(ImpsTags.MSISDN);
- }
- return escapeValueString(value);
- }
- }
- static class CapabilityEncoder extends ElemValueEncoder {
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- ArrayList<PrimitiveElement> caps = elem.getChildren();
- int i, len;
- StringBuilder result = new StringBuilder();
- result.append('(');
- for (i = 0, len = caps.size(); i < len; i++) {
- PrimitiveElement capElem = caps.get(i);
- String capName = capElem.getTagName();
- String capValue = capElem.getContents();
- if (i > 0) {
- result.append(',');
- }
- if (!appendNameAndValue(result, capName, capValue,
- PtsCodes.sCapElementToCode, PtsCodes.sCapValueToCode,
- ImpsTags.SupportedCIRMethod.equals(capName))) {
- result.deleteCharAt(result.length() - 1);
- }
- }
- result.append(')');
- return result.toString();
- }
- }
- static class ServiceTreeEncoder extends ElemValueEncoder {
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- StringBuilder buf = new StringBuilder();
- buf.append('(');
- appendFeature(buf, elem.getFirstChild());
- buf.append(')');
- return buf.toString();
- }
- private void appendFeature(StringBuilder buf, PrimitiveElement elem)
- throws SerializerException {
- int childCount = elem.getChildCount();
- if (childCount > 0) {
- ArrayList<PrimitiveElement> children = elem.getChildren();
- for (int i = 0; i < childCount; i++) {
- appendFeature(buf, children.get(i));
- }
- } else {
- String code = PtsCodes.getServiceTreeCode(elem.getTagName());
- if (code == null) {
- throw new SerializerException("Invalid service tree tag:"
- + elem.getTagName());
- }
- if (buf.length() > 1) {
- buf.append(',');
- }
- buf.append(code);
- }
- }
- }
- static class ResultEncoder extends ElemValueEncoder {
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- String code = elem.getChildContents(ImpsTags.Code);
- String desc = elem.getChildContents(ImpsTags.Description);
- // Client never sends partial success result, the DetailedResult is
- // ignored.
- if (desc == null) {
- return code;
- } else {
- StringBuilder res = new StringBuilder();
- appendPairValue(res, code, escapeValueString(desc));
- return res.toString();
- }
- }
- }
- static class NickListEncoder extends ElemValueEncoder {
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- StringBuilder buf = new StringBuilder();
- ArrayList<PrimitiveElement> children = elem.getChildren();
- int count = children.size();
- buf.append('(');
- for (int i = 0; i < count; i++) {
- PrimitiveElement child = children.get(i);
- String tagName = child.getTagName();
- String nickName = null;
- String userId = null;
- if (tagName.equals(ImpsTags.NickName)) {
- nickName = child.getChildContents(ImpsTags.Name);
- userId = child.getChildContents(ImpsTags.UserID);
- } else if (tagName.equals(ImpsTags.UserID)) {
- userId = child.getContents();
- }
- if (i > 0) {
- buf.append(',');
- }
- if (nickName != null) {
- nickName = escapeValueString(nickName);
- }
- appendPairValue(buf, nickName, escapeValueString(userId));
- }
- buf.append(')');
- return buf.toString();
- }
- }
- static class ProperitiesEncoder extends ElemValueEncoder {
- private HashMap<String, String> mPropNameCodes;
- public ProperitiesEncoder(HashMap<String, String> propNameCodes) {
- mPropNameCodes = propNameCodes;
- }
- @Override
- public String encodeValue(Primitive p, PrimitiveElement elem)
- throws SerializerException {
- ArrayList<PrimitiveElement> props = elem.getChildren();
- StringBuilder result = new StringBuilder();
- result.append('(');
- int count = props.size();
- for (int i = 0; i < count; i++) {
- PrimitiveElement property = props.get(i);
- String name;
- String value;
- if (property.getTagName().equals(ImpsTags.Property)) {
- name = property.getChildContents(ImpsTags.Name);
- value = property.getChildContents(ImpsTags.Value);
- } else {
- name = property.getTagName();
- value = property.getContents();
- }
- if (i > 0) {
- result.append(',');
- }
- appendNameAndValue(result, name, value, mPropNameCodes, null, false);
- }
- result.append(')');
- return result.toString();
- }
- }
- }