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

org.netbeans.modules.properties.Util Maven / Gradle / Ivy

There is a newer version: RELEASE240
Show newest version
/*
 * 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.modules.properties;


import java.io.IOException;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.cookies.SaveCookie;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.Repository;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.loaders.FileEntry;

import org.openide.loaders.MultiDataObject;
import org.openide.util.NbBundle;


/**
 * Miscellaneous utilities for properties(reosurce bundles) module.
 * @author Petr Jiricka
 * @author Marian Petras
 */
public final class Util extends Object {
    
    /** Help ID for properties module in general. */
    public static final String HELP_ID_PROPERTIES = "propfiles.prop";   //NOI18N
    /** Help ID for properties new from template. */
    public static final String HELP_ID_CREATING = "propfiles.creating"; //NOI18N
    /** Help ID for new property dialog. */
    public static final String HELP_ID_ADDING = "propfiles.adding";     //NOI18N
    /** Help ID for table view of properties. */
    public static final String HELP_ID_MODIFYING
                               = "propfiles.modifying";                 //NOI18N
    /** Help ID for new locale dialog. */
    public static final String HELP_ID_ADDLOCALE
                               = "propfiles.addlocale";                 //NOI18N
    /** Help ID for source editor of .properties file. */
    public static final String HELP_ID_EDITLOCALE
                               = "propfiles.editlocale";                //NOI18N

    /** Character used to separate parts of bundle properties file name */
    public static final char PRB_SEPARATOR_CHAR
                             = PropertiesDataLoader.PRB_SEPARATOR_CHAR;
    /** Default length for the first part of node label */
    public static final int LABEL_FIRST_PART_LENGTH = 10;

    /** Converts a string to a string suitable for a resource bundle key */
    public static String stringToKey(String source) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < source.length(); i++) {
            char x = source.charAt(i);
            switch (x) {
            case '=':
            case ':':
            case '\t':
            case '\r':
            case '\n':
            case '\f':
            case ' ':
                result.append('_'); break;
            default:
                result.append(x);
            }
        }
        return result.toString();
    }

    /**
     * Assembles a file name for a properties file from its base name and
     * language.
     *
     * @return assembled name
     */
    public static String assembleName (String baseName, String lang) {
        if (lang.length() == 0) {
            return baseName;
        } else {
            if (lang.charAt(0) != PRB_SEPARATOR_CHAR) {
                StringBuffer res = new StringBuffer().append(baseName)
                                                     .append(PRB_SEPARATOR_CHAR)
                                                     .append(lang);
                return res.toString();
            } else {
                return baseName + lang;
            }
        }
    }
    
    /**
     * Returns a locale specification suffix of a given
     * MultiDataObject entry.
     * 

* Examples:
*

    
Bundle.properties -> ""
*
    
Bundle_en_CA.properties -> "_en_CA" * * @param fe DataObject entry, representing a single bundle * @return locale specification suffix of a given entry; * or an empty string if the given entry has no locale suffix * @see #getLanguage * @see #getCountry * @see #getVariant */ public static String getLocaleSuffix(MultiDataObject.Entry fe) { FileObject fo = fe.getFile(); String fName = fo.getName(); String baseName = getBaseName(fName); if (fName.equals(baseName)) return ""; else return fName.substring(baseName.length()); } private static boolean isValidLocaleSuffix(String s) { // first char is _ int n = s.length(); String s1; // check first suffix - language (two chars) if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) { s1 = s.substring(1, 3).toLowerCase(); // language must be followed by a valid country suffix or no suffix } else { return false; } // check second suffix - country (two chars) String s2; if (n == 3) { s2 = null; } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) { s2 = s.substring(4, 6).toUpperCase(); // country may be followed by whatever additional suffix } else { return false; } HashSet knownLanguages = new HashSet(Arrays.asList(Locale.getISOLanguages())); if (!knownLanguages.contains(s1)) { return false; } if (s2 != null) { HashSet knownCountries = new HashSet(Arrays.asList(Locale.getISOCountries())); if (!knownCountries.contains(s2)) { return false; } } return true; } /** * Returns a language specification abbreviation of a given * MultiDataObject entry. * For example, if the specified entry represents file * Bundle_en_UK.properties, this method returns * "en". * * @return
    *
  • the language specification part of the locale specification, * if present
  • *
  • an empty string ("") * if the locale specification does not contain * language specification
  • *
  • null if the file (entry) has no locale * specification
  • *
* @see #getCountry * @see #getVariant */ public static String getLanguage(final String localeSuffix) { return getFirstPart(localeSuffix); } /** * Returns a country specification abbreviation of a given * MultiDataObject entry. * For example, if the specified entry represents file * Bundle_en_UK.properties, this method returns * "UK". * * @return
    *
  • the country specification part of the locale * specification, if present
  • *
  • an empty string ("") * if the locale specification does not contain * country specification
  • *
  • null if the file (entry) has no locale * specification
  • *
* @see #getLanguage * @see #getVariant */ public static String getCountry(final String localeSuffix) { if (localeSuffix.length() == 0) { return null; } int start = localeSuffix.indexOf(PRB_SEPARATOR_CHAR, 1); return (start != -1) ? getFirstPart(localeSuffix.substring(start)) : ""; //NOI18N } /** * Returns a variant specification abbreviation of a given * MultiDataObject entry. * For example, if the specified entry represents file * Bundle_en_US_POSIX.properties, this method returns * "POSIX". * * @return
    *
  • the variant specification part of the locale * specification, if present
  • *
  • an empty string ("") * if the locale specification does not contain * variant specification
  • *
  • null if the file (entry) has no locale * specification
  • *
* @see #getLanguage * @see #getCountry */ public static String getVariant(final String localeSuffix) { if (localeSuffix.length() == 0) { return null; } int start = localeSuffix.indexOf(PRB_SEPARATOR_CHAR, 1); if (start == -1) { return ""; //NOI18N } start = localeSuffix.indexOf(PRB_SEPARATOR_CHAR, start + 1); return (start != -1) ? localeSuffix.substring(start + 1) : ""; //NOI18N } /** * Returns the first part of a given locale suffix. * The locale suffix must be either empty or start with an underscore. * * @param localeSuffix locale suffix, e.g. "_en_US" * @return first part of the suffix, i. e. the part * between the initial '_' and the * (optional) next '_'; or null * if an empty string was given as an argument */ private static String getFirstPart(String localeSuffix) { if (localeSuffix.length() == 0) { return null; } assert localeSuffix.charAt(0) == PRB_SEPARATOR_CHAR; int end = localeSuffix.indexOf(PRB_SEPARATOR_CHAR, 1); return (end != -1) ? localeSuffix.substring(1, end) : localeSuffix.substring(1); } /** Gets a label for properties nodes for individual locales. */ public static String getLocaleLabel(MultiDataObject.Entry fe) { String localeSuffix = getLocaleSuffix(fe); String language; String country; String variant; /* * Get the abbreviations for language, country and variant and check * if at least one of them is specified. If none of them is specified, * return the default label: */ if (localeSuffix.length() == 0) { language = ""; //NOI18N country = ""; //NOI18N variant = ""; //NOI18N } else { language = getLanguage(localeSuffix); country = getCountry(localeSuffix); variant = getVariant(localeSuffix); // intern empty strings so that we can use '==' instead of equals(): language = language.length() != 0 ? language : ""; //NOI18N country = country.length() != 0 ? country : ""; //NOI18N variant = variant.length() != 0 ? variant : ""; //NOI18N } String defaultLangName = null; if (language == "") { //NOI18N defaultLangName = NbBundle.getMessage( Util.class, "LAB_defaultLanguage"); //NOI18N } /* Simple case #1 - the default locale */ if (language == "" && country == "" && variant == "") { //NOI18N return defaultLangName; } String localeSpec = localeSuffix.substring(1); Locale locale = new Locale(language, country, variant); /* - language name: */ String langName; if (language == "") { //NOI18N langName = defaultLangName; } else { langName = locale.getDisplayLanguage(); if (langName.equals(language)) { langName = NbBundle.getMessage(Util.class, "LAB_unknownLanguage", //NOI18N language); } } /* Simple case #2 - language specification only */ if (country == "" && variant == "") { //NOI18N return NbBundle.getMessage(Util.class, "LAB_localeSpecLang", //NOI18N localeSpec, langName); } /* - country name: */ String countryName = ""; //NOI18N if (country != "") { //NOI18N countryName = locale.getDisplayCountry(); if (countryName.equals(country)) { countryName = NbBundle.getMessage(Util.class, "LAB_unknownCountry", //NOI18N country); } } /* - variant name: */ String variantName = variant == "" ? "" //NOI18N : locale.getDisplayVariant(); /* Last case - country and/or variant specification */ String countryAndVariant; if (variantName == "") { //NOI18N countryAndVariant = countryName; } else if (countryName == "") { //NOI18N countryAndVariant = variantName; } else { countryAndVariant = countryName + ", " + variantName; //NOI18N } return NbBundle.getMessage(Util.class, "LAB_localeSpecLangCountry", //NOI18N localeSpec, langName, countryAndVariant); } /** Notifies an error happened when attempted to create locale which exists already. * @param locale locale which already exists */ private static void notifyError(String locale) { NotifyDescriptor.Message msg = new NotifyDescriptor.Message( MessageFormat.format( NbBundle.getBundle(PropertiesDataNode.class).getString("MSG_LangExists"), new Object[] {locale}), NotifyDescriptor.ERROR_MESSAGE); DialogDisplayer.getDefault().notify(msg); } /** * Creates a new PropertiesDataObject (properties file). * @param folder FileObject folder where to create the properties file * @param fileName String name of the file without the extension, can include * relative path underneath the folder * @return created PropertiesDataObjet */ public static PropertiesDataObject createPropertiesDataObject(FileObject folder, String fileName) throws IOException { int idx = fileName.lastIndexOf('/'); if (idx > 0) { String folderPath = fileName.substring(0, idx); folder = FileUtil.createFolder(folder, folderPath); fileName = fileName.substring(idx + 1); } FileSystem defaultFS = Repository.getDefault().getDefaultFileSystem(); FileObject templateFO = defaultFS.findResource("Templates/Other/properties.properties"); // NOI18N DataObject template = DataObject.find(templateFO); return (PropertiesDataObject) template.createFromTemplate(DataFolder.findFolder(folder), fileName); } /** * Create new DataObject with requested locale and notify that new locale was added * @param propertiesDataObject DataObject to add locale * @param locale * @param copyInitialContent */ public static void createLocaleFile(PropertiesDataObject propertiesDataObject, String locale, boolean copyInitialContent) { try { if(locale.length() == 0) { // It would mean default locale to create again. notifyError(locale); return; } if(propertiesDataObject != null) { // FileObject file = propertiesDataObject.getPrimaryFile(); FileObject file = propertiesDataObject.getBundleStructure().getNthEntry(0).getFile(); String extension = PropertiesDataLoader.PROPERTIES_EXTENSION; if (!file.hasExt(extension)) { if (file.getMIMEType().equalsIgnoreCase(PropertiesDataLoader.PROPERTIES_MIME_TYPE)) extension = file.getExt(); } //Default locale may be deleted final String newName = getBaseName(file.getName()) + PropertiesDataLoader.PRB_SEPARATOR_CHAR + locale; final FileObject folder = file.getParent(); // final PropertiesEditorSupport editor = (PropertiesEditorSupport)propertiesDataObject.getCookie(PropertiesEditorSupport.class); java.util.Iterator it = propertiesDataObject.secondaryEntries().iterator(); while (it.hasNext()) { FileObject f = ((FileEntry)it.next()).getFile(); if (newName.startsWith(f.getName()) && f.getName().length() > file.getName().length()) file = f; } if (file.getName().equals(newName)) { return; // do nothing if the file already exists } if (copyInitialContent) { if (folder.getFileObject(newName, extension) == null) { SaveCookie save = (SaveCookie) propertiesDataObject.getCookie(SaveCookie.class); if (save != null) { save.save(); } final FileObject templateFile = file; final String ext = extension; folder.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() { public void run() throws IOException { templateFile.copy(folder, newName, ext); } }); //find just created DataObject PropertiesDataObject dataObject = (PropertiesDataObject) DataObject.find(folder.getFileObject(newName, extension)); dataObject.setBundleStructure(propertiesDataObject.getBundleStructure()); //update entries in BundleStructure propertiesDataObject.getBundleStructure().updateEntries(); //Add it to OpenSupport propertiesDataObject.getOpenSupport().addDataObject(dataObject); //Notify BundleStructure that one file changed propertiesDataObject.getBundleStructure().notifyOneFileChanged(folder.getFileObject(newName, extension)); } } else { // Create an empty file - creating from template via DataObject // API would create a separate DataObject for the locale file. // After creation force the DataObject to refresh its entries. DataObject.find(folder.createData(newName, extension)); //update entries in BundleStructure propertiesDataObject.getBundleStructure().updateEntries(); } } } catch(IOException ioe) { if(Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N ioe.printStackTrace(); notifyError(locale); } } /** * * @param obj DataObject * @return DataObject which represent default locale * In case when default locale is absent it will return first found locale as primary, * which has the same base name * @throws org.openide.loaders.DataObjectNotFoundException */ static PropertiesDataObject findPrimaryDataObject(PropertiesDataObject obj) throws DataObjectNotFoundException { FileObject primary = obj.getPrimaryFile(); assert primary != null : "Object " + obj + " cannot have null primary file"; // NOI18N String fName; fName = primary.getName(); String baseName = getBaseName(fName); FileObject parent = primary.getParent(); int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR); while (index != -1) { FileObject candidate = parent.getFileObject( fName.substring(0, index), primary.getExt()); if (candidate != null && isValidLocaleSuffix(fName.substring(index))) { return (PropertiesDataObject) DataObject.find(candidate); } else if (candidate == null){ for (FileObject file : parent.getChildren()) { if (!file.hasExt(PropertiesDataLoader.PROPERTIES_EXTENSION)) { continue; } if (file.getName().indexOf(baseName) != -1) { if (isValidLocaleSuffix(file.getName().substring(index))) { return (PropertiesDataObject) DataObject.find(file); } } } } index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1); } return obj; } /** * * @param f * @param parent Directory where to search * @param baseName of the locale (name without locale suffix) * @return BundleStructure or null * @throws org.openide.loaders.DataObjectNotFoundException */ static BundleStructure findBundleStructure (FileObject f, FileObject parent, String baseName) throws DataObjectNotFoundException{ String fName; PropertiesDataObject dataObject = null; BundleStructure structure; String extension = PropertiesDataLoader.PROPERTIES_EXTENSION; if (!f.hasExt(extension)) { if (f.getMIMEType().equalsIgnoreCase(PropertiesDataLoader.PROPERTIES_MIME_TYPE)) extension = f.getExt(); } for (FileObject file : parent.getChildren()) { if (!file.hasExt(extension) || file.equals(f)) { continue; } fName = file.getName(); if (fName.equals(baseName) && file.isValid()) { dataObject = (PropertiesDataObject) DataObject.find(file); if (dataObject == null) continue; structure = dataObject.getBundleStructureOrNull(); if (structure != null) return structure; else continue; } if (fName.indexOf(baseName) != -1) { int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR); if (baseName.length()!=index) continue; while (index != -1) { FileObject candidate = file; if (candidate != null && isValidLocaleSuffix(fName.substring(index)) && file.isValid()) { DataObject defaultDataObject = DataObject.find(candidate); if (defaultDataObject instanceof PropertiesDataObject) { dataObject = (PropertiesDataObject) DataObject.find(candidate); } else { index = -1; } if (dataObject == null) continue; structure = dataObject.getBundleStructureOrNull(); if (structure != null) return structure; } index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1); } } } return null; } /** * @param name file name * @return Base name for this locale */ static String getBaseName(String name) { String baseName = null; int index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR); while (index != -1) { baseName = name.substring(0, index); if (baseName != null && isValidLocaleSuffix(name.substring(index))) { return baseName; } index = name.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, index + 1); } return name; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy