/**
* Copyright 2013-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* Licensed 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 net.roboconf.core.model.beans;
import java.io.File;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import net.roboconf.core.model.helpers.InstanceHelpers;
/**
* An application groups an identifier, graph definitions and instances.
* @author Vincent Zurczak - Linagora
*/
public class Application extends AbstractApplication implements Serializable {
private static final long serialVersionUID = -4753958407033243184L;
private final ApplicationTemplate template;
private final Map<String,Set<String>> applicationBindings = new ConcurrentHashMap<> ();
/**
* Constructor.
* @param template
*/
public Application( ApplicationTemplate template ) {
this.template = template;
// We must duplicate all the instances
if( template != null ) {
template.associateApplication( this );
for( Instance rootInstance : template.getRootInstances())
getRootInstances().add( InstanceHelpers.replicateInstance( rootInstance ));
}
}
/**
* Constructor.
* @param name
* @param template
*/
public Application( String name, ApplicationTemplate template ) {
this( template );
setName( name );
}
/**
* @return the template
*/
public ApplicationTemplate getTemplate() {
return this.template;
}
@Override
public Graphs getGraphs() {
return this.template == null ? null : this.template.getGraphs();
}
/**
* A shortcut method to access the template's external exports mapping.
* @return a non-null map
*/
public Map<String,String> getExternalExports() {
return this.template != null ? this.template.externalExports : new HashMap<String,String>( 0 );
}
@Override
public boolean equals( Object obj ) {
return obj instanceof Application
&& Objects.equals( this.name, ((Application) obj ).getName());
}
@Override
public int hashCode() {
return this.name == null ? 29 : this.name.hashCode();
}
/**
* Sets the name in a chain approach.
*/
public Application name( String name ) {
this.name = name;
return this;
}
/**
* Sets the description in a chain approach.
*/
public Application description( String description ) {
this.description = description;
return this;
}
/**
* Sets the directory in a chain approach.
*/
public Application directory( File directory ) {
this.directory = directory;
return this;
}
/**
* Removes the association between this application and its template.
*/
public void removeAssociationWithTemplate() {
if( this.template != null )
this.template.removeApplicationAssocation( this );
}
/**
* Binds an external export prefix with an application name.
* <p>
* No error is thrown if the bound already existed.
* </p>
*
* @param externalExportPrefix an external export prefix (not null)
* @param applicationName an application name (not null)
*/
public void bindWithApplication( String externalExportPrefix, String applicationName ) {
Set<String> bounds = this.applicationBindings.get( externalExportPrefix );
if( bounds == null ) {
bounds = new LinkedHashSet<> ();
this.applicationBindings.put( externalExportPrefix, bounds );
}
bounds.add( applicationName );
}
/**
* Unbinds an external export prefix from an application name.
* <p>
* No error is thrown if the bound did not exist.
* </p>
*
* @param externalExportPrefix an external export prefix (not null)
* @param applicationName an application name (not null)
* @return true if bindings were modified, false if no binding existed
*/
public boolean unbindFromApplication( String externalExportPrefix, String applicationName ) {
boolean result = false;
Set<String> bounds = this.applicationBindings.get( externalExportPrefix );
if( bounds != null ) {
result = bounds.remove( applicationName );
if( bounds.isEmpty())
this.applicationBindings.remove( externalExportPrefix );
}
return result;
}
/**
* Replaces application bindings for a given prefix.
* @param externalExportPrefix an external export prefix (not null)
* @param applicationNames a non-null set of application names
* @return true if bindings were modified, false otherwise
*/
public boolean replaceApplicationBindings( String externalExportPrefix, Set<String> applicationNames ) {
// There is a change if the set do not have the same size or if they do not contain the same
// number of element. If no binding had been registered previously, then we only check whether
// the new set contains something.
boolean changed = false;
Set<String> oldApplicationNames = this.applicationBindings.remove( externalExportPrefix );
if( oldApplicationNames == null ) {
changed = ! applicationNames.isEmpty();
} else if( oldApplicationNames.size() != applicationNames.size()) {
changed = true;
} else {
oldApplicationNames.removeAll( applicationNames );
changed = ! oldApplicationNames.isEmpty();
}
// Do not register keys when there is no binding
if( ! applicationNames.isEmpty())
this.applicationBindings.put( externalExportPrefix, applicationNames );
return changed;
}
/**
* @return the applicationBindings
*/
public Map<String,Set<String>> getApplicationBindings() {
return Collections.unmodifiableMap( this.applicationBindings );
}
}