aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/objc/Xcdatamodel.java
blob: e4b13c7409a7c6e5b888c4e15e1589d571c15470 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.rules.objc;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.vfs.PathFragment;

/**
 * Represents an .xcdatamodel[d] directory - knowing all {@code Artifact}s contained therein - and
 * the .zip file that it is compiled to which should be merged with the final application bundle.
 * <p>
 * An .xcdatamodel (here and below note that lack or presence of a d) directory contains the schema
 * for a managed object, or a managed object model. It typically has two files: {@code layout} and
 * {@code contents}, although this detail isn't addressed in Bazel code. Directories of this
 * sort are compiled into a single .mom file. If the .xcdatamodel directory is inside a
 * .xcdatamodeld directory, then the .mom file is placed inside a .momd directory. The .momd
 * directory or .mom file is placed in the bundle root of the final bundle.
 * <p>
 * An .xcdatamodeld directory contains several .xcdatamodel directories, each corresponding to a
 * different version. In addition the .xcdatamodeld directory contains a {@code .xccurrentversion}
 * file which identifies the current version. (this file is also not handled explicitly by Bazel
 * code).
 * <p>
 * When processing artifacts referenced by a {@code datamodels} attribute, we must determine if it
 * is in a .xcdatamodeld directory or only a .xcdatamodel directory. We also must group the
 * artifacts by their container, the container being an .xcdatamodeld directory if possible, and a
 * .xcdatamodel directory otherwise. Every container is compiled with a single invocation of the
 * Managed Object Model Compiler (momc) and corresponds to exactly one instance of this class. We
 * invoke momc indirectly through the momczip tool (part of Bazel) which runs momc and zips the
 * output. The files in this zip are placed in the bundle root of the final application, not unlike
 * the zips generated by {@code actoolzip} or {@code ibtoolzip}.
 */
class Xcdatamodel extends Value<Xcdatamodel> {
  private final Artifact outputZip;
  private final ImmutableSet<Artifact> inputs;
  private final PathFragment container;

  Xcdatamodel(Artifact outputZip, ImmutableSet<Artifact> inputs, PathFragment container) {
    super(ImmutableMap.of(
        "outputZip", outputZip,
        "inputs", inputs,
        "container", container));
    this.outputZip = outputZip;
    this.inputs = inputs;
    this.container = container;
  }

  public Artifact getOutputZip() {
    return outputZip;
  }

  /**
   * Returns every known file in the container. This is every input file that is processed by momc.
   */
  public ImmutableSet<Artifact> getInputs() {
    return inputs;
  }

  public PathFragment getContainer() {
    return container;
  }

  /**
   * The ARCHIVE_ROOT passed to momczip. The archive root is the name of the .mom file
   * unversioned object models, and the name of the .momd directory for versioned object models.
   */
  public String archiveRootForMomczip() {
    return name() + (container.getBaseName().endsWith(".xcdatamodeld") ? ".momd" : ".mom");
  }

  /**
   * The name of the data model. This is the name of the container without the extension. For
   * instance, if the container is "foo/Information.xcdatamodel" or "bar/Information.xcdatamodeld",
   * then the name is "Information".
   */
  public String name() {
    String baseContainerName = container.getBaseName();
    int lastDot = baseContainerName.lastIndexOf('.');
    return baseContainerName.substring(0, lastDot);
  }

  public static Iterable<Artifact> outputZips(Iterable<Xcdatamodel> models) {
    return Iterables.transform(models, Xcdatamodel::getOutputZip);
  }
}