14b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki/*
24b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * Copyright (C) 2009 The Android Open Source Project
34b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki *
44b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License");
54b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * you may not use this file except in compliance with the License.
64b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * You may obtain a copy of the License at
74b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki *
84b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki *      http://www.apache.org/licenses/LICENSE-2.0
94b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki *
104b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * Unless required by applicable law or agreed to in writing, software
114b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS,
124b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * See the License for the specific language governing permissions and
144b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * limitations under the License.
154b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki */
164b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1718ffaa2561cc7dd2e3ef81737e6537931c0a9a11Dmitri Plotnikovpackage com.android.contacts.editor;
184b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
194b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onukiimport android.os.Bundle;
204b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onukiimport android.os.Parcel;
214b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onukiimport android.os.Parcelable;
224b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
23851222a96b5d68602fb361ea3527101e893f67e3Maurice Chuimport com.android.contacts.model.RawContactDelta;
24738ff8623dc77dd91a1b9023861e924ba5e4c27eChiao Chengimport com.android.contacts.common.model.ValuesDelta;
25428f008513d1591cc08fcfe2cf0c9237fb313241Chiao Chengimport com.android.contacts.common.model.dataitem.DataKind;
26e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
274b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki/**
284b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * A class that provides unique view ids for {@link ContentEditorView}, {@link KindSectionView},
29392ccec3b56e8074a5a028af28106134b39f64bcDaniel Lehmann * {@link LabeledEditorView} and {@link EditView} on {@link EditContactActivity}.
304b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * It is used to assign a unique but consistent id to each view across {@link EditContactActivity}'s
314b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * lifecycle, so that we can re-construct view state (e.g. focused view) when the screen rotates.
324b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki *
334b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki * <p>This class is not thread safe.
344b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki */
354b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onukipublic final class ViewIdGenerator implements Parcelable {
364b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private static final int INVALID_VIEW_ID = 0;
374b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private static final int INITIAL_VIEW_ID = 1;
384b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
394b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public static final int NO_VIEW_INDEX = -1;
404b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
414b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private int mNextId;
424b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
434b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    /**
444b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * Used as a map from the "key" of the views to actual ids.  {@link #getId()} generates keys for
454b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * the views.
464b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     */
474b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private Bundle mIdMap = new Bundle();
484b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
494b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private static final char KEY_SEPARATOR = '*';
504b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
514b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private final static StringBuilder sWorkStringBuilder = new StringBuilder();
524b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
534b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public ViewIdGenerator() {
544b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        mNextId = INITIAL_VIEW_ID;
554b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
564b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
574b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    /** {@inheritDoc} */
584b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public int describeContents() {
594b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        return 0;
604b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
614b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
624b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    /**
634b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * Returns an id for a view associated with specified contact field.
644b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     *
65851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu     * @param entity {@link RawContactDelta} associated with the view
664b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * @param kind {@link DataKind} associated with the view, or null if none exists.
674b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * @param values {@link ValuesDelta} associated with the view, or null if none exists.
684b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     * @param viewIndex index of the view in the parent {@link Editor}, if it's a leave view.
694b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     *     Otherwise, pass {@link #NO_VIEW_INDEX}.
704b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki     */
71851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    public int getId(RawContactDelta entity, DataKind kind, ValuesDelta values,
724b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            int viewIndex) {
734b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        final String k = getMapKey(entity, kind, values, viewIndex);
744b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
754b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        int id = mIdMap.getInt(k, INVALID_VIEW_ID);
764b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        if (id == INVALID_VIEW_ID) {
774b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            // Make sure the new id won't conflict with auto-generated ids by masking with 0xffff.
784b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            id = (mNextId++) & 0xFFFF;
794b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            mIdMap.putInt(k, id);
804b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        }
814b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        return id;
824b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
834b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
84851222a96b5d68602fb361ea3527101e893f67e3Maurice Chu    private static String getMapKey(RawContactDelta entity, DataKind kind, ValuesDelta values,
854b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            int viewIndex) {
864b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        sWorkStringBuilder.setLength(0);
874b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        if (entity != null) {
884b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            sWorkStringBuilder.append(entity.getValues().getId());
894b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
904b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            if (kind != null) {
914b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                sWorkStringBuilder.append(KEY_SEPARATOR);
924b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                sWorkStringBuilder.append(kind.mimeType);
934b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
944b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                if (values != null) {
954b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                    sWorkStringBuilder.append(KEY_SEPARATOR);
964b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                    sWorkStringBuilder.append(values.getId());
974b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
984b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                    if (viewIndex != NO_VIEW_INDEX) {
994b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                        sWorkStringBuilder.append(KEY_SEPARATOR);
1004b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                        sWorkStringBuilder.append(viewIndex);
1014b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                    }
1024b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki                }
1034b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            }
1044b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        }
1054b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        return sWorkStringBuilder.toString();
1064b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
1074b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1084b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    /** {@Override} */
1094b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public void writeToParcel(Parcel dest, int flags) {
1104b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        dest.writeInt(mNextId);
1114b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        dest.writeBundle(mIdMap);
1124b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
1134b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1144b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    private void readFromParcel(Parcel src) {
1154b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        mNextId = src.readInt();
1164b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        mIdMap = src.readBundle();
1174b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    }
1184b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1194b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    public static final Parcelable.Creator<ViewIdGenerator> CREATOR =
1204b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            new Parcelable.Creator<ViewIdGenerator>() {
1214b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        public ViewIdGenerator createFromParcel(Parcel in) {
1224b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            final ViewIdGenerator vig = new ViewIdGenerator();
1234b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            vig.readFromParcel(in);
1244b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            return vig;
1254b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        }
1264b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki
1274b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        public ViewIdGenerator[] newArray(int size) {
1284b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki            return new ViewIdGenerator[size];
1294b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki        }
1304b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki    };
1314b722a93f1ecdeb2890fb7e5db4c22794bccfdcdMakoto Onuki}
132