diff options
Diffstat (limited to 'jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/validation/internal/strategy/AttributeValidatingStrategy.java')
-rw-r--r-- | jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/validation/internal/strategy/AttributeValidatingStrategy.java | 710 |
1 files changed, 0 insertions, 710 deletions
diff --git a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/validation/internal/strategy/AttributeValidatingStrategy.java b/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/validation/internal/strategy/AttributeValidatingStrategy.java deleted file mode 100644 index 7f887a21e..000000000 --- a/jsf/plugins/org.eclipse.jst.jsf.core/src/org/eclipse/jst/jsf/validation/internal/strategy/AttributeValidatingStrategy.java +++ /dev/null @@ -1,710 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2008 Oracle Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Oracle Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.jst.jsf.validation.internal.strategy; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.ISafeRunnable; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.SafeRunner; -import org.eclipse.emf.common.util.BasicDiagnostic; -import org.eclipse.emf.common.util.Diagnostic; -import org.eclipse.jdt.core.Signature; -import org.eclipse.jface.preference.IPreferenceStore; -import org.eclipse.jst.jsf.common.dom.AttrDOMAdapter; -import org.eclipse.jst.jsf.common.dom.AttributeIdentifier; -import org.eclipse.jst.jsf.common.dom.DOMAdapter; -import org.eclipse.jst.jsf.common.internal.types.CompositeType; -import org.eclipse.jst.jsf.common.internal.types.TypeComparator; -import org.eclipse.jst.jsf.common.internal.types.TypeComparatorDiagnosticFactory; -import org.eclipse.jst.jsf.common.internal.types.TypeConstants; -import org.eclipse.jst.jsf.common.internal.types.TypeTransformer; -import org.eclipse.jst.jsf.common.runtime.internal.model.ViewObject; -import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentFactory; -import org.eclipse.jst.jsf.common.runtime.internal.model.component.ComponentInfo; -import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ConverterDecorator; -import org.eclipse.jst.jsf.common.runtime.internal.model.decorator.ConverterTypeInfo; -import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext; -import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory; -import org.eclipse.jst.jsf.core.internal.JSFCorePlugin; -import org.eclipse.jst.jsf.core.internal.region.Region2AttrAdapter; -import org.eclipse.jst.jsf.core.internal.region.Region2ElementAdapter; -import org.eclipse.jst.jsf.core.jsfappconfig.internal.IJSFAppConfigManager; -import org.eclipse.jst.jsf.core.jsfappconfig.internal.JSFAppConfigManagerFactory; -import org.eclipse.jst.jsf.designtime.DTAppManagerUtil; -import org.eclipse.jst.jsf.designtime.internal.view.DTUIViewRoot; -import org.eclipse.jst.jsf.designtime.internal.view.IDTViewHandler.ViewHandlerException; -import org.eclipse.jst.jsf.designtime.internal.view.XMLViewDefnAdapter; -import org.eclipse.jst.jsf.designtime.internal.view.XMLViewDefnAdapter.DTELExpression; -import org.eclipse.jst.jsf.designtime.internal.view.XMLViewObjectMappingService; -import org.eclipse.jst.jsf.designtime.internal.view.XMLViewObjectMappingService.ElementData; -import org.eclipse.jst.jsf.facesconfig.emf.ConverterForClassType; -import org.eclipse.jst.jsf.facesconfig.emf.ConverterType; -import org.eclipse.jst.jsf.metadataprocessors.MetaDataEnabledProcessingFactory; -import org.eclipse.jst.jsf.metadataprocessors.features.ELIsNotValidException; -import org.eclipse.jst.jsf.metadataprocessors.features.IValidELValues; -import org.eclipse.jst.jsf.metadataprocessors.features.IValidValues; -import org.eclipse.jst.jsf.metadataprocessors.features.IValidationMessage; -import org.eclipse.jst.jsf.validation.internal.AbstractXMLViewValidationStrategy; -import org.eclipse.jst.jsf.validation.internal.JSFValidationContext; -import org.eclipse.jst.jsf.validation.internal.el.ELExpressionValidator; -import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection; -import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; -import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; - -/** - * An XML view validation strategy that validates - * - * @author cbateman - * - */ -public class AttributeValidatingStrategy extends -AbstractXMLViewValidationStrategy -{ - private static final String DISABLE_ALTERATIVE_TYPES_KEY = "jsfCoreDisableConverterValidation"; //$NON-NLS-1$ - static final boolean DEBUG; - static - { - final String value = Platform - .getDebugOption("org.eclipse.jst.jsf.validation.internal.el/debug/jspsemanticsvalidator"); //$NON-NLS-1$ - DEBUG = value != null && value.equalsIgnoreCase("true"); //$NON-NLS-1$ - } - - /** - * identifier - */ - public final static String ID = "org.eclipse.jst.jsf.validation.strategy.AttributeValidatingStrategy"; //$NON-NLS-1$ - private final static String DISPLAY_NAME = "Attribute Validator"; //$NON-NLS-1$ - - private final JSFValidationContext _validationContext; - private final TypeComparator _typeComparator; - private Set<String> _conversionTypes; - - /** - * Default constructor - * - * @param validationContext - */ - public AttributeValidatingStrategy(final JSFValidationContext validationContext) - { - super(ID, DISPLAY_NAME); - - _validationContext = validationContext; - _typeComparator = new TypeComparator( - new TypeComparatorDiagnosticFactory(validationContext - .getPrefs().getTypeComparatorPrefs())); - } - - @Override - public boolean isInteresting(final DOMAdapter domAdapter) - { - return (domAdapter instanceof AttrDOMAdapter); - } - - @Override - public void validate(final DOMAdapter domAdapter) - { - if (domAdapter instanceof AttrDOMAdapter) - { - final long curTime = System.nanoTime(); - final Region2AttrAdapter attrAdapter = (Region2AttrAdapter) domAdapter; - // check that this is attribute value region - 221722 - if (attrAdapter.getAttributeValueRegion() != null) - { - final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE - .getContext(attrAdapter.getDocumentContext() - .getStructuredDocument(), attrAdapter - .getOwningElement().getDocumentContext() - .getDocumentPosition() - + attrAdapter.getAttributeValueRegion() - .getStart()); - - validateAttributeValue(context, attrAdapter); - } - if (DEBUG) - { - System.out.println(String.format("Validation for attribute: %s took %d" //$NON-NLS-1$ - , domAdapter.toString() - , Long.valueOf(System.nanoTime()-curTime))); - } - } - } - - /** - * Validates the attribute value. Reports any problems to the reporter in - * the JSFValidationContext. - * - * @param context - * @param attrAdapter - */ - private void validateAttributeValue( - final IStructuredDocumentContext context, - final Region2AttrAdapter attrAdapter) - { - // so of the code in run calls out into extension code or code - // dependent on external data (meta-data) - SafeRunner.run(new ISafeRunnable() - { - public void handleException(final Throwable exception) - { - JSFCorePlugin.log(String.format( - "Error validating attribute: %s on element %s", //$NON-NLS-1$ - attrAdapter.getNodeName(), attrAdapter - .getOwningElement().getNodeName()), exception); - } - - public void run() throws Exception - { - final Region2ElementAdapter elementAdapter = - attrAdapter.getOwningElement(); - // if there's elText then validate it - // TODO: this approach will fail with mixed expressions - if (!checkIfELAndValidate(elementAdapter, attrAdapter, context)) - { - validateNonELAttributeValue(context, attrAdapter); - } - } - }); - } - - private boolean checkIfELAndValidate(final Region2ElementAdapter elementAdapter, - final Region2AttrAdapter attrAdapter, - final IStructuredDocumentContext context) - { - int offsetOfFirstEL = -1; - final String attrValue = attrAdapter.getValue(); - - // TODO: should find and validate all - offsetOfFirstEL = attrValue.indexOf('#'); - - if (offsetOfFirstEL != -1 && offsetOfFirstEL < attrValue.length() - 1 - && attrValue.charAt(offsetOfFirstEL + 1) == '{') - { - offsetOfFirstEL += 2; - } - else - { - offsetOfFirstEL = -1; - } - - final XMLViewDefnAdapter adapter = DTAppManagerUtil - .getXMLViewDefnAdapter(context); - - boolean isEL = false; - if (adapter != null && offsetOfFirstEL != -1) - { - try - { - // use the attribute's context plus the offset into the - // whole attribute value to find where we think the el - // expression starts. Add one since the attribute value - // string returned by attrAdapter will have the value quotes - // removed, but the region offsets include the quotes. - IStructuredDocumentContext elContext = IStructuredDocumentContextFactory.INSTANCE - .getContext(context.getStructuredDocument(), context - .getDocumentPosition() - + offsetOfFirstEL + 1); - final DTELExpression elExpression = adapter - .getELExpression(elContext); - if (elExpression != null) - { - final String elText = elExpression.getText(); - - if (DEBUG) - { - System.out.println(addDebugSpacer(3) + "EL attrVal= " //$NON-NLS-1$ - + elText); - } - - elContext = elExpression.getDocumentContext(); - // EL validation is user configurable because - // it can be computationally costly. - if (_validationContext.shouldValidateEL()) - { - // also, skip the validation if the expression is empty - // or only whitespace, since the parser doesn't handle - // it - // anyway. - if ("".equals(elText.trim())) //$NON-NLS-1$ - { - final int offset = elContext.getDocumentPosition() - 1; - final int length = elText.length() + 2; - final Diagnostic diagnostic = _validationContext - .getDiagnosticFactory() - .create_EMPTY_EL_EXPRESSION(); - // detected empty EL expression - if (_validationContext.shouldValidateEL()) - { - _validationContext.getReporter().report( - diagnostic, offset, length); - } - } - else - { - final List elVals = MetaDataEnabledProcessingFactory - .getInstance() - .getAttributeValueRuntimeTypeFeatureProcessors( - IValidELValues.class, - elContext, - attrAdapter - .getAttributeIdentifier()); - final String safeELText = elText.replaceAll( - "[\n\r\t]", " "); //$NON-NLS-1$ //$NON-NLS-2$ - validateELExpression(context, elContext, elVals, - elementAdapter, attrAdapter, safeELText); - isEL = true; - } - } - } - } - catch (final ViewHandlerException e) - { - // fall through to return false - } - } - - // is el if we've already detected it or if the step 2 method - // finds it. Run the method first to avoid short-circuiting - final boolean isEL2 = checkIfELAndValidate2(attrAdapter, context); - - return isEL || isEL2; - } - - /** - * Checks the region to see if it contains an EL attribute value. If it - * does, validates it - * - * @return true if validated EL, false otherwise - */ - private boolean checkIfELAndValidate2(final Region2AttrAdapter attrAdapter, - final IStructuredDocumentContext sDocContext) - { - final ITextRegion attrValueRegion = attrAdapter - .getAttributeValueRegion(); - if (attrValueRegion instanceof ITextRegionCollection) - { - final ITextRegionCollection parentRegion = ((ITextRegionCollection) attrValueRegion); - if (parentRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_VALUE) - { - final ITextRegionList regionList = parentRegion.getRegions(); - - if (regionList.size() >= 3) - { - final ITextRegion openQuote = regionList.get(0); - final ITextRegion vblOpen = regionList.get(1); - - if ((openQuote.getType() == DOMJSPRegionContexts.XML_TAG_ATTRIBUTE_VALUE_DQUOTE || openQuote - .getType() == DOMJSPRegionContexts.JSP_VBL_DQUOTE || - openQuote.getType() == DOMJSPRegionContexts.JSP_TAG_ATTRIBUTE_VALUE_DQUOTE) - && vblOpen.getType() == DOMJSPRegionContexts.JSP_VBL_OPEN) - { - boolean foundClosingQuote = false; - for (int i = 2; !foundClosingQuote - && i < regionList.size(); i++) - { - final ITextRegion searchRegion = regionList.get(i); - if (searchRegion.getType() == DOMJSPRegionContexts.JSP_VBL_CLOSE) - { - foundClosingQuote = true; - } - } - - if (!foundClosingQuote - && _validationContext.shouldValidateEL()) - { - final int offset = sDocContext - .getDocumentPosition() + 1; - final int length = parentRegion.getText().length(); - final Diagnostic diagnostic = _validationContext - .getDiagnosticFactory() - .create_MISSING_CLOSING_EXPR_BRACKET(); - _validationContext.getReporter().report(diagnostic, - offset, length); - } - return true; - } - } - } - } - return false; - } - - private void validateELExpression(final IStructuredDocumentContext context, - final IStructuredDocumentContext elContext, final List elVals, - final Region2ElementAdapter elementAdapter, - final Region2AttrAdapter attrAdapter, final String elText) - { - // Call EL validator which will perform at least the syntactical - // validation - final ELExpressionValidator elValidator = new ELExpressionValidator( - elContext, elText, _validationContext - .getSymbolResolverFactory(), _validationContext - .getReporter()); - elValidator.validateXMLNode(); - - final CompositeType exprType = elValidator.getExpressionType(); - if (exprType != null) - { - // Ignore the expression whose last two segments are of types Object. - final CompositeType boxedType = TypeTransformer - .transformBoxPrimitives(exprType); - final String[] testSignatures = boxedType.getSignatures(); - if (testSignatures.length > 0 && TypeConstants.TYPE_JAVAOBJECT.equals(testSignatures[0])) - { - if (elText.indexOf('.') != -1) - { - String elText2 = elText.substring(0, elText.lastIndexOf('.')); - final ELExpressionValidator elValidator2 = new ELExpressionValidator( - elContext, elText2, _validationContext - .getSymbolResolverFactory(), _validationContext - .getReporter()); - elValidator2.validateXMLNode(); - - final CompositeType exprType2 = elValidator.getExpressionType(); - final CompositeType boxedType2 = TypeTransformer.transformBoxPrimitives(exprType2); - final String[] testSignatures2 = boxedType2.getSignatures(); - if (testSignatures2.length > 0 && TypeConstants.TYPE_JAVAOBJECT.equals(testSignatures2[0])) - { - return; - } - } - } - - for (final Iterator it = elVals.iterator(); it.hasNext();) - { - final IValidELValues elval = (IValidELValues) it.next(); - final String attributeVal = attrAdapter.getValue(); - CompositeType expectedType; - Diagnostic status = null; - try - { - expectedType = elval.getExpectedRuntimeType(); - - if (expectedType != null) - { - expectedType = maybeAddAlternativeTypes( - expectedType, exprType, elementAdapter, - attrAdapter); - status = _typeComparator.calculateTypeCompatibility( - expectedType, exprType); - if (status.getSeverity() != Diagnostic.OK) - { - reportValidationMessage(status, context, - attributeVal); - } - } - } - catch (final ELIsNotValidException e) - { - reportValidationMessage(createValidationMessage(context, - attributeVal, IStatus.WARNING, e.getMessage(), - _validationContext.getFile()), context, - attributeVal); - } - } - } - } - - private boolean disableAlternativeTypes() - { - String res = System.getProperty(DISABLE_ALTERATIVE_TYPES_KEY); - if (res == null) { - //check env var also - res = System.getenv(DISABLE_ALTERATIVE_TYPES_KEY); - } - if (res != null) - { - return true; - } - final IPreferenceStore prefStore = JSFCorePlugin.getDefault().getPreferenceStore(); - return prefStore.getBoolean("org.eclipse.jst.jsf.core."+DISABLE_ALTERATIVE_TYPES_KEY); //$NON-NLS-1$ - } - /** - * @return true if alternative type comparison (i.e. post-conversion) passes - */ - private CompositeType maybeAddAlternativeTypes( - final CompositeType expectedType, final CompositeType exprTypes, - final Region2ElementAdapter elementAdapter, - final Region2AttrAdapter attrAdapter) - { - final long curTime = System.nanoTime(); - if (disableAlternativeTypes()) - { - return expectedType; - } - - final IStructuredDocumentContext context = elementAdapter - .getDocumentContext(); - final DTUIViewRoot viewRoot = _validationContext.getViewRootHandle().getCachedViewRoot(); - final IAdaptable serviceAdaptable = viewRoot.getServices(); - final XMLViewObjectMappingService mappingService = (XMLViewObjectMappingService) serviceAdaptable - .getAdapter(XMLViewObjectMappingService.class); - if (mappingService != null) - { - final ElementData elementData = XMLViewObjectMappingService - .createElementData(elementAdapter.getNamespace(), - elementAdapter.getLocalName(), context, - Collections.EMPTY_MAP); - final ViewObject viewObject = mappingService - .findViewObject(elementData); - // if the corresponding view object is a valueholder, then - // we need to see if you think there a valid conversion - // available - if (viewObject instanceof ComponentInfo - && ((ComponentInfo) viewObject).getComponentTypeInfo() != null - && ((ComponentInfo) viewObject).getComponentTypeInfo() - .isInstanceOf( - ComponentFactory.INTERFACE_VALUEHOLDER)) - { - final ComponentInfo component = (ComponentInfo) viewObject; - // get the original elementData - final ElementData mappedElementData = mappingService - .findElementData(component); - final String propName = mappedElementData - .getPropertyName(attrAdapter.getLocalName()); - if ("value".equals(propName)) //$NON-NLS-1$ - { - // final List converters = - // component.getDecorators(ComponentFactory.CONVERTER); - - // (ConverterDecorator) it.next(); - final CompositeType alternativeTypes = createCompositeType( - expectedType, exprTypes, component - .getDecorators(ComponentFactory.CONVERTER)); - if (DEBUG) - { - System.out.println(String.format( - "maybeAddAlternative took %d", Long.valueOf(System //$NON-NLS-1$ - .nanoTime() - - curTime))); - } - return alternativeTypes; - } - } - } - if (DEBUG) - { - System.out.println(String.format("maybeAddAlternative took %d", Long //$NON-NLS-1$ - .valueOf(System.nanoTime() - curTime))); - } - // don't add anything by default - return expectedType; - } - - private CompositeType createCompositeType(final CompositeType initialTypes, - final CompositeType testTypes, final List<ConverterDecorator> decorators) - { - // indicates unknown converter - final Set<String> types = new HashSet(Arrays.asList(initialTypes - .getSignatures())); - // look for converters. If there's one where we don't know the type, - // simply copy over the testTypes to force validation to ignore, since - // we have no idea. - for (final ConverterDecorator decorator : decorators) - { - if (decorator.getTypeInfo() != null) - { - final ConverterTypeInfo converterTypeInfo = decorator.getTypeInfo(); - if (converterTypeInfo.getForClass().length == 0) - { - types.addAll(Arrays.asList(testTypes.getSignatures())); - break; - } - types.addAll(createSignatures(converterTypeInfo.getForClass())); - } - } - types.addAll(getRegisteredConversionTypesByClass()); - return new CompositeType(types.toArray(new String[0]) - , initialTypes.getAssignmentTypeMask()); - } - - private Set<String> getRegisteredConversionTypesByClass() - { - if (_conversionTypes == null) - { - _conversionTypes = new HashSet<String>(); - final IProject project = _validationContext.getFile().getProject(); - final IJSFAppConfigManager appConfig = JSFAppConfigManagerFactory.getJSFAppConfigManagerInstance(project); - final List<ConverterType> converters = appConfig.getConverters(); - for (final ConverterType converterType : converters) - { - final ConverterForClassType forClassType = converterType.getConverterForClass(); - if (forClassType != null) - { - final String forClass = forClassType.getTextContent(); - if (forClass != null) - { - String signature = forClass.trim(); - try - { - // arrays are a special case where the - // [Ljava.lang.String; syntax is valid. - if (Signature.getArrayCount(signature)>0) - { - _conversionTypes.add(signature); - } - } - catch (final IllegalArgumentException e) - { - // ignore - } - - try - { - signature = Signature.createTypeSignature(signature, true); - _conversionTypes.add(signature); - } - catch (final Exception e) - { - // ignore: JSFCorePlugin.log(IStatus.INFO, "Could not use registered converter for-class: "+forClass); //$NON-NLS-1$ - } - } - } - } - } - return _conversionTypes; - } - - private List<String> createSignatures(final String[] classNames) - { - final List<String> signatures = new ArrayList<String>(); - for (final String className : classNames) - { - try - { - String signature = Signature.createTypeSignature(className, true); - signatures.add(signature); - } - catch (final Exception e) - { - JSFCorePlugin.log(e, "Trying to create signature"); //$NON-NLS-1$ - } - } - return signatures; - } - - /** - * Validates an attribute value in context using the JSF metadata processing - * framework - * - * @param context - * @param region - * @param uri - * @param tagName - * @param attrName - * @param attributeVal - * @param reporter - * @param file - */ - private void validateNonELAttributeValue( - final IStructuredDocumentContext context, - final Region2AttrAdapter attrAdapter) - { - final String attributeValue = attrAdapter.getValue(); - // else validate as static attribute value - if (DEBUG) - { - System.out.println(addDebugSpacer(3) + "attrVal= " //$NON-NLS-1$ - + (attributeValue != null ? attributeValue : "null")); //$NON-NLS-1$ - } - - final AttributeIdentifier attributeId = attrAdapter - .getAttributeIdentifier(); - - if (attributeId.getTagIdentifier() == null - || attributeId.getTagIdentifier().getTagName() == null - || attributeId.getName() == null) - { - return; - } - - final List vv = MetaDataEnabledProcessingFactory.getInstance() - .getAttributeValueRuntimeTypeFeatureProcessors( - IValidValues.class, context, attributeId); - if (!vv.isEmpty()) - { - for (final Iterator it = vv.iterator(); it.hasNext();) - { - final IValidValues v = (IValidValues) it.next(); - if (!v.isValidValue(attributeValue.trim())) - { - if (DEBUG) - { - System.out.println(addDebugSpacer(4) + "NOT VALID "); //$NON-NLS-1$ - } - - for (final Iterator msgs = v.getValidationMessages() - .iterator(); msgs.hasNext();) - { - final IValidationMessage msg = (IValidationMessage) msgs - .next(); - reportValidationMessage(createValidationMessage( - context, attributeValue, msg.getSeverity(), msg - .getMessage(), _validationContext - .getFile()), context, attributeValue); - } - } - else if (DEBUG) - { - System.out.println(addDebugSpacer(5) + "VALID "); //$NON-NLS-1$ - } - } - } - else if (DEBUG) - { - System.out.println(addDebugSpacer(4) + "NO META DATA "); //$NON-NLS-1$ - } - } - - private void reportValidationMessage(final Diagnostic problem, - final IStructuredDocumentContext context, - final String attributeValue) - { - final int start = context.getDocumentPosition() + 1; - final int length = attributeValue.length(); - _validationContext.getReporter().report(problem, start, length); - } - - private Diagnostic createValidationMessage( - final IStructuredDocumentContext context, - final String attributeValue, final int severity, final String msg, - final IFile file) - { - // TODO: need factory - final Diagnostic diagnostic = new BasicDiagnostic(severity, "", -1, //$NON-NLS-1$ - msg, null); - return diagnostic; - } - - private String addDebugSpacer(final int count) - { - final String TAB = "\t"; //$NON-NLS-1$ - final StringBuffer ret = new StringBuffer(""); //$NON-NLS-1$ - for (int i = 0; i <= count; i++) - { - ret.append(TAB); - } - return ret.toString(); - } - -} |