1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.ddmlib.log;
18
19import com.android.ddmlib.log.EventContainer.EventValueType;
20
21import java.util.Locale;
22
23
24/**
25 * Describes an {@link EventContainer} value.
26 * <p/>
27 * This is a stand-alone object, not linked to a particular Event. It describes the value, by
28 * name, type ({@link EventValueType}), and (if needed) value unit ({@link ValueType}).
29 * <p/>
30 * The index of the value is not contained within this class, and is instead dependent on the
31 * index of this particular object in the array of {@link EventValueDescription} returned by
32 * {@link EventLogParser#getEventInfoMap()} when queried for a particular event tag.
33 *
34 */
35public final class EventValueDescription {
36
37    /**
38     * Represents the type of a numerical value. This is used to display values of vastly different
39     * type/range in graphs.
40     */
41    public static enum ValueType {
42        NOT_APPLICABLE(0),
43        OBJECTS(1),
44        BYTES(2),
45        MILLISECONDS(3),
46        ALLOCATIONS(4),
47        ID(5),
48        PERCENT(6);
49
50        private int mValue;
51
52        /**
53         * Checks that the {@link EventValueType} is compatible with the {@link ValueType}.
54         * @param type the {@link EventValueType} to check.
55         * @throws InvalidValueTypeException if the types are not compatible.
56         */
57        public void checkType(EventValueType type) throws InvalidValueTypeException {
58            if ((type != EventValueType.INT && type != EventValueType.LONG)
59                    && this != NOT_APPLICABLE) {
60                throw new InvalidValueTypeException(
61                        String.format("%1$s doesn't support type %2$s", type, this));
62            }
63        }
64
65        /**
66         * Returns a {@link ValueType} from an integer value, or <code>null</code> if no match
67         * were found.
68         * @param value the integer value.
69         */
70        public static ValueType getValueType(int value) {
71            for (ValueType type : values()) {
72                if (type.mValue == value) {
73                    return type;
74                }
75            }
76            return null;
77        }
78
79        /**
80         * Returns the integer value of the enum.
81         */
82        public int getValue() {
83            return mValue;
84        }
85
86        @Override
87        public String toString() {
88            return super.toString().toLowerCase(Locale.US);
89        }
90
91        private ValueType(int value) {
92            mValue = value;
93        }
94    }
95
96    private String mName;
97    private EventValueType mEventValueType;
98    private ValueType mValueType;
99
100    /**
101     * Builds a {@link EventValueDescription} with a name and a type.
102     * <p/>
103     * If the type is {@link EventValueType#INT} or {@link EventValueType#LONG}, the
104     * {@link #mValueType} is set to {@link ValueType#BYTES} by default. It set to
105     * {@link ValueType#NOT_APPLICABLE} for all other {@link EventValueType} values.
106     * @param name
107     * @param type
108     */
109    EventValueDescription(String name, EventValueType type) {
110        mName = name;
111        mEventValueType = type;
112        if (mEventValueType == EventValueType.INT || mEventValueType == EventValueType.LONG) {
113            mValueType = ValueType.BYTES;
114        } else {
115            mValueType = ValueType.NOT_APPLICABLE;
116        }
117    }
118
119    /**
120     * Builds a {@link EventValueDescription} with a name and a type, and a {@link ValueType}.
121     * <p/>
122     * @param name
123     * @param type
124     * @param valueType
125     * @throws InvalidValueTypeException if type and valuetype are not compatible.
126     *
127     */
128    EventValueDescription(String name, EventValueType type, ValueType valueType)
129            throws InvalidValueTypeException {
130        mName = name;
131        mEventValueType = type;
132        mValueType = valueType;
133        mValueType.checkType(mEventValueType);
134    }
135
136    /**
137     * @return the Name.
138     */
139    public String getName() {
140        return mName;
141    }
142
143    /**
144     * @return the {@link EventValueType}.
145     */
146    public EventValueType getEventValueType() {
147        return mEventValueType;
148    }
149
150    /**
151     * @return the {@link ValueType}.
152     */
153    public ValueType getValueType() {
154        return mValueType;
155    }
156
157    @Override
158    public String toString() {
159        if (mValueType != ValueType.NOT_APPLICABLE) {
160            return String.format("%1$s (%2$s, %3$s)", mName, mEventValueType.toString(),
161                    mValueType.toString());
162        }
163
164        return String.format("%1$s (%2$s)", mName, mEventValueType.toString());
165    }
166
167    /**
168     * Checks if the value is of the proper type for this receiver.
169     * @param value the value to check.
170     * @return true if the value is of the proper type for this receiver.
171     */
172    public boolean checkForType(Object value) {
173        switch (mEventValueType) {
174            case INT:
175                return value instanceof Integer;
176            case LONG:
177                return value instanceof Long;
178            case STRING:
179                return value instanceof String;
180            case LIST:
181                return value instanceof Object[];
182        }
183
184        return false;
185    }
186
187    /**
188     * Returns an object of a valid type (based on the value returned by
189     * {@link #getEventValueType()}) from a String value.
190     * <p/>
191     * IMPORTANT {@link EventValueType#LIST} and {@link EventValueType#TREE} are not
192     * supported.
193     * @param value the value of the object expressed as a string.
194     * @return an object or null if the conversion could not be done.
195     */
196    public Object getObjectFromString(String value) {
197        switch (mEventValueType) {
198            case INT:
199                try {
200                    return Integer.valueOf(value);
201                } catch (NumberFormatException e) {
202                    return null;
203                }
204            case LONG:
205                try {
206                    return Long.valueOf(value);
207                } catch (NumberFormatException e) {
208                    return null;
209                }
210            case STRING:
211                return value;
212        }
213
214        return null;
215    }
216}
217