/****************************************************************************** * Copyright (c) 2016 Oracle * 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: * Konstantin Komissarchik - initial implementation and ongoing maintenance ******************************************************************************/ package org.eclipse.sapphire; import java.util.HashMap; import java.util.Locale; import java.util.Map; import org.eclipse.sapphire.modeling.CorruptedResourceExceptionInterceptor; import org.eclipse.sapphire.modeling.ElementPropertyBinding; import org.eclipse.sapphire.modeling.ResourceStoreException; import org.eclipse.sapphire.modeling.localization.LocalizationService; import org.eclipse.sapphire.modeling.localization.SourceLanguageLocalizationService; /** * @author <a href="mailto:konstantin.komissarchik@oracle.com">Konstantin Komissarchik</a> */ public abstract class Resource implements Disposable { private final Resource parent; private Element element; private final Map<Property,PropertyBinding> bindings = new HashMap<Property,PropertyBinding>(); private CorruptedResourceExceptionInterceptor corruptedResourceExceptionInterceptor; private final Map<Locale,LocalizationService> localizationServices = new HashMap<Locale,LocalizationService>(); public Resource( final Resource parent ) { this.parent = parent; } public void init( final Element element ) { if( this.element != null ) { throw new IllegalStateException(); } this.element = element; } public Resource parent() { return this.parent; } public Resource root() { if( this.parent == null ) { return this; } else { return this.parent.root(); } } public final Element element() { return this.element; } public final PropertyBinding binding( final PropertyDef property ) { return binding( this.element.property( property ) ); } public final ValuePropertyBinding binding( final ValueProperty property ) { return (ValuePropertyBinding) binding( (PropertyDef) property ); } public final ElementPropertyBinding binding( final ElementProperty property ) { return (ElementPropertyBinding) binding( (PropertyDef) property ); } public final ListPropertyBinding binding( final ListProperty property ) { return (ListPropertyBinding) binding( (PropertyDef) property ); } public final PropertyBinding binding( final Property property ) { PropertyBinding binding = this.bindings.get( property ); if( binding == null ) { binding = createBinding( property ); if( binding == null ) { throw new IllegalArgumentException(); } binding.init( property ); this.bindings.put( property, binding ); } return binding; } protected abstract PropertyBinding createBinding( final Property property ); /** * @throws ResourceStoreException */ public void save() throws ResourceStoreException { final Resource root = root(); if( this != root ) { root.save(); } } public <A> A adapt( final Class<A> adapterType ) { A result = Sapphire.service( MasterConversionService.class ).convert( this, adapterType ); if( result == null ) { if( adapterType.isInstance( this ) ) { result = adapterType.cast( this ); } else if( adapterType == LocalizationService.class ) { result = adapterType.cast( getLocalizationService() ); } else if( this.parent != null ) { result = this.parent.adapt( adapterType ); } } return result; } public boolean isOutOfDate() { final Resource root = root(); if( this != root ) { return root.isOutOfDate(); } return false; } public final LocalizationService getLocalizationService() { return getLocalizationService( Locale.getDefault() ); } public final LocalizationService getLocalizationService( final Locale locale ) { synchronized( this.localizationServices ) { LocalizationService service = this.localizationServices.get( locale ); if( service == null ) { service = initLocalizationService( locale ); if( service != null ) { this.localizationServices.put( locale, service ); } } return service; } } protected LocalizationService initLocalizationService( final Locale locale ) { final Resource root = root(); if( this != root ) { return root.getLocalizationService( locale ); } return SourceLanguageLocalizationService.INSTANCE; } public final void setCorruptedResourceExceptionInterceptor( final CorruptedResourceExceptionInterceptor interceptor ) { this.corruptedResourceExceptionInterceptor = interceptor; } protected final boolean validateCorruptedResourceRecovery() { if( this.corruptedResourceExceptionInterceptor != null ) { return this.corruptedResourceExceptionInterceptor.shouldAttemptRepair(); } return false; } @Override public void dispose() { for( PropertyBinding binding : this.bindings.values() ) { try { binding.dispose(); } catch( Exception e ) { Sapphire.service( LoggingService.class ).log( e ); } } } }