com.google.devtools.build.lib.rules.objc.Xcdatamodel.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.build.lib.rules.objc.Xcdatamodel.java

Source

// 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.base.Function;
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;
    }

    /**
     * Returns the files that should be supplied to Xcodegen when generating a project that includes
     * all of the given xcdatamodel source files.
     */
    public static Iterable<Artifact> inputsToXcodegen(Iterable<Artifact> datamodelFiles) {
        ImmutableSet.Builder<Artifact> inputs = new ImmutableSet.Builder<>();
        for (Artifact generalInput : datamodelFiles) {
            if (generalInput.getExecPath().getBaseName().equals(".xccurrentversion")) {
                inputs.add(generalInput);
            }
        }
        return inputs.build();
    }

    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, new Function<Xcdatamodel, Artifact>() {
            @Override
            public Artifact apply(Xcdatamodel model) {
                return model.getOutputZip();
            }
        });
    }
}