/* * 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.getResource( 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; } } }