/**
* Copyright (C) 2013 Kametic <epo.jemba@kametic.com>
*
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June 2007;
* or any later version
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
* 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.nuunframework.kernel.api.topology.grapher;
import static com.google.common.base.Preconditions.checkState;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.nuunframework.kernel.commons.specification.Specification;
public class GrapherInternal implements Grapher, Grapher2, Grapher3, Grapher5, Grapher6
{
final Map<String, Object> all;
public final Map<String, instance> instancesByName;
public final List<instance> instances;
public final List<reference> references;
private reference currentReference;
private instance currentInstance;
public static class instance
{
public final String name;
public final Class<?> type;
public final Set<reference> references = new HashSet<GrapherInternal.reference>();
public final Collection<String> subInstances = new HashSet<String>();
public final Map<Object, Object> properties = new HashMap<Object, Object>();
public final Specification<Class<?>> specification;
public instance(String name )
{
this.name = name;
this.type = null;
this.specification = null;
}
public instance(String name , Class<?> type )
{
this.name = name;
this.type = type;
this.specification = null;
}
public instance(String name, Specification<Class<?>> specification)
{
this.name = name;
this.specification = specification;
this.type = null;
}
}
public static class reference
{
public final String name;
public final String target;
public final String source;
public final Map<Object, Object> properties = new HashMap<Object, Object>();
public reference(String name, String target , String source)
{
this.name = name;
this.target = target;
this.source = source;
}
}
public GrapherInternal()
{
all = new HashMap<String, Object>();
instancesByName = new HashMap<String, instance>();
instances = new ArrayList<GrapherInternal.instance>();
references = new ArrayList<GrapherInternal.reference>();
}
@Override
public Grapher3 newInstance(String name)
{
clearReference();
checkNotExisting(name);
currentInstance = new instance(name);
all.put( name , currentInstance);
instances.add(currentInstance);
instancesByName.put(name, currentInstance);
return this;
}
@Override
public Grapher3 newInstance(String name, Class<?> type)
{
clearReference();
checkNotExisting(name);
currentInstance = new instance(name,type);
all.put( name , currentInstance);
instances.add(currentInstance);
instancesByName.put(name, currentInstance);
return this;
}
@Override
public Grapher3 newSpecificationInstance(String name,Specification<Class<?>> specification)
{
clearReference();
checkNotExisting(name);
currentInstance = new instance(name,specification);
all.put( name , currentInstance);
instances.add(currentInstance);
instancesByName.put(name, currentInstance);
return this;
}
@Override
public Grapher6 newCompositeInstance(String name)
{
clearReference();
checkNotExisting(name);
currentInstance = new instance(name);
all.put( name , currentInstance);
instances.add(currentInstance);
instancesByName.put(name, currentInstance);
return this;
}
@Override
public Grapher3 withChildInstances ( String... names )
{
checkState(currentInstance != null , "currentInstance should not be null");
checkState(names != null , "Child Instance should be not null");
for (String name : names)
{
currentInstance.subInstances.add( name );
}
return this;
}
////////////////////////////////////////////////////////
String currentName;
String currentSource;
String currentTarget;
@Override
public Grapher2 newReference(String referenceName)
{
clearInstance();
boolean expression =
( currentName != null && currentSource != null && currentTarget != null)
|| (currentName == null && currentSource == null && currentTarget == null);
checkState( expression , "Invalid Use of the dsl");
currentName = currentSource = currentTarget = null;
currentReference = null;
currentName = referenceName;
return this;
}
@Override
public Grapher5 from(String sourceInstance)
{
checkState(currentSource == null, "currentSource should be null.");
checkState(all.get(sourceInstance) != null, "%s should exist." , sourceInstance);
currentSource = sourceInstance;
return this;
}
@Override
public Grapher3 to(String targetInstance)
{
checkState(currentTarget == null, "currentTarget should be null.");
checkState(all.get(targetInstance) != null, "%s should exist." , targetInstance);
currentTarget = targetInstance;
currentReference = new reference(currentName, targetInstance , currentSource);
references.add(currentReference);
instancesByName.get(currentSource).references.add(currentReference);
all.put( currentName , currentReference);
// we reinit the whole stuff.
return this;
}
////////////////////////////////////////////////////////
@Override
public Grapher3 withProperty(Object key, Object value)
{
if (currentReference != null)
{
currentReference.properties.put(key, value);
}
if (currentInstance != null )
{
currentInstance.properties.put(key, value);
}
return this;
}
////////////////////////////////////////////////////////
private void clearInstance()
{
currentReference = null;
}
private void clearReference()
{
currentName = currentSource = currentTarget = null;
}
private void checkNotExisting(String name)
{
checkState(all.get(name) == null, "%s already exists.", name);
}
}