131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov/*
231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * Copyright (C) 2010 The Android Open Source Project
331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov *
431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * Licensed under the Apache License, Version 2.0 (the "License");
531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * you may not use this file except in compliance with the License.
631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * You may obtain a copy of the License at
731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov *
831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov *      http://www.apache.org/licenses/LICENSE-2.0
931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov *
1031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * Unless required by applicable law or agreed to in writing, software
1131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * distributed under the License is distributed on an "AS IS" BASIS,
1231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * See the License for the specific language governing permissions and
1431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * limitations under the License.
1531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov */
1631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
1731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovpackage com.android.contacts.tests.allintents;
1831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
1931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.app.Activity;
2031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.content.ContentUris;
2131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.content.Intent;
2231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.database.Cursor;
2331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.graphics.Bitmap;
2431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.graphics.BitmapFactory;
2531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.graphics.Color;
2631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.net.Uri;
2731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.os.Bundle;
2831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.os.Parcelable;
29e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.provider.ContactsContract.CommonDataKinds.Photo;
3031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.provider.ContactsContract.Contacts;
3131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.provider.ContactsContract.Data;
3231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.text.TextUtils;
3331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.view.View;
3431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.widget.ImageView;
35e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport android.widget.ImageView.ScaleType;
3631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.widget.TableLayout;
3731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.widget.TableRow;
3831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport android.widget.TextView;
39e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Cheng
40e0b2f1e2d01d1ac52ba207dc7ce76971d853298eChiao Chengimport com.android.contacts.tests.R;
4131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
4231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovimport java.util.Arrays;
4331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
4431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov/**
4531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov * An activity that shows the result of a contacts activity invocation.
4631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov */
4731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikovpublic class ResultActivity extends Activity {
4831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
4931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    @Override
5031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    protected void onCreate(Bundle savedInstanceState) {
5131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        super.onCreate(savedInstanceState);
5231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        setContentView(R.layout.result);
5331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
5431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        Intent intent = getIntent();
5531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        addRowsForIntent((Intent)intent.getExtras().get("data"));
5631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
5731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
5831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRowsForIntent(Intent intent) {
5931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        if (intent == null) {
6031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow("", "No data intent returned");
6131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else {
6231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow("INTENT", intent.toString());
6331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addSeparator(3);
6431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
6531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            Bundle extras = intent.getExtras();
6631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            if (extras != null && !extras.isEmpty()) {
6731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                for (String key : extras.keySet()) {
6831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    Object value = extras.get(key);
6931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    addRow("EXTRA", key);
7031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    addRowForValue("", value);
7131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                }
7231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
7331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                addSeparator(3);
7431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
7531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
7631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            String dataUri = intent.getDataString();
7731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            if (dataUri != null) {
7831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                addRowsForQuery(Uri.parse(dataUri));
7931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
8031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        }
8131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
8231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
8331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRowForValue(String label, Object value) {
8431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        if (value == null) {
8531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow(label, "null");
8631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else if (value instanceof Bitmap) {
8731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRowWithBitmap(label, (Bitmap)value);
8831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else if (value instanceof Intent) {
8931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow(label, "INTENT");
9031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRowsForIntent((Intent)value);
9131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else if (value instanceof Uri) {
9231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow(label, "DATA");
9331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRowsForQuery((Uri)value);
9431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else if (value.getClass().isArray()) {
9531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow(label, "ARRAY");
9631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            Parcelable[] array = (Parcelable[])value;
9731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            for (int i = 0; i < array.length; i++) {
9831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                addRowForValue("[" + i + "]", String.valueOf(array[i]));
9931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
10031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else {
10131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow(label, String.valueOf(value));
10231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        }
10331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
10431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
10531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRowsForQuery(Uri dataUri) {
10631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        Cursor cursor = getContentResolver().query(dataUri, null, null, null, null);
10731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        if (cursor == null) {
10831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            addRow("", "No data for this URI");
10931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } else {
11031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            try {
11131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                while (cursor.moveToNext()) {
11231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    addRow("", "DATA");
11331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    String[] columnNames = cursor.getColumnNames();
11431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    String[] names = new String[columnNames.length];
11531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    System.arraycopy(columnNames, 0, names, 0, columnNames.length);
11631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    Arrays.sort(names);
11731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    for (int i = 0; i < names.length; i++) {
11831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                        int index = cursor.getColumnIndex(names[i]);
11931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                        String value = cursor.getString(index);
12031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                        addRow(names[i], value);
12131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
12231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                        if (names[i].equals(Contacts.PHOTO_ID) && !TextUtils.isEmpty(value)) {
12331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                            addRowWithPhoto(Long.parseLong(value));
12431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                        }
12531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                    }
12631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                }
12731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            } finally {
12831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                cursor.close();
12931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
13031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        }
13131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
13231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
13331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRow(String column0, String column1) {
13431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TextView label = new TextView(this);
13531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        label.setPadding(4, 4, 4, 4);
13631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        label.setText(column0);
13731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TextView value = new TextView(this);
13831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        value.setPadding(4, 4, 4, 4);
13931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        value.setText(column1);
14031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        addRow(label, value);
14131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
14231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
14331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRowWithPhoto(long photoId) {
14431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        byte[] data = null;
14531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        Cursor cursor = getContentResolver().query(
14631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                ContentUris.withAppendedId(Data.CONTENT_URI, photoId),
14731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                new String[]{Photo.PHOTO}, null, null, null);
14831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        try {
14931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            if (cursor.moveToNext()) {
15031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                data = cursor.getBlob(0);
15131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
15231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        } finally {
15331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            if (cursor != null) {
15431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov                cursor.close();
15531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            }
15631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        }
15731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
15831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        if (data == null) {
15931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov            return;
16031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        }
16131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
16231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        addRowWithBitmap("Photo", BitmapFactory.decodeByteArray(data, 0, data.length));
16331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
16431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
16531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRowWithBitmap(String label, Bitmap bitmap) {
16631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TextView labelView = new TextView(this);
16731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        labelView.setPadding(4, 4, 4, 4);
16831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        labelView.setText(label);
16931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
17031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        ImageView imageView = new ImageView(this);
17131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        imageView.setImageBitmap(bitmap);
17231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        imageView.setPadding(4, 4, 4, 4);
17331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        imageView.setScaleType(ScaleType.FIT_START);
17431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        addRow(labelView, imageView);
17531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
17631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
17731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addRow(View column0, View column1) {
17831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TableLayout table = (TableLayout)findViewById(R.id.table);
17931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TableRow row = new TableRow(this);
18031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        row.addView(column0);
18131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        row.addView(column1);
18231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        table.addView(row);
18331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
18431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        addSeparator(1);
18531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
18631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov
18731ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    private void addSeparator(int height) {
18831ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TableLayout table = (TableLayout)findViewById(R.id.table);
18931ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        View separator = new View(this);
19031ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        TableLayout.LayoutParams params = new TableLayout.LayoutParams();
19131ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        params.height = height;
19231ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        separator.setLayoutParams(params);
19331ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        separator.setBackgroundColor(Color.rgb(33, 66, 33));
19431ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov        table.addView(separator);
19531ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov    }
19631ec0b51ac4d508f8727608b98d0bf916f2b20b9Dmitri Plotnikov}
197