| /* |
| * 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.apache.felix.metatype; |
| |
| |
| import java.util.*; |
| |
| import org.apache.felix.metatype.internal.Activator; |
| import org.osgi.service.log.LogService; |
| import org.osgi.service.metatype.AttributeDefinition; |
| |
| |
| /** |
| * The <code>AD</code> class represents the <code>AD</code> element of the |
| * meta type descriptor. |
| * |
| * @author fmeschbe |
| */ |
| public class AD |
| { |
| |
| /** |
| * The message returned from the {@link #validate(String)} method if the |
| * value is not any of the specified {@link #getOptionValues() option values} |
| * (value is "%not a valid option"). |
| */ |
| public static final String VALIDATE_NOT_A_VALID_OPTION = "%not a valid option"; |
| |
| /** |
| * The message returned from the {@link #validate(String)} method if the |
| * value is greater than the specified {@link #getMax() maximum value} |
| * (value is "%greater than maximum"). |
| */ |
| public static final String VALIDATE_GREATER_THAN_MAXIMUM = "%greater than maximum"; |
| |
| /** |
| * The message returned from the {@link #validate(String)} method if the |
| * value is less than the specified {@link #getMin() minimum value} |
| * (value is "%less than minimum"). |
| */ |
| public static final String VALIDATE_LESS_THAN_MINIMUM = "%less than minimum"; |
| |
| private String id; |
| private String name; |
| private String description; |
| private int type; |
| private int cardinality = 0; |
| private String[] optionLabels; |
| private String[] optionValues; |
| private String[] defaultValue; |
| private String min; |
| private String max; |
| private boolean isRequired = true; |
| |
| |
| public String getID() |
| { |
| return id; |
| } |
| |
| |
| public String getName() |
| { |
| return name; |
| } |
| |
| |
| public String getDescription() |
| { |
| return description; |
| } |
| |
| |
| public int getType() |
| { |
| return type; |
| } |
| |
| |
| public int getCardinality() |
| { |
| return cardinality; |
| } |
| |
| |
| public String[] getOptionLabels() |
| { |
| return optionLabels; |
| } |
| |
| |
| public String[] getOptionValues() |
| { |
| return optionValues; |
| } |
| |
| |
| public String[] getDefaultValue() |
| { |
| return defaultValue; |
| } |
| |
| |
| public String getMin() |
| { |
| return min; |
| } |
| |
| |
| public String getMax() |
| { |
| return max; |
| } |
| |
| |
| public boolean isRequired() |
| { |
| return isRequired; |
| } |
| |
| |
| /** |
| * Implements validation of the <code>valueString</code> and returns an |
| * indication of the success: |
| * <dl> |
| * <dt><code>null</code> |
| * <dd>If neither a {@link #getMin() minimal value} nor a |
| * {@link #getMax() maximal value} nor any |
| * {@link #getOptionValues() optional values} are defined in this |
| * instance, validation cannot be performed. |
| * <dt>Empty String |
| * <dd>If validation succeeds. This value is also returned if the |
| * <code>valueString</code> is empty or <code>null</code> or cannot be |
| * converted into a numeric type. |
| * <dt><b>%</b>message |
| * <dd>If the value falls below the minimum, higher than the maximum or is |
| * not any of the option values, an explanatory message, which may be |
| * localized is returned. If any of the minimum, maximum or option |
| * values is <code>null</code>, the respective value is not checked. |
| * </dl> |
| * |
| * @param valueString The string representation of the value to validate. |
| * |
| * @return As explained above. |
| * |
| * @see #VALIDATE_GREATER_THAN_MAXIMUM |
| * @see #VALIDATE_LESS_THAN_MINIMUM |
| * @see #VALIDATE_NOT_A_VALID_OPTION |
| */ |
| public String validate( String valueString ) |
| { |
| // no validation if no min and max |
| if ( getMin() == null && getMax() == null && getOptionValues() == null ) |
| { |
| return null; |
| } |
| |
| Comparable value = convertToType( valueString ); |
| if ( value == null ) |
| { |
| return ""; // accept null value |
| } |
| |
| Comparable other = convertToType( getMin() ); |
| if ( other != null ) |
| { |
| if ( value.compareTo( other ) < 0 ) |
| { |
| return VALIDATE_LESS_THAN_MINIMUM; |
| } |
| } |
| |
| other = convertToType( getMax() ); |
| if ( other != null ) |
| { |
| if ( value.compareTo( other ) > 0 ) |
| { |
| return VALIDATE_GREATER_THAN_MAXIMUM; |
| } |
| } |
| |
| String[] optionValues = getOptionValues(); |
| if ( optionValues != null && optionValues.length > 0) |
| { |
| for ( int i = 0; i < optionValues.length; i++ ) |
| { |
| other = convertToType( optionValues[i] ); |
| if ( value.compareTo( other ) == 0 ) |
| { |
| // one of the option values |
| return ""; |
| } |
| } |
| |
| // not any of the option values, fail |
| return VALIDATE_NOT_A_VALID_OPTION; |
| } |
| |
| // finally, we accept the value |
| return ""; |
| } |
| |
| |
| //--------- Setters for setting up this instance -------------------------- |
| |
| /** |
| * @param id the id to set |
| */ |
| public void setID( String id ) |
| { |
| this.id = id; |
| } |
| |
| |
| /** |
| * @param name the name to set |
| */ |
| public void setName( String name ) |
| { |
| this.name = name; |
| } |
| |
| |
| /** |
| * @param description the description to set |
| */ |
| public void setDescription( String description ) |
| { |
| this.description = description; |
| } |
| |
| |
| /** |
| * @param typeString the type to set |
| */ |
| public void setType( String typeString ) |
| { |
| this.type = toType( typeString ); |
| } |
| |
| |
| /** |
| * @param cardinality the cardinality to set |
| */ |
| public void setCardinality( int cardinality ) |
| { |
| this.cardinality = cardinality; |
| } |
| |
| |
| /** |
| * @param options the options to set |
| */ |
| public void setOptions( Map options ) |
| { |
| optionLabels = new String[options.size()]; |
| optionValues = new String[options.size()]; |
| int i = 0; |
| for ( Iterator oi = options.entrySet().iterator(); oi.hasNext(); i++ ) |
| { |
| Map.Entry entry = ( Map.Entry ) oi.next(); |
| optionValues[i] = String.valueOf( entry.getKey() ); |
| optionLabels[i] = String.valueOf( entry.getValue() ); |
| } |
| } |
| |
| |
| /** |
| * @param defaultValue the defaultValue to set |
| */ |
| public void setDefaultValue( String defaultValue ) |
| { |
| this.defaultValue = splitList( defaultValue ); |
| } |
| |
| |
| /** |
| * @param min the min to set |
| */ |
| public void setMin( String min ) |
| { |
| this.min = min; |
| } |
| |
| |
| /** |
| * @param max the max to set |
| */ |
| public void setMax( String max ) |
| { |
| this.max = max; |
| } |
| |
| |
| /** |
| * @param defaultValue the defaultValue to set |
| */ |
| public void setDefaultValue( String[] defaultValue ) |
| { |
| this.defaultValue = ( String[] ) defaultValue.clone(); |
| } |
| |
| |
| /** |
| * @param isRequired the isRequired to set |
| */ |
| public void setRequired( boolean isRequired ) |
| { |
| this.isRequired = isRequired; |
| } |
| |
| |
| public static int toType( String typeString ) |
| { |
| if ( "String".equals( typeString ) ) |
| { |
| return AttributeDefinition.STRING; |
| } |
| else if ( "Long".equals( typeString ) ) |
| { |
| return AttributeDefinition.LONG; |
| } |
| else if ( "Double".equals( typeString ) ) |
| { |
| return AttributeDefinition.DOUBLE; |
| } |
| else if ( "Float".equals( typeString ) ) |
| { |
| return AttributeDefinition.FLOAT; |
| } |
| else if ( "Integer".equals( typeString ) ) |
| { |
| return AttributeDefinition.INTEGER; |
| } |
| else if ( "Byte".equals( typeString ) ) |
| { |
| return AttributeDefinition.BYTE; |
| } |
| else if ( "Char".equals( typeString ) ) |
| { |
| return AttributeDefinition.CHARACTER; |
| } |
| else if ( "Boolean".equals( typeString ) ) |
| { |
| return AttributeDefinition.BOOLEAN; |
| } |
| else if ( "Short".equals( typeString ) ) |
| { |
| return AttributeDefinition.SHORT; |
| } |
| |
| // finally fall back to string for illegal values |
| return AttributeDefinition.STRING; |
| } |
| |
| |
| public static String[] splitList( String listString ) |
| { |
| // return nothing ... |
| if ( listString == null ) |
| { |
| return null; |
| } |
| |
| List values = new ArrayList(); |
| boolean escape = false; |
| StringBuffer buf = new StringBuffer(); |
| for ( int i = 0; i < listString.length(); i++ ) |
| { |
| char c = listString.charAt( i ); |
| |
| if ( escape ) |
| { |
| // just go ahead |
| escape = false; |
| } |
| else if ( c == ',' ) |
| { |
| String value = buf.toString().trim(); |
| if ( value.length() > 0 ) |
| { |
| values.add( value ); |
| } |
| buf.delete( 0, buf.length() ); |
| continue; |
| } |
| else if ( c == '\\' ) |
| { |
| escape = true; |
| continue; |
| } |
| |
| buf.append( c ); |
| } |
| |
| // add last string |
| if ( buf.length() > 0 ) |
| { |
| String value = buf.toString().trim(); |
| if ( value.length() > 0 ) |
| { |
| values.add( value ); |
| } |
| } |
| |
| return values.isEmpty() ? null : ( String[] ) values.toArray( new String[values.size()] ); |
| } |
| |
| |
| protected Comparable convertToType( final String value ) |
| { |
| if ( value != null && value.length() > 0 ) |
| { |
| try |
| { |
| switch ( getType() ) |
| { |
| case AttributeDefinition.BOOLEAN: |
| // Boolean is only Comparable starting with Java 5 |
| return new ComparableBoolean(value); |
| case AttributeDefinition.CHARACTER: |
| return new Character( value.charAt( 0 ) ); |
| case AttributeDefinition.BYTE: |
| return Byte.valueOf( value ); |
| case AttributeDefinition.SHORT: |
| return Short.valueOf( value ); |
| case AttributeDefinition.INTEGER: |
| return Integer.valueOf( value ); |
| case AttributeDefinition.LONG: |
| return Long.valueOf( value ); |
| case AttributeDefinition.FLOAT: |
| return Float.valueOf( value ); |
| case AttributeDefinition.DOUBLE: |
| return Double.valueOf( value ); |
| case AttributeDefinition.STRING: |
| default: |
| return value; |
| } |
| } |
| catch ( NumberFormatException nfe ) |
| { |
| Activator.log( LogService.LOG_INFO, "Cannot convert value '" + value + "'", nfe ); |
| } |
| } |
| |
| return null; |
| } |
| |
| private static class ComparableBoolean implements Comparable { |
| private boolean value; |
| |
| ComparableBoolean(String boolValue) { |
| value = Boolean.valueOf(boolValue).booleanValue(); |
| } |
| |
| public int compareTo(Object obj) { |
| ComparableBoolean cb = (ComparableBoolean) obj; |
| return (cb.value == value ? 0 : (value ? 1 : -1)); |
| } |
| } |
| } |