Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
   *
   * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
   *
   * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   * Other names may be trademarks of their respective owners.
   *
   * The contents of this file are subject to the terms of either the GNU
  * General Public License Version 2 only ("GPL") or the Common
  * Development and Distribution License("CDDL") (collectively, the
  * "License"). You may not use this file except in compliance with the
  * License. You can obtain a copy of the License at
  * http://www.netbeans.org/cddl-gplv2.html
  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  * specific language governing permissions and limitations under the
  * License.  When distributing the software, include this License Header
  * Notice in each file and include the License file at
  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
  * particular file as subject to the "Classpath" exception as provided
  * by Oracle in the GPL Version 2 section of the License file that
  * accompanied this code. If applicable, add the following below the
  * License Header, with the fields enclosed by brackets [] replaced by
  * your own identifying information:
  * "Portions Copyrighted [year] [name of copyright owner]"
  *
  * Contributor(s):
  *
  * The Original Software is NetBeans. The Initial Developer of the Original
  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2008 Sun
  * Microsystems, Inc. All Rights Reserved.
  *
  * If you wish your version of this file to be governed by only the CDDL
  * or only the GPL Version 2, indicate your decision by adding
  * "[Contributor] elects to include this software in this distribution
  * under the [CDDL or GPL Version 2] license." If you do not indicate a
  * single choice of license, a recipient has the option to distribute
  * your version of this file under either the CDDL, the GPL Version 2 or
  * to extend the choice of license to its licensees as provided above.
  * However, if you add GPL Version 2 code and therefore, elected the GPL
  * Version 2 license, then the option applies only if the new code is
  * made subject to such option by the copyright holder.
  */
 
 
 package org.netbeans.modules.i18n.java;
 
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
Support for internationalizing strings in java sources.

Author(s):
Peter Zavadsky
See also:
org.netbeans.modules.i18n.I18nSupport
public class JavaI18nSupport extends I18nSupport {

    
Modifiers of field which are going to be internbationalized (default is private static final).
    protected Set<Modifiermodifiers = EnumSet.of(.,
                                                   .,
                                                   .);

    
Identifier of field element pointing to field which defines resource bundle in the source.
    protected String identifier;

    
Generate field?
    protected boolean generateField;
    
    
Init string format.
    protected String initFormat;
    private JavaReplacePanel additionalCustomizer;
    
    
    public JavaI18nSupport(DataObject sourceDataObject) {
        super(sourceDataObject);
         = I18nUtil.getOptions().getInitJavaCode();
    }
    
    
    
Creates I18nFinder. Implements superclass abstract method.
    protected I18nFinder createFinder() {
        return new JavaI18nFinder();
    }
    
    
Creates I18nReplacer. Implemens superclass abstract method.
    protected I18nReplacer createReplacer() {        
        return new JavaI18nReplacer();
    }
    
    
Creates ResourceHolder. Implemens superclass abstract method.
    protected ResourceHolder createResourceHolder() {
        return new JavaResourceHolder();
    }
    
    
Implements superclass abstract method.
    public I18nString getDefaultI18nString(HardCodedString hcString) {
        I18nString i18nString = new JavaI18nString(this);
        
        final ResourceHolder resourceHolder
                = i18nString.getSupport().getResourceHolder();
        if (resourceHolder.getResource() == null) {
            DataObject lastResource = I18nUtil.getOptions().getLastResource2();
            if (lastResource != null) {
                FileObject sourceFile = .getPrimaryFile();
                FileObject bundleFile = lastResource.getPrimaryFile();
                ClassPath execClassPath = ClassPath.getClassPath(sourceFile,
                                                                 .);
                if (execClassPath != null) {
                    if (execClassPath.getResourceName(bundleFile) != null) {
                        resourceHolder.setResource(lastResource);
                    }
                }
            }
        }
        if (hcString == null) {
            return i18nString;
        }
        
        String text = decodeUnicodeSeq(hcString.getText());
        String key = text.toUpperCase(); // don't replace ' ' with '_' ! #168798
        
        String hcStr = hcString.getText();
        String strAndVar = ((JavaI18nFinder)getFinder()).;
        int strAndVarLength = strAndVar.length();
        if(hcStr.contains(strAndVar)) { // handle Bug 33759 (http://netbeans.org/bugzilla/show_bug.cgi?id=33759)
            ArrayList<Stringvariables = new ArrayList<String>();
            int startVar = hcStr.indexOf(strAndVar);
            int endVar = -1;
            int counterVar = 0;
            text = hcStr.substring(0, startVar);
            while(startVar != -1) {
                if(counterVar > 0) {
                    text = text.concat(hcStr.substring(endVar + strAndVarLengthstartVar));
                }
                endVar = hcStr.indexOf(strAndVarstartVar + strAndVarLength);
                if(startVar + strAndVarLength == endVar) {
                    counterVar--;
                } else {
                    text = text.concat("{").concat(Integer.toString(counterVar)).concat("}"); // NOI18N
                    variables.add(hcStr.substring(startVar + strAndVarLengthendVar).trim());
                }
                startVar = hcStr.indexOf(strAndVarendVar + strAndVarLength);
                counterVar++;
                if(startVar == -1) {
                    text = text.concat(hcStr.substring(endVar + strAndVarLength));
                }
            }
            key = text.toUpperCase(); // don't replace ' ' with '_' ! #168798
            i18nString.setKey(key);
            i18nString.setValue(text);
            i18nString.setComment(""); // NOI18N
            i18nString.setReplaceFormat(I18nUtil.getReplaceFormatItems().get(4));
            String[] arguments = new String[variables.size()];
            for (int i = 0; i < variables.size(); i++) {
                arguments[i] = variables.get(i);                
            }
            ((JavaI18nString)i18nString).setArguments(arguments);
        } else {
            i18nString.setKey(key);
            i18nString.setValue(text);
            i18nString.setComment(""); // NOI18N
            // If generation of field is set and replace format doesn't include identifier argument replace it with the default with identifier.
            if (isGenerateField() && i18nString.getReplaceFormat().indexOf("{identifier}") == -1) { // NOI18N
                i18nString.setReplaceFormat(I18nUtil.getReplaceFormatItems().get(0));
            }
        }
        return i18nString;
    }
    private static final String octalDigitChars
                                = "01234567";                           //NOI18N
    private static final String hexaDigitChars
                                = "0123456789abcdefABCDEF";             //NOI18N

    
Translates Java Unicode sequences (\unnnn) to the corresponding characters.

Parameters:
text text with or without Unicode sequences
Returns:
the same text with Unicode sequences replaced with corresponding characters; may be the same instance as the passed text if there were no valid Unicode sequences present in it
Author(s):
Marian Petras
    private static String decodeUnicodeSeq(String text) {
        final StringBuilder result = new StringBuilder(text.length());
        final char[] chars = text.toCharArray();
        final int stateInitial = 0;
        final int stateBackSlash = 1;
        final int stateUnicode = 2;
        final int stateOctalValue = 3;
        int state = stateInitial;
        int unicodeValue = 0;
        char[] unicodeValueChars = new char[3];
        int valueBytesRead = 0;
        int position;
        int charIndex = 0;
        while (charIndex < chars.length) {
            char c = chars[charIndex++];
            switch (state) {
                case stateInitial:
                    if (c == '\\') {
                        state = stateBackSlash;
                    } else {
                        result.append(c);
                    }
                    break;
                case stateBackSlash:
                    if (c == 'u') {
                        state = stateUnicode;
                    } else if ((c >= '0') && (c <= '3')) {
                        unicodeValue = c - '0';
                        assert (unicodeValue >= 0) && (unicodeValue <= 3);
                        valueBytesRead = 1;
                        state = stateOctalValue;
                    } else {
                        result.append('\\').append(c);
                        state = stateInitial;
                    }
                    break;
                case stateOctalValue:
                    position = .indexOf(c);
                    if (position >= 0) {
                        unicodeValue = (unicodeValue << 3) | position;
                        valueBytesRead++;
                    } else {
                        charIndex--;    //handle the character in the next round
                    }
                    if ((position < 0) || (valueBytesRead == 3)) {
                        appendChar(resultunicodeValue);
                        state = stateInitial;
                        valueBytesRead = 0;
                        unicodeValue = 0;
                    }
                    break;
                case stateUnicode:
                    position = .indexOf(c);
                    if (position >= 0) {
                        if (position > 15) {   //one of [A-F] used
                            position -= 6;     //transform to lowercase
                        }
                        assert position <= 15;
                        unicodeValue = (unicodeValue << 4) | position;
                        if (++valueBytesRead == 4) {
                            appendChar(resultunicodeValue);
                            state = stateInitial;
                        } else {
                            unicodeValueChars[valueBytesRead - 1] = c;
                            /* keep the state at stateUnicode */
                        }
                    } else if (c == 'u') {
                        /*
                         * Handles \\u.... sequences with multiple
                         * 'u' characters, such as \\uuu1234 (which is legal).
                         */
                        /* keep the state at stateUnicode */
                    } else {
                        /* append the malformed Unicode sequence: */
                        result.append('\\');
                        result.append('u');
                        for (int i = 0; i < valueBytesReadi++) {
                            result.append(unicodeValueChars[i]);
                        }
                        result.append(c);
                        state = stateInitial;
                    }
                    if (state != stateUnicode) {
                        valueBytesRead = 0;
                        unicodeValue = 0;
                    }
                    break;
                default:
                    assert false;
                    throw new IllegalStateException();
            } //switch (state)
        } //for-loop
        switch (state) {
            case stateInitial:
                break;
            case stateBackSlash:
                result.append('\\');
                break;
            case stateOctalValue:
                assert (valueBytesRead >= 0) && (valueBytesRead < 3);
                appendChar(resultunicodeValue);
                break;
            case stateUnicode:
                /* append the incomplete Unicode sequence: */
                assert (valueBytesRead >= 0) && (valueBytesRead < 4);
                result.append('\\').append('u');
                for (int i = 0; i < valueBytesReadi++) {
                    result.append(unicodeValueChars[i]);
                }
                break;
            default:
                assert false;
                throw new IllegalStateException();
        }
        return result.toString();
    }

    
Appends a character to the given buffer.

Parameters:
buf buffer to which a character is to be added
unicodeValue Unicode value of the character to be appended; must be in range from 0 to 65535
Returns:
the passed buffer
    private static final StringBuilder appendChar(StringBuilder buf,
                                                  int unicodeValue)
                throws IllegalArgumentException {
        if ((unicodeValue < 0) || (unicodeValue > 0xffff)) {
            throw new IllegalArgumentException("value out of range: "   //NOI18N
                                               + unicodeValue);
        }
        /* append the Unicode character: */
        if ((unicodeValue >= 0x20) && (unicodeValue != 0x7f)) {
            buf.append((charunicodeValue);
        } else {
            buf.append('\\');
            switch (unicodeValue) {
                case 0x08:
                    buf.append('b');            //bell
                    break;
                case 0x09:
                    buf.append('t');            //tab
                    break;
                case 0x0a:
                    buf.append('n');            //NL
                    break;
                case 0x0c:
                    buf.append('f');            //FF
                    break;
                case 0x0d:
                    buf.append('r');            //CR
                    break;
                default:
                    buf.append('u');
                    for (int shift = 12; shift >= 0; shift -= 4) {
                        buf.append(.charAt(
                                ((unicodeValue >> shift) & 0xf)));
                    }
                    break;
            }
        }
        return buf;
    }
    
    
Implements I18nSupport superclass abstract method. Gets info panel about found hard string.
    public JPanel getInfo(HardCodedString hcString) {
        return new JavaInfoPanel(hcString);
    }

    
Getter for identifier.
    
    public String getIdentifier() {
        if (( == null) || ( == "")) {               //NOI18N
            createIdentifier();
        }
        return ;
    }

    
Setter for identifier.
    
    public void setIdentifier(String identifier) {
        this. = identifier;
    }

    
Getter for modifiers.
    public Set<ModifiergetModifiers() {
        return ;
    }
    
    
Setter for modifiers.
    public void setModifiers(Set<Modifiermodifiers) {
        this. = modifiers;
    }
    
    
Getter for generate field property
    public boolean isGenerateField() {
        return ;
    }
    
    
Setter for generate field property.
    public void setGenerateField(boolean generateField) {
        this. = generateField;
    }
    
    
Getter for init format property.
    public String getInitFormat() {
        return ;
    }
    
    
Setter for init format property.
    public void setInitFormat(String initFormat) {
        this. = initFormat;
    }

    
Overrides superclass method.
    @Override
    public PropertyPanel getPropertyPanel() {
        return new JavaPropertyPanel();
    }
    
    
Overrides superclass method.

Returns:
true
    @Override
    public boolean hasAdditionalCustomizer() {
        return true;
    }
    
    
Overrides superclass method.

Returns:
JavaReplacePanel which offers to customize additional source values (in our case for creating bundle field)
    @Override
    public JPanel getAdditionalCustomizer() {
        if ( == null
             = new JavaReplacePanel(this);
        return ;
    }

    
Overrides superclass method. Actuallay creates bundle field specified by user
    @Override
    public void performAdditionalChanges() {
        // Creates field.
        createField();
    }

    
Utility method. Creates identifier for this support instance.
    public void createIdentifier() {
        String name;
        
        try {
            name = .getResource().getName();
        } catch (NullPointerException npe) {
             = ""// NOI18N
            return;
        }
        // first letter to lowercase
        if (name.length() > 0) {
            name = name.substring(0, 1).toLowerCase() + name.substring(1);
        } else {
            name = name.toLowerCase();
        }
        
         = name;
    }

    
Task that adds a field to the internationalized Java source file.
    private final class AddFieldTask implements Task<WorkingCopy> {

        
name of the field to be added
        private final String fieldName;
        AddFieldTask(String fieldName) {
            this. = fieldName;
        }
        public void run(WorkingCopy workingCopythrows Exception {
            final TypeElement sourceClassElem = getClass(workingCopy);
            if (sourceClassElem == null) {
                return;
            }
            List<? extends javax.lang.model.element.ElementclassMembers
                    = sourceClassElem.getEnclosedElements();
            List<? extends VariableElementfields
                    = ElementFilter.fieldsIn(classMembers);
            if (containsField(fields)) {
                return;
            }
            int targetPosition = findTargetPosition(classMembersfields);
            final TreeMaker treeMaker = workingCopy.getTreeMaker();
            final Elements elements = workingCopy.getElements();
            final Trees trees = workingCopy.getTrees();
            final TreeUtilities treeUtilities = workingCopy.getTreeUtilities();
            TypeElement resourceBundleTypeElem = elements.getTypeElement(
                                            "java.util.ResourceBundle");//NOI18N
            assert resourceBundleTypeElem != null;
            ExpressionTree fieldDefaultValue
                    = treeUtilities.parseVariableInitializer(getInitString(),
                                                             new SourcePositions[1]);
            TreePath classTreePath = trees.getPath(sourceClassElem);
            Scope classScope = trees.getScope(classTreePath);
            if (classScope != null) {
                treeUtilities.attributeTree(fieldDefaultValueclassScope);
            }
            VariableTree field = treeMaker.Variable(
                    treeMaker.Modifiers(),
                    ,
                    treeMaker.QualIdent(resourceBundleTypeElem),
                    GeneratorUtilities.get(workingCopy).importFQNs(fieldDefaultValue));
            ClassTree oldClassTree = (ClassTreeclassTreePath.getLeaf();
            ClassTree newClassTree = (targetPosition != -1) 
                                     ? treeMaker.insertClassMember(oldClassTreetargetPositionfield)
                                     : treeMaker.addClassMember(oldClassTreefield);
            workingCopy.rewrite(oldClassTreenewClassTree);
        }

        
Finds the target position within the source class element. In the current implementation, the target position is just below the last static field of the class; if there is no static field in the class, the target position is the top of the class.

Parameters:
classMembers list of all members of the class
fields list of the fields in the class
Returns:
target position (0-based) of the field, or -1 if the field should be added to the end of the class
        private int findTargetPosition(
                List<? extends javax.lang.model.element.ElementclassMembers,
                List<? extends VariableElementfields) {
            if (fields.isEmpty()) {
                return 0;
            }
            int target = 0;
            boolean skippingStaticFields = false;
            Iterator<? extends javax.lang.model.element.ElementmembersIt
                    = classMembers.iterator();
            for (int index = 0; membersIt.hasNext(); index++) {
                javax.lang.model.element.Element member = membersIt.next();
                ElementKind kind = member.getKind();
                if (kind.isField()
                        && (kind != .)
                        && member.getModifiers().contains(.)) {
                    /* it is a static field - skip it! */
                    skippingStaticFields = true;
                } else if (skippingStaticFields) {
                    /* we were skipping all static fields - until now */
                    skippingStaticFields = false;
                    target = index;
                }
            }
            return !skippingStaticFields ? target : -1;
        }

        
Finds a main top-level class or a nested class element for sourceDataObject which should be initialized.
        private TypeElement getClass(WorkingCopy workingCopy)
                                                            throws IOException {
            workingCopy.toPhase(.);
            final String preferredName = .getName();
            TypeElement firstPublicNestedClass = null;
            
            List<? extends TypeElementtopClasses = workingCopy.getTopLevelElements();
            for (TypeElement topElement : topClasses) {
                ElementKind elementKind = topElement.getKind();
                if (!elementKind.isClass()) {
                    continue;
                }
                if (topElement.getSimpleName().contentEquals(preferredName)) {
                    return topElement;
                }
                if ((firstPublicNestedClass == null)
                        && topElement.getModifiers().contains(.)) {
                    firstPublicNestedClass = topElement;
                }
            }
            return firstPublicNestedClass;
        }

        
Checks whether the given class contains a field of the given name.

Parameters:
clazz class that should be searched
fieldName name of the field
Returns:
true if the class contains such a field, false otherwise
        private boolean containsField(List<? extends VariableElementfields,
                                      String fieldName) {
            if (!fields.isEmpty()) {
                for (VariableElement field : fields) {
                    if (field.getSimpleName().contentEquals(fieldName)) {
                        return true;
                    }
                }
            }
            return false;
        }
    
    }
    
    
Creates a new field which holds a reference to the resource holder (resource bundle). The field is added to the internationalized file.
    private void createField() {
        // Check if we have to generate field.
        if (!isGenerateField()) {
            return;
        }
        final JavaSource javaSource = JavaSource.forDocument();
        try {
            ModificationResult result
                    = javaSource.runModificationTask(new AddFieldTask(getIdentifier()));
            result.commit();
        } catch (Exception ex) {
            ErrorManager.getDefault().notify(.ex);
        }
    }

    
Helper method. Gets the string, the piece of code which initializes field resource bundle in the source. E.g.:
java.util.ResourceBundle <identifier name>
= java.util.ResourceBundle.getBundle("<package name>")

Returns:
String -> piece of initilizing code.
    public String getInitString() {
        String initJavaFormat = getInitFormat();
        // Create map.
        ClassPath cp = ClassPath.getClassPath(fo.);
        
        Map<String,Stringmap = new HashMap<String,String>(3);
        map.put("bundleNameSlashes"cp.getResourceName(fo'/'false));//NOI18N
        map.put("bundleNameDots"cp.getResourceName(fo'.'false));  //NOI18N
        map.put("sourceFileName", ( != null)
                                  ? .getPrimaryFile().getName()
                                  : "");                                //NOI18N
        return MapFormat.format(initJavaFormatmap);
        
    }
    
    
Replacer for java sources used by enclosing class.
    public static class JavaI18nReplacer implements I18nReplacer {
        
        
Constructor
        public JavaI18nReplacer() {
        }
        

        
Replaces found hard coded string in source.

Parameters:
hcString found hard coded string to-be replaced
rbString holds replacing values
        public void replace(final HardCodedString hcString,
                            final I18nString i18nString) {
            // comment out?
            if (i18nString.getKey() == null) {
                final StyledDocument document = i18nString.getSupport().getDocument();
                NbDocument.runAtomic(
                document,
                new Runnable() {
                    public void run() {
                        try {
                            // find the end of line
                            int idx = hcString.getEndPosition().getOffset() + 1;
                            String text = document.getText(idxdocument.getLength() - idx);
                            for (int i = idxidx-i < text.length() && text.charAt(idx-i) != '\n' ; idx++);
                            document.insertString(idx" //NOI18N"null); //NOI18N
                        } catch (BadLocationException ble) {
                            NotifyDescriptor.Message message
                                    = new NotifyDescriptor.Message(
                                            NbBundle.getMessage(JavaI18nSupport.class,
                                                                "MSG_CouldNotReplace"),//NOI18N
                                            .);
                            DialogDisplayer.getDefault().notify(message);
                        }
                    }
                });
                return;
            }
            if (!(i18nString instanceof JavaI18nString)) {
                throw new IllegalArgumentException(
                        "I18N module: i18nString have to be an instance of JavaI18nString.");//NOI18N
            }
            
            final String newCode = i18nString.getReplaceString();
            final StyledDocument document = i18nString.getSupport().getDocument();
            
            // Call runAtomic method to break guarded flag if it is necessary. (For non-guarded works as well).
            NbDocument.runAtomic(
            document,
            new Runnable() {
                public void run() {
                    try {
                        if (hcString.getLength() > 0) {
                            document.remove(hcString.getStartPosition().getOffset(),
                                            hcString.getLength());
                        }
                        if (newCode != null && newCode.length() > 0) {
                            document.insertString(hcString.getEndPosition().getOffset(),
                                                  newCodenull);
                        }
                    } catch (BadLocationException ble) {
                        NotifyDescriptor.Message message
                                = new NotifyDescriptor.Message(
                                        NbBundle.getMessage(JavaI18nSupport.class,
                                                            "MSG_CouldNotReplace"),//NOI18N
                                        .);
                        DialogDisplayer.getDefault().notify(message);
                    }
                }
            });
        }
    } // End of nested class JavaI18nReplacer.

    
    
Panel for showing info about hard coded string.
    private static class JavaInfoPanel extends InfoPanel {
        
        
Constructor.
        public JavaInfoPanel(HardCodedString hcStringStyledDocument document) {
            super(hcStringdocument);
        }
        
        
Implements superclass abstract method.
        protected void setHardCodedString(HardCodedString hcStringStyledDocument document) {
            getStringText().setText(hcString == null ? ""               //NOI18N
                                                     : hcString.getText());
            
            int pos;
            String hardLine;
            
            if (hcString.getStartPosition() == null) {
                hardLine = "";                                          //NOI18N
            } else {
                pos = hcString.getStartPosition().getOffset();
                try {
                    Element paragraph = document.getParagraphElement(pos);
                    hardLine = document.getText(paragraph.getStartOffset(),
                                                paragraph.getEndOffset() - paragraph.getStartOffset())
                                       .trim();
                } catch (BadLocationException ble) {
                    hardLine = ""// NOI18N
                }
            }
            getFoundInText().setText(hardLine);
            
            remove(getComponentLabel());
            remove(getComponentText());
            remove(getPropertyLabel());
            remove(getPropertyText());
        }
    } // End of JavaInfoPanel inner class.
    
    
    
Factory for JavaI18nSupport.
    public static class Factory extends I18nSupport.Factory {
        
        
Implements interface.
        public I18nSupport createI18nSupport(DataObject dataObject) {
            return new JavaI18nSupport(dataObject);
        }

        
Gets class of supported DataObject.

Returns:
JavaDataObject class or null if java module is not available
        public Class getDataObjectClass() {
            // XXX Cleaner should be this code dependend on java module
            // -> I18n API needed.
            try {
                return Class.forName(
                    "org.netbeans.modules.java.JavaDataObject"// NOI18N
                    false,
                    Lookup.getDefault().lookup(ClassLoader.class));
            } catch (ClassNotFoundException cnfe) {
                return null;
            }
        }
    } // End of class Factory.