blob: 4b625a0d5c63202d43008a3ba070e50c7b3614f9 [file] [log] [blame]
/*
* Copyright (c) 2008, 2009, 2011, 2012, 2015 Eike Stepper (Berlin, Germany) and others.
* 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:
* Andre Dietisheim - initial API and implementation
* Eike Stepper - maintenance
*/
package org.eclipse.net4j.util.defs.impl;
import org.eclipse.net4j.util.defs.Def;
import org.eclipse.net4j.util.defs.Net4jUtilDefsPackage;
import org.eclipse.net4j.util.event.EventUtil;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.impl.EObjectImpl;
import java.util.List;
/**
* <!-- begin-user-doc --> An implementation of the model object ' <em><b>Definition</b></em>'. <!-- end-user-doc -->
* <p>
* </p>
*
* @generated
*/
public abstract class DefImpl extends EObjectImpl implements Def
{
/** The internal instance. */
private Object instance;
/** the touched (dirty) state */
private boolean touched;
/* Lifecycle listener for the internal instance */
protected IListener instanceListener = new LifecycleEventAdapter()
{
@Override
protected void onDeactivated(ILifecycle lifecycle)
{
if (lifecycle == instance)
{
handleDeactivation(instance);
}
}
};
/** adapter that tracks if this def was touched */
protected Adapter touchedAdapter = new AdapterImpl()
{
@Override
public void notifyChanged(Notification msg)
{
switch (msg.getEventType())
{
case Notification.SET:
case Notification.UNSET:
case Notification.ADD:
case Notification.REMOVE:
touched = true;
}
}
};
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->.
*
* @generated NOT
*/
protected DefImpl()
{
super();
eAdapters().add(touchedAdapter);
}
/**
* Gets the internal instance.
*
* @return the internal instance
* @ADDED
*/
public Object getInternalInstance()
{
return instance;
}
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->.
*
* @return the e class
* @generated
*/
@Override
protected EClass eStaticClass()
{
return Net4jUtilDefsPackage.Literals.DEF;
}
/**
* returns an instance that is created for the given definition. Instances are stored and reused. The instance is
* activated before it is returned. A later call to #getInstace
*
* @return the instance that this definition defines
* @see #createInstance()
* @see #wireInstance(Object)
* @see LifecycleUtil#activate(Object)
* @generated NOT
*/
public Object getInstance()
{
synchronized (this)
{
if (!isSetInstance())
{
// instance is not created yet
setInstance();
}
else if (isSetInstance() && isTouched())
{
// instance is created but def settings were changed afterwards
unsetInstance();
setInstance();
}
touched = false;
return instance;
}
}
/**
* @ADDED
*/
private void setInstance()
{
validateDefinition();
instance = createInstance();
wireInstance(instance);
activateInstance(instance);
}
/**
* Activate a given instance.
*
* @param instance
* the instance to activate
* @ADDED
*/
protected void activateInstance(Object instance)
{
LifecycleUtil.activate(instance);
}
/**
* Deactivate a given instance.
*
* @ADDED
*/
protected void deactivateInstance(Object instance)
{
LifecycleUtil.deactivate(instance);
}
/**
* <!-- begin-user-doc -->Unsets the instance managed by this Definition. The internal reference to it is cleared and
* internal listeners to it are removed <!-- end-user-doc -->
*
* @ADDED
*/
public void unsetInstance()
{
deactivateInstance(instance);
}
/**
* Checks if the the instance in this <em>definition</em> is set. In other words, if the instance handled by this
* <em>defintion</em> is present
*
* @return <code>true</code>, if the instance in this definition is set
* @ADDED
*/
public boolean isSetInstance()
{
return instance != null;
}
/**
* Returns whether this definition (and all its nested, referenced defs) was touched since it created its internal
* instance.
*
* @return true, if this definition was touched since it created its internal instance
* @ADDED
*/
public boolean isTouched()
{
if (touched)
{
return touched = true;
}
else
{
touched = areReferencedDefsTouched();
}
return touched;
}
/**
* Returns whether any referenced def is touched
*
* @return true, if there's any referenced def that has been touched
*/
protected boolean areReferencedDefsTouched()
{
boolean touched = false;
for (EStructuralFeature structuralFeature : eClass().getEStructuralFeatures())
{
if (structuralFeature.getEType().eClass() == Net4jUtilDefsPackage.eINSTANCE.getDef().eClass())
{
Object referencedObject = eGet(structuralFeature, true);
if (referencedObject != null)
{
if (structuralFeature.getUpperBound() != -1)
{
if (((Def)referencedObject).isTouched())
{
touched = true;
break;
}
}
else
{
List<?> referenceList = (List<?>)referencedObject;
for (Object reference : referenceList)
{
if (((Def)reference).isTouched())
{
touched = true;
break;
}
}
}
}
}
}
return touched;
}
/**
* @ADDED
*/
protected void wireInstance(Object instance)
{
EventUtil.addListener(instance, instanceListener);
}
/**
* @ADDED
*/
protected void unwireInstance(Object instance)
{
EventUtil.removeListener(instance, instanceListener);
}
/**
* @ADDED
*/
protected void handleDeactivation(Object instance)
{
synchronized (this)
{
unwireInstance(instance);
this.instance = null;
}
}
/**
* validates the present definition. Subclasses have to provide an implementation
*
* @throws IllegalStateException
* @ADDED
*/
protected void validateDefinition()
{
}
/**
* Creates a new instance. Subclasses have to provide an implementation
*
* @return a new instance
* @ADDED
*/
protected abstract Object createInstance();
} // DefinitionImpl