1/*
2 * Copyright (C) 2015 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
17#include "xml/XmlUtil.h"
18
19#include <string>
20
21#include "util/Maybe.h"
22#include "util/Util.h"
23
24using android::StringPiece;
25
26namespace aapt {
27namespace xml {
28
29std::string BuildPackageNamespace(const StringPiece& package,
30                                  bool private_reference) {
31  std::string result =
32      private_reference ? kSchemaPrivatePrefix : kSchemaPublicPrefix;
33  result.append(package.data(), package.size());
34  return result;
35}
36
37Maybe<ExtractedPackage> ExtractPackageFromNamespace(
38    const std::string& namespace_uri) {
39  if (util::StartsWith(namespace_uri, kSchemaPublicPrefix)) {
40    StringPiece schema_prefix = kSchemaPublicPrefix;
41    StringPiece package = namespace_uri;
42    package = package.substr(schema_prefix.size(),
43                             package.size() - schema_prefix.size());
44    if (package.empty()) {
45      return {};
46    }
47    return ExtractedPackage{package.to_string(), false /* is_private */};
48
49  } else if (util::StartsWith(namespace_uri, kSchemaPrivatePrefix)) {
50    StringPiece schema_prefix = kSchemaPrivatePrefix;
51    StringPiece package = namespace_uri;
52    package = package.substr(schema_prefix.size(),
53                             package.size() - schema_prefix.size());
54    if (package.empty()) {
55      return {};
56    }
57    return ExtractedPackage{package.to_string(), true /* is_private */};
58
59  } else if (namespace_uri == kSchemaAuto) {
60    return ExtractedPackage{std::string(), true /* is_private */};
61  }
62  return {};
63}
64
65void TransformReferenceFromNamespace(IPackageDeclStack* decl_stack,
66                                     const StringPiece& local_package,
67                                     Reference* in_ref) {
68  if (in_ref->name) {
69    if (Maybe<ExtractedPackage> transformed_package =
70            decl_stack->TransformPackageAlias(in_ref->name.value().package,
71                                              local_package)) {
72      ExtractedPackage& extracted_package = transformed_package.value();
73      in_ref->name.value().package = std::move(extracted_package.package);
74
75      // If the reference was already private (with a * prefix) and the
76      // namespace is public,
77      // we keep the reference private.
78      in_ref->private_reference |= extracted_package.private_namespace;
79    }
80  }
81}
82
83}  // namespace xml
84}  // namespace aapt
85