All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.api.templates.FileBuilder Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.netbeans.api.templates;

import java.io.IOException;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.netbeans.api.annotations.common.CheckForNull;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.NullAllowed;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Lookup;
import org.openide.util.MapFormat;
import org.openide.util.Parameters;

/**
 * Fluent interface for file creation. The Builder is first parametrized. After
 * everything is set up, call {@link #build} to materialize the template using
 * the supplied parameters/settings.
 * 

* The create file(s) get names derived from the template and the existing target folder * contents (so that the filenames do not conflict with existing files). A desired * filename can be set up by {@link #name}. *

* The file build request will be forwarded to {@link CreateFromTemplateHandler}s; if none * {@link CreateFromTemplateHandler#accept}s the request, the default procedure takes place, * depending on the {@code #defaultMode} setting (default: {@link Mode#COPY}). *

* There are several values predefined:

    *
  • name - the created filename without extension *
  • nameAndExt - the created filename including the extension *
  • date - date of creation, printed in the default date format *
  • dateTime - {@link Date} object representing the creation time *
  • time - time of creation, printed in the default time format *
  • user - the user id of the user creating the file *
* * @author sdedic */ public final class FileBuilder { /** * A specific {@link CreateFromTemplateHandler} to be used with this particular template. * If present on a template, will be used as a default. Still can be overriden by a lookup-registered * registered {@link CreateFromTemplateHandler}. * @since 1.23 */ public static final String ATTR_TEMPLATE_HANDLER = "template.createTemplateHandler"; // NOI18N /** * A flag used by the default template processing to create files from template structures in existing folders * rather than create unique folder names. By default, folders in template will create unique folders on the disk, * if the same-named folder already exists. The attribute, if defined, should have a boolean value true/false. * @since 1.23 */ public static final String ATTR_TEMPLATE_MERGE_FOLDERS = "template.mergeFolders"; // NOI18N /** * Marks file(s) in the template, that should be opened in the editor. If the template file attribute * is set to {@link Boolean#TRUE}, the template handler should the file created from the file template from * the {@link #build} method. Note the attribute serves as a hint, so the Handler may choose to ignore * the instruction. * @since 1.23 */ public static final String ATTR_TEMPLATE_OPEN_FILE = "template.openFile"; // NOI18N /** * Determines the default procedure for copying the template in {@link #createFromTemplate}. */ public static enum Mode { /** * The template will be formatted using formatter. */ FORMAT, /** * The template will be just copied. */ COPY, /** * The template will not be processed if no custom {@link CreateFromTemplateHandler} handles it. */ FAIL } /** * Creates a Builder based on the CreateDescriptor. The FileBuilder inherits * all parameters of the original {@link CreateDescriptor}. The client may change the attributes. * The method may be useful when creating secondary files; for example target and all attributes * are retained. During {@link #build()}, attributes may be redefined as needed for the * additional file, just like in normal Builder operation. *

* The new FileBuilder instance is completely indepenent of the original Descriptor. If the CreateDescriptor * supports additional properties in the future, using this method guarantees that they will be * transferred to the FileBuilder copy. * * @param desc the original descriptor * @return new FileBuilder * @since 1.5 */ public static @NonNull FileBuilder fromDescriptor(@NonNull CreateDescriptor desc) { Parameters.notNull("desc", desc); return new FileBuilder(desc.getTemplate(), desc.getTarget()). name(desc.getProposedName()). useLocale(desc.getLocale()). withParameters(desc.getParameters()); } /** * Creates a new FileBuilder for a specific template and target folder. * @param template the template to use. * @param target the target folder; must already exist. */ public FileBuilder(@NonNull FileObject template, @NonNull FileObject target) { descriptor = new CreateDescriptor(template, target); } /** * Use specific Lookup for creation. This allows to pass in additional * parameters or services. A GUI-aware caller may, for example, add * a ProgressHandle or a project ActionProgress interface to the lookup, * in a hope that template handler will use service to report progress. * @param contextLookup the Lookup passed to template creation subprocesses * @return this FileBuilder instance. * @since 1.23 */ public FileBuilder useLookup(Lookup contextLookup) { descriptor.setLookup(contextLookup); return this; } /** * Specifies the locale to be used during file creation. * The locale also applies to the standard parameters passed to the template (e.g. date and time representation). * @param l the locale * @return this FileBuilder instance. */ public FileBuilder useLocale(@NonNull Locale l) { descriptor.locale = l; return this; } /** * Sets the desired target file's name. * * @param n the name * @return this FileBuilder instance */ public FileBuilder name(String n) { descriptor.name = n; return this; } /** * Includes parameters for the template. * For backwards compatibility, special parameters {@link CreateDescriptor#FREE_FILE_EXTENSION} and * {@link CreateDescriptor#PREFORMATTED_TEMPLATE} are processed and appropriate properties modified on the * CreateDescriptor. * * @param params the string-value pairs * @return this FileBuilder instance */ public FileBuilder withParameters(@NullAllowed Map params) { if (descriptor.parameters != null) { descriptor.parameters.putAll(params); } else { descriptor.parameters = params == null ? null : new HashMap(params); } if (params != null) { Object v = params.get(CreateDescriptor.FREE_FILE_EXTENSION); if (v instanceof Boolean) { boolean val = Boolean.TRUE.equals(v); descriptor.freeExtension = val; } v = params.get(CreateDescriptor.PREFORMATTED_TEMPLATE); if (v instanceof Boolean) { boolean val = Boolean.TRUE.equals(v); descriptor.preformatted = val; } } return this; } /** * Adds a parameter to the template. * For backwards compatibility, special parameters {@link CreateDescriptor#FREE_FILE_EXTENSION} and * {@link CreateDescriptor#PREFORMATTED_TEMPLATE} are processed and appropriate properties modified on the * CreateDescriptor. * * @param n parameter name * @param v the value * @return this FileBuilder instance */ public FileBuilder param(@NonNull String n, Object v) { if (descriptor.parameters == null) { descriptor.parameters = new HashMap<>(); } descriptor.parameters.put(n, v); if (v instanceof Boolean) { if (CreateDescriptor.FREE_FILE_EXTENSION.equals(n)) { boolean val = Boolean.TRUE.equals(v); descriptor.freeExtension = val; } if (CreateDescriptor.PREFORMATTED_TEMPLATE.equals(n)) { boolean val = Boolean.TRUE.equals(v); descriptor.preformatted = val; } } return this; } /** * Specifies the behaviour to be used when no {@link CreateFromTemplateHandler} accepts the template. * @param m the default processing mode * @return this FileBuilder instance * @see Mode for details */ public FileBuilder defaultMode(@NonNull Mode m) { this.defaultMode = m; return this; } /** * Uses the specified formatter for file creation. Also sets the default mode to * {@link Mode#FORMAT}. If the supplied Format instance happens to be a * {@link MapFormat}, the templating code will pass parameters produced by * {@link CreateFromTemplateAttributes} to the format when the target file * contents is generated. * * @param def the format to use * @return this FileBuilder instance * @see Mode for details on different modes */ public FileBuilder useFormat(@NonNull Format def) { this.format = def; return defaultMode(Mode.FORMAT); } /** * Creates the file(s) from template. * @return list of created files. If some file is 'master' or otherwise of high importance and represents * the file set, it should be placed first in the list. * @throws IOException if the creation fails */ public @CheckForNull List build() throws IOException { return CreateFromTemplateImpl.build(this); } CreateDescriptor getDescriptor() { return descriptor; } /** * Creates a descriptor from the current Builder's state. * If `collectAttributes' is false, the descriptor * will have no additional parameters set from {@link CreateFromTemplateAttributes} providers; * the caller must process the providers, if it wishes to get additional attributes. * The Descriptor can be used to collect information from attribute providers or manually * trigger file creation in template handler. *

* The operation changes the FileBuilder state. * * @param collectAttributes if true, attribute providers are asked to add their attributes * to the builder/descriptor. * @return descriptor * @since 1.5 */ public @NonNull CreateDescriptor createDescriptor(boolean collectAttributes) { if (collectAttributes) { CreateFromTemplateImpl.collectAttributes(this); } CreateFromTemplateImpl.computeEffectiveName(descriptor); return descriptor; } private final CreateDescriptor descriptor; @SuppressWarnings("PackageVisibleField") Mode defaultMode; @SuppressWarnings("PackageVisibleField") Format format; /** * Creates a new file based on the template. This convenience method is intended for easier * migration of clients using DataLoader templating API before {@link FileBuilder} introduction. * The method will collect parameters * tied to the template using registered {@link CreateFromTemplateAttributes} providers, * and will try to locate a willing {@link CreateFromTemplateHandler} that will create * the target file. If no such handler exists, and the {@code defaultCopy} parameter is true, * the file contents is just copied to the target location. *

* If the {@code name} parameter is null, the function attempts to compute a suitable name * from the file. *

* The default copy algorithm uses the supplied {@link Mode#FORMAT} to * process tokens. *

* If the passed {@code name} is {@code null}, the implementation will pick a free name based on * the template's own name (see {@link FileUtil#findFreeFileName}). * @param f the template file * @param folder the target folder, must exist * @param name the desired name. If {@code null}, the implementation will choose the name. * @param attributes values to apply on the template. May be {@code null} = no values. * @param defaultMode the mode of operations to use * @return The created file, or {@code null} if no creation handler is located. * @throws IOException when an I/O operation fails */ @SuppressWarnings("AssignmentToMethodParameter") @CheckForNull public static FileObject createFromTemplate(@NonNull FileObject f, @NonNull FileObject folder, @NullAllowed String name, @NullAllowed Map attributes, Mode defaultMode) throws IOException { Format frm = null; switch (defaultMode) { case FORMAT: MapFormat mf = new MapFormat(new HashMap<>()); mf.setExactMatch(false); mf.setLeftBrace("__"); mf.setRightBrace("__"); frm = mf; break; case COPY: frm = new Format() { @Override public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) { toAppendTo.append(obj); return toAppendTo; } @Override public Object parseObject(String source, ParsePosition pos) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }; break; } FileBuilder fb = new FileBuilder(f, folder). name(name). withParameters(attributes). useFormat(frm). defaultMode(defaultMode); List fos = fb.build(); if (fos == null || fos.isEmpty()) { return null; } else { return fos.iterator().next(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy