Java tutorial
/* * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * This component and the accompanying materials are made available * under the terms of the License "Eclipse Public License v1.0" * which accompanies this distribution, and is available * at the URL "http://www.eclipse.org/legal/epl-v10.html". * * Initial Contributors: * Nokia Corporation - initial contribution. * * Contributors: * * Description: * */ package com.nokia.carbide.cpp.pi.button; import java.io.File; import java.io.IOException; import java.math.BigDecimal; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.TreeMap; import java.util.Map.Entry; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.EList; import org.eclipse.jface.preference.IPreferenceStore; import com.nokia.carbide.cpp.internal.pi.button.ui.BupPreferenceConstants; import com.nokia.carbide.cpp.internal.pi.util.config.PIConfigXMLLoader; import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileListType; import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.ButtonEventProfileType; import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.MappingType; import com.nokia.carbide.cpp.internal.pi.util.config.gen.PIConfig.PIConfigFactory; import com.nokia.carbide.cpp.pi.util.GeneralMessages; import com.nokia.carbide.cpp.sdk.core.ISymbianSDK; import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin; public class BupEventMapManager { static private IBupEventMapProfile DEFAULT_PROFILE; // this is initialized at constructor, static public is bad static private IBupEventMapProfile TECHVIEW_PROFILE; // this is initialized at constructor, static public is bad static private IBupEventMapProfile S60_PROFILE; // this is initialized at constructor, static public is bad static private IBupEventMapProfile MOAP_PROFILE; // this is initialized at constructor, static public is bad static private IBupEventMapProfile UIQ_PROFILE; // this is initialized at constructor, static public is bad static private IBupEventMapProfile LEGACY_PROFILE; // this is initialized at constructor, static public is bad static private String WORKSPACE_PROFILE_FILENAME = "keymap.xml"; //$NON-NLS-1$ static public String TECHVIEW_PROFILE_ID = "Symbian_TechView"; //$NON-NLS-1$ static public String S60_PROFILE_ID = "S60"; //$NON-NLS-1$ static public String MOAP_PROFILE_ID = "MOAP"; //$NON-NLS-1$ static public String UIQ_PROFILE_ID = "UIQ"; //$NON-NLS-1$ static public String LEGACY_PROFILE_ID = "PI pre-2.0"; //$NON-NLS-1$ static public URI DEFAULT_PROFILE_URI; static public URI WORKSPACE_PREF_KEY_MAP_URI; static private BupEventMapManager instance = null; static HashMap<IBupEventMapProfile, IBupEventMap> loadedKeyMap = new HashMap<IBupEventMapProfile, IBupEventMap>(); private class BupEventMapProfile implements IBupEventMapProfile { String profileId = null; ISymbianSDK sdk = null; URI uri = null; /** * @param profileId ID string for the profile in XML * @param sdk SDK associated, could be null * @param xmlUri URI for the XML file(SDK, workspace pref, built in location) */ public BupEventMapProfile(String profileId, ISymbianSDK sdk, URI xmlURI) { this.profileId = profileId; this.sdk = sdk; this.uri = xmlURI; } /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; BupEventMapProfile other = (BupEventMapProfile) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (profileId == null) { if (other.profileId != null) return false; } else if (!profileId.equals(other.profileId)) return false; if (sdk == null) { if (other.sdk != null) return false; } else if (!sdk.equals(other.sdk)) return false; if (uri == null) { if (other.uri != null) return false; } else if (!uri.equals(other.uri)) return false; return true; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + getOuterType().hashCode(); result = prime * result + ((profileId == null) ? 0 : profileId.hashCode()); result = prime * result + ((sdk == null) ? 0 : sdk.hashCode()); result = prime * result + ((uri == null) ? 0 : uri.hashCode()); return result; } public String toString() { if (sdk == null) { if (uri.equals(DEFAULT_PROFILE_URI)) return profileId + Messages.getString("BupEventMapManager.34"); //$NON-NLS-1$ return profileId + Messages.getString("BupEventMapManager.35"); //$NON-NLS-1$ } else return profileId + Messages.getString("BupEventMapManager.37") + sdk.getUniqueId() //$NON-NLS-1$ + Messages.getString("BupEventMapManager.39"); //$NON-NLS-1$ } public String getProfileId() { return profileId; } public ISymbianSDK getSDK() { return sdk; } public URI getURI() { return uri; } private BupEventMapManager getOuterType() { return BupEventMapManager.this; } } private class BupEventMap implements IBupEventMap { private class MapEntry { String enumString; String label; } private String profileName = null; private IBupEventMapProfile profile = null; private int checkOutCount = 1; // count myself too private TreeMap<Integer, MapEntry> keyCodeMap = new TreeMap<Integer, MapEntry>(); public BupEventMap(ButtonEventProfileType buttonProfileType, IBupEventMapProfile buttonProfile) { profileName = buttonProfileType.getProfileId(); profile = buttonProfile; EList<MappingType> mappingList = buttonProfileType.getMapping(); for (MappingType mapping : mappingList) { addMapping(Long.valueOf(mapping.getKeyCode()).intValue(), mapping.getEnumString(), mapping.getLabel()); } } public int getCheckOutCount() { return checkOutCount; } public void upCheckOutCount() { ++checkOutCount; } public void downCheckOutCount() { --checkOutCount; } public IBupEventMapProfile getProfile() { return profile; } public String getProfileName() { return profileName; } public String getLabel(int keyCode) { MapEntry entry = keyCodeMap.get(keyCode); if (entry == null) { return "" + keyCode; // default is just the decimal value string //$NON-NLS-1$ } return entry.label; } public Set<Integer> getKeyCodeSet() { return keyCodeMap.keySet(); } public String getEnum(int keyCode) { MapEntry entry = keyCodeMap.get(keyCode); if (entry == null) { return ""; //$NON-NLS-1$ } return entry.enumString; } public void addMapping(int keyCode, String enumString, String label) { MapEntry entry = keyCodeMap.get(keyCode); // support override of mapping if (entry == null) { entry = new MapEntry(); keyCodeMap.put(Integer.valueOf(keyCode), entry); } entry.enumString = enumString; entry.label = label; } public void removeMapping(int keyCode) { MapEntry entry = keyCodeMap.get(keyCode); if (entry != null) { keyCodeMap.remove(Integer.valueOf(keyCode)); } } public ButtonEventProfileType toEmfModel() { ButtonEventProfileType profile = PIConfigFactory.E_INSTANCE.createButtonEventProfileType(); profile.setProfileId(getProfileName()); EList<MappingType> mappingList = profile.getMapping(); for (Entry<Integer, MapEntry> entry : keyCodeMap.entrySet()) { MappingType mappingType = PIConfigFactory.E_INSTANCE.createMappingType(); mappingType.setKeyCode(entry.getKey().longValue()); mappingType.setEnumString(entry.getValue().enumString); mappingType.setLabel(entry.getValue().label); mappingList.add(mappingType); } return profile; } } private BupEventMapManager() { // singleton try { DEFAULT_PROFILE_URI = FileLocator .find(ButtonPlugin.getDefault().getBundle(), new Path("/data/default.xml"), null).toURI(); //$NON-NLS-1$ WORKSPACE_PREF_KEY_MAP_URI = new File( ButtonPlugin.getDefault().getStateLocation().append(WORKSPACE_PROFILE_FILENAME).toOSString()) .toURI(); } catch (URISyntaxException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.41")); //$NON-NLS-1$ } ArrayList<IBupEventMapProfile> profiles = getProfilesFromBuiltin(); for (IBupEventMapProfile profile : profiles) { if (profile.getProfileId().equals(TECHVIEW_PROFILE_ID)) { TECHVIEW_PROFILE = profile; } if (profile.getProfileId().equals(S60_PROFILE_ID)) { S60_PROFILE = profile; } if (profile.getProfileId().equals(MOAP_PROFILE_ID)) { MOAP_PROFILE = profile; } if (profile.getProfileId().equals(UIQ_PROFILE_ID)) { UIQ_PROFILE = profile; } if (profile.getProfileId().equals(LEGACY_PROFILE_ID)) { LEGACY_PROFILE = profile; } } DEFAULT_PROFILE = S60_PROFILE; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); // singleton } public static BupEventMapManager getInstance() { if (instance == null) { instance = new BupEventMapManager(); } return instance; } private ArrayList<IBupEventMapProfile> getProfilesFromURI(URI uri, ISymbianSDK sdk) { ArrayList<IBupEventMapProfile> allProfiles = new ArrayList<IBupEventMapProfile>(); ButtonEventProfileListType settings; try { settings = PIConfigXMLLoader.loadPiSettings(uri.toURL()); EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile(); for (ButtonEventProfileType profile : profileList) { allProfiles.add(new BupEventMapProfile(profile.getProfileId(), sdk, uri)); } } catch (MalformedURLException e) { // just skip this file if it failed, sdk relative and hardcoded path should never fail } catch (IOException e) { // just skip this file if it failed, sdk relative and hardcoded path should never fail } return allProfiles; } /** * @return Key press profiles available from built in. */ public ArrayList<IBupEventMapProfile> getProfilesFromBuiltin() { return getProfilesFromURI(DEFAULT_PROFILE_URI, null); } /** * @return Key press profiles available from workspace preference. */ public ArrayList<IBupEventMapProfile> getProfilesFromWorkspacePref() { if (new File(WORKSPACE_PREF_KEY_MAP_URI).exists()) { return getProfilesFromURI(WORKSPACE_PREF_KEY_MAP_URI, null); } else { try { new File(WORKSPACE_PREF_KEY_MAP_URI).createNewFile(); } catch (IOException e) { // just try our best creating new file } return new ArrayList<IBupEventMapProfile>(); } } public String profileLocatationInSDK(ISymbianSDK sdk) { String profileString = sdk.getEPOCROOT(); if (profileString.endsWith(File.separator)) profileString += "epoc32" + File.separator + "data" + File.separator + "pikeymap.xml"; //$NON-NLS-1$" //$NON-NLS-2$" //$NON-NLS-3$" else profileString += File.separator + "epoc32" + File.separator + "data" + File.separator + "pikeymap.xml"; //$NON-NLS-1$" //$NON-NLS-2$" //$NON-NLS-3$" return profileString; } /** * @param sdk Any SDK from devices.xml, null workspace pref * @return Key press profiles available in a SDK. */ public ArrayList<IBupEventMapProfile> getProfilesFromSDK(ISymbianSDK sdk) { File profileFile = new File(profileLocatationInSDK(sdk)); if (!profileFile.exists()) { //$NON-NLS-1$" return new ArrayList<IBupEventMapProfile>(); // just return blank if there is no XML file } return getProfilesFromURI(profileFile.toURI(), sdk); } /** * @return A List of all known good key press profiles available to Carbide. */ public ArrayList<IBupEventMapProfile> getAllProfiles() { ArrayList<IBupEventMapProfile> allProfiles = new ArrayList<IBupEventMapProfile>(); allProfiles.addAll(getProfilesFromBuiltin()); allProfiles.addAll(getProfilesFromWorkspacePref()); List<ISymbianSDK> sdkList = SDKCorePlugin.getSDKManager().getSDKList(); for (ISymbianSDK sdk : sdkList) { allProfiles.addAll(getProfilesFromSDK(sdk)); } return allProfiles; } /** * * We hide mapping profile creation inside BupEventMapManager on purpose, user should * obtain list of profile from BupEventMapManager and use them immediately, this save * us from error handling user specified profile ID unavailable (e.g. removed from SDK) * * @param uid The UID for the instance(e.g. current editor) to bind mapping to. * @param profile The mapping obtain from getProfilesFromSDK/getAllProfiles. * @return The key press map captured. */ public IBupEventMap captureMap(IBupEventMapProfile profile) { synchronized (loadedKeyMap) { IBupEventMap map = loadedKeyMap.get(profile); if (map == null) { try { ButtonEventProfileListType settings = PIConfigXMLLoader .loadPiSettings(profile.getURI().toURL()); EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile(); for (ButtonEventProfileType buttonProfileType : profileList) { if (buttonProfileType.getProfileId().equals(profile.getProfileId())) { map = new BupEventMap(buttonProfileType, profile); loadedKeyMap.put(profile, map); } } } catch (MalformedURLException e) { GeneralMessages .showErrorMessage(Messages.getString("BupEventMapManager.44") + profile.getURI()); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages .showErrorMessage(Messages.getString("BupEventMapManager.45") + profile.getURI()); //$NON-NLS-1$ } if (map == null) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.42") + profile); //$NON-NLS-1$ //$NON-NLS-2$ } } else { ((BupEventMap) map).upCheckOutCount(); } return map; } } /** * Release the key mapping when the UID is going away * * @param uid The UID for the instance you want to release key mapping binding */ public void releaseMap(IBupEventMap map) { synchronized (loadedKeyMap) { if (map != null) { ((BupEventMap) map).downCheckOutCount(); if (((BupEventMap) map).getCheckOutCount() <= 0) { loadedKeyMap.remove(((BupEventMap) map).getProfile()); } } } } public void addToWorkspace(String profileId) { try { ButtonEventProfileListType workspace_settings = PIConfigXMLLoader .loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL()); EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile(); ButtonEventProfileType buttonEventProfileType = PIConfigFactory.E_INSTANCE .createButtonEventProfileType(); buttonEventProfileType.setProfileId(profileId); buttonEventProfileType.getMapping().clear(); workspace_profileList.add(buttonEventProfileType); // write back the model PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL()); } catch (MalformedURLException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.47") + profileId); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.48") + profileId); //$NON-NLS-1$ } } public void removeFromWorkspace(IBupEventMapProfile removedProfile) { synchronized (loadedKeyMap) { try { ButtonEventProfileListType workspace_settings = PIConfigXMLLoader .loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL()); EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile(); // profile with the same ID will replace workspace pref ButtonEventProfileType remove = null; for (ButtonEventProfileType profile : workspace_profileList) { if (profile.getProfileId().equals(removedProfile.getProfileId())) { remove = profile; } } if (remove != null) { int i = workspace_profileList.indexOf(remove); workspace_profileList.remove(i); } // write back the model PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL()); } catch (MalformedURLException e) { GeneralMessages.showErrorMessage( Messages.getString("BupEventMapManager.49") + removedProfile.getProfileId()); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages.showErrorMessage( Messages.getString("BupEventMapManager.50") + removedProfile.getProfileId()); //$NON-NLS-1$ } } } public void commitEditToWorkspace(IBupEventMap map) { synchronized (loadedKeyMap) { try { ButtonEventProfileListType workspace_settings = PIConfigXMLLoader .loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL()); EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile(); // profile with the same ID will replace workspace pref ButtonEventProfileType replace = null; for (ButtonEventProfileType profile : workspace_profileList) { if (profile.getProfileId().equals(map.getProfile().getProfileId())) { replace = profile; } } if (replace != null) { int i = workspace_profileList.indexOf(replace); workspace_profileList.remove(i); workspace_profileList.add(i, map.toEmfModel()); } else { workspace_profileList.add(map.toEmfModel()); } // write back the model PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL()); } catch (MalformedURLException e) { GeneralMessages.showErrorMessage( Messages.getString("BupEventMapManager.51") + map.getProfile().getProfileId()); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages.showErrorMessage( Messages.getString("BupEventMapManager.52") + map.getProfile().getProfileId()); //$NON-NLS-1$ } } } public void importMergeToWorkspace(URI uri) { try { ButtonEventProfileListType workspace_settings = PIConfigXMLLoader .loadPiSettings(WORKSPACE_PREF_KEY_MAP_URI.toURL()); EList<ButtonEventProfileType> workspace_profileList = workspace_settings.getButtonEventProfile(); ButtonEventProfileListType settings = PIConfigXMLLoader.loadPiSettings(uri.toURL()); EList<ButtonEventProfileType> profileList = settings.getButtonEventProfile(); // profile with the same ID will replace workspace pref while (profileList.size() > 0) { ButtonEventProfileType replace = null; for (ButtonEventProfileType profile : workspace_profileList) { if (profile.getProfileId().equals(profileList.get(0).getProfileId())) { replace = profile; } } // containment == true in XML, profileList will remove the element if (replace != null) { int i = workspace_profileList.indexOf(replace); workspace_profileList.remove(i); workspace_profileList.add(i, profileList.get(0)); } else { workspace_profileList.add(profileList.get(0)); } } // write back the model PIConfigXMLLoader.writePiSettings(workspace_settings, WORKSPACE_PREF_KEY_MAP_URI.toURL()); } catch (MalformedURLException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.53") + uri); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.54") + uri); //$NON-NLS-1$ } } public void saveMap(URI uri, ArrayList<ButtonEventProfileType> mapList) { ButtonEventProfileListType profileList = PIConfigFactory.E_INSTANCE.createButtonEventProfileListType(); profileList.setButtonEventProfileVersion(new BigDecimal("1.0")); //$NON-NLS-1$ profileList.getButtonEventProfile().addAll(mapList); try { PIConfigXMLLoader.writePiSettings(profileList, uri.toURL()); } catch (MalformedURLException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.56") + uri); //$NON-NLS-1$ } catch (IOException e) { GeneralMessages.showErrorMessage(Messages.getString("BupEventMapManager.57") + uri); //$NON-NLS-1$ } } /** * @param uri * @return */ public ArrayList<IBupEventMapProfile> getOverLapWithWorkspace(URI uri) { ArrayList<IBupEventMapProfile> result = new ArrayList<IBupEventMapProfile>(); ArrayList<IBupEventMapProfile> uriProfiles = getProfilesFromURI(uri, null); ArrayList<IBupEventMapProfile> workspaceProfiles = getProfilesFromWorkspacePref(); for (IBupEventMapProfile workspaceProfile : workspaceProfiles) { for (IBupEventMapProfile uriProfile : uriProfiles) { if (workspaceProfile.getProfileId().equals(uriProfile.getProfileId())) { result.add(workspaceProfile); } } } return result; } /** * Read from global preference for profile selection * * @return */ public IBupEventMapProfile getPrefSelectedProfile() { IPreferenceStore store = ButtonPlugin.getBupPrefsStore(); String profileID = store.getString(BupPreferenceConstants.KEY_MAP_PROFILE_STRING); if (profileID != null) { ArrayList<IBupEventMapProfile> profiles = getAllProfiles(); for (IBupEventMapProfile profile : profiles) { if (profile.toString().equals(profileID)) { return profile; } } } return DEFAULT_PROFILE; } /** * @param profile * @return */ public boolean canRemoveProfile(IBupEventMapProfile profile) { return loadedKeyMap.get(profile) == null; } /** * @return */ public IBupEventMapProfile getLegacyProfile() { return LEGACY_PROFILE; } /** * @return */ public IBupEventMapProfile getDefaultProfile() { return DEFAULT_PROFILE; } /** * @return */ public IBupEventMapProfile getTechViewProfile() { return TECHVIEW_PROFILE; } /** * @return */ public IBupEventMapProfile getBuiltinS60Profile() { return S60_PROFILE; } }