| /* |
| * 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.internal; |
| |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.*; |
| |
| import org.apache.felix.metatype.AD; |
| import org.apache.felix.metatype.OCD; |
| import org.apache.felix.metatype.internal.l10n.Resources; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.metatype.AttributeDefinition; |
| import org.osgi.service.metatype.ObjectClassDefinition; |
| |
| |
| /** |
| * The <code>LocalizedObjectClassDefinition</code> class is the implementation |
| * of the <code>ObjectClassDefinition</code> interface. This class delegates |
| * calls to the underlying {@link OCD} localizing the results of the following |
| * methods: {@link #getName()}, {@link #getDescription()}, and |
| * {@link #getIcon(int)}. |
| * |
| * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> |
| */ |
| public class LocalizedObjectClassDefinition extends LocalizedBase implements ObjectClassDefinition |
| { |
| |
| private Bundle bundle; |
| |
| private OCD ocd; |
| |
| |
| /** |
| * Creates and instance of this localizing facade. |
| * |
| * @param bundle The <code>Bundle</code> providing this object class |
| * definition. |
| * @param ocd The {@link OCD} to which calls are delegated. |
| * @param resources The {@link Resources} used to localize return values of |
| * localizable methods. |
| */ |
| public LocalizedObjectClassDefinition( Bundle bundle, OCD ocd, Resources resources ) |
| { |
| super( resources ); |
| this.bundle = bundle; |
| this.ocd = ocd; |
| } |
| |
| |
| /** |
| * @param filter |
| * @see org.osgi.service.metatype.ObjectClassDefinition#getAttributeDefinitions(int) |
| */ |
| public AttributeDefinition[] getAttributeDefinitions( int filter ) |
| { |
| if ( ocd.getAttributeDefinitions() == null ) |
| { |
| return null; |
| } |
| |
| Iterator adhIter = ocd.getAttributeDefinitions().values().iterator(); |
| if ( filter == ObjectClassDefinition.OPTIONAL || filter == ObjectClassDefinition.REQUIRED ) |
| { |
| boolean required = ( filter == ObjectClassDefinition.REQUIRED ); |
| adhIter = new RequiredFilterIterator( adhIter, required ); |
| } |
| else if ( filter != ObjectClassDefinition.ALL ) |
| { |
| return null; |
| } |
| |
| if ( !adhIter.hasNext() ) |
| { |
| return null; |
| } |
| |
| List result = new ArrayList(); |
| while ( adhIter.hasNext() ) |
| { |
| result.add( new LocalizedAttributeDefinition( ( AD ) adhIter.next(), getResources() ) ); |
| } |
| |
| return ( AttributeDefinition[] ) result.toArray( new AttributeDefinition[result.size()] ); |
| } |
| |
| |
| /** |
| * @see org.osgi.service.metatype.ObjectClassDefinition#getDescription() |
| */ |
| public String getDescription() |
| { |
| return localize( ocd.getDescription() ); |
| } |
| |
| |
| /** |
| * @see org.osgi.service.metatype.ObjectClassDefinition#getIcon(int) |
| */ |
| public InputStream getIcon( int desiredSize ) throws IOException |
| { |
| // nothing if no icons are defined |
| Map icons = ocd.getIcons(); |
| if ( icons == null ) |
| { |
| return null; |
| } |
| |
| // get exact size |
| String iconPath = ( String ) icons.get( new Integer( desiredSize ) ); |
| |
| if ( iconPath == null ) |
| { |
| // approximate size: largest icon smaller than requested |
| Integer selectedSize = new Integer( Integer.MIN_VALUE ); |
| for ( Iterator ei = icons.keySet().iterator(); ei.hasNext(); ) |
| { |
| Integer iconSize = ( Integer ) ei.next(); |
| if ( iconSize.intValue() <= desiredSize && selectedSize.compareTo( iconSize ) < 0 ) |
| { |
| selectedSize = iconSize; |
| } |
| } |
| // get the raw path, fail if no path can be found |
| iconPath = ( String ) icons.get( selectedSize ); |
| } |
| |
| // localize the path |
| iconPath = localize( iconPath ); |
| |
| // fail if no icon could be found (or localization returned null) |
| if ( iconPath == null ) |
| { |
| return null; |
| } |
| |
| // just create an URL based on the source of the metadata |
| // see FELIX2868 |
| URL url = this.bundle.getEntry( iconPath ); |
| if ( url == null ) |
| { |
| url = new URL( this.ocd.getMetadata().getSource(), iconPath ); |
| } |
| return url.openStream(); |
| } |
| |
| |
| /** |
| * @see org.osgi.service.metatype.ObjectClassDefinition#getID() |
| */ |
| public String getID() |
| { |
| return ocd.getID(); |
| } |
| |
| |
| /** |
| * @see org.osgi.service.metatype.ObjectClassDefinition#getName() |
| */ |
| public String getName() |
| { |
| return localize( ocd.getName() ); |
| } |
| |
| private static class RequiredFilterIterator implements Iterator |
| { |
| |
| private final Iterator base; |
| |
| private final boolean required; |
| |
| private AD next; |
| |
| |
| private RequiredFilterIterator( Iterator base, boolean required ) |
| { |
| this.base = base; |
| this.required = required; |
| this.next = seek(); |
| } |
| |
| |
| public boolean hasNext() |
| { |
| return next != null; |
| } |
| |
| |
| public Object next() |
| { |
| if ( !hasNext() ) |
| { |
| throw new NoSuchElementException(); |
| } |
| |
| AD toReturn = next; |
| next = seek(); |
| return toReturn; |
| } |
| |
| |
| public void remove() |
| { |
| throw new UnsupportedOperationException( "remove" ); |
| } |
| |
| |
| private AD seek() |
| { |
| if ( base.hasNext() ) |
| { |
| AD next; |
| do |
| { |
| next = ( AD ) base.next(); |
| } |
| while ( next.isRequired() != required && base.hasNext() ); |
| |
| if ( next.isRequired() == required ) |
| { |
| return next; |
| } |
| } |
| |
| // nothing found any more |
| return null; |
| } |
| |
| } |
| } |